diff options
author | kan <kan@FreeBSD.org> | 2003-07-11 04:00:23 +0000 |
---|---|---|
committer | kan <kan@FreeBSD.org> | 2003-07-11 04:00:23 +0000 |
commit | 4e7ac24200e18bbd6367139a46c1286294a70474 (patch) | |
tree | c567c233a70a71a655646549c59efb4bd5c61d04 /contrib | |
parent | b664230ac178e69c3c146968ee0c3300a4009f60 (diff) | |
download | FreeBSD-src-4e7ac24200e18bbd6367139a46c1286294a70474.zip FreeBSD-src-4e7ac24200e18bbd6367139a46c1286294a70474.tar.gz |
FreeBSD uses stock versions of these GCC files.
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/gcc/Makefile.in | 1187 | ||||
-rw-r--r-- | contrib/gcc/builtins.c | 578 | ||||
-rw-r--r-- | contrib/gcc/c-common.c | 3549 | ||||
-rw-r--r-- | contrib/gcc/c-tree.h | 154 | ||||
-rw-r--r-- | contrib/gcc/config/alpha/alpha.c | 2046 | ||||
-rw-r--r-- | contrib/gcc/config/i386/i386.md | 5687 | ||||
-rw-r--r-- | contrib/gcc/config/sparc/freebsd.h | 11 | ||||
-rwxr-xr-x | contrib/gcc/configure | 2433 | ||||
-rw-r--r-- | contrib/gcc/cp/except.c | 173 | ||||
-rw-r--r-- | contrib/gcc/dbxout.c | 103 | ||||
-rw-r--r-- | contrib/gcc/dwarfout.c | 237 | ||||
-rw-r--r-- | contrib/gcc/emit-rtl.c | 1818 | ||||
-rw-r--r-- | contrib/gcc/final.c | 544 | ||||
-rw-r--r-- | contrib/gcc/flags.h | 91 | ||||
-rw-r--r-- | contrib/gcc/function.c | 799 | ||||
-rw-r--r-- | contrib/gcc/ginclude/stdarg.h | 15 | ||||
-rw-r--r-- | contrib/gcc/ginclude/varargs.h | 141 | ||||
-rw-r--r-- | contrib/gcc/libgcc2.c | 593 | ||||
-rw-r--r-- | contrib/gcc/print-tree.c | 68 | ||||
-rw-r--r-- | contrib/gcc/recog.c | 376 | ||||
-rw-r--r-- | contrib/gcc/reload.c | 346 |
21 files changed, 13760 insertions, 7189 deletions
diff --git a/contrib/gcc/Makefile.in b/contrib/gcc/Makefile.in index e7c29b9e..75e4d03 100644 --- a/contrib/gcc/Makefile.in +++ b/contrib/gcc/Makefile.in @@ -69,6 +69,13 @@ CFLAGS = -g STAGE1_CFLAGS = -g @stage1_cflags@ BOOT_CFLAGS = -g -O2 +# Flags to determine code coverage. When coverage is disabled, this will +# contain the optimization flags, as you normally want code coverage +# without optimization. The -dumpbase $@ makes sure that the auxilary +# files end up near the object files. +COVERAGE_FLAGS = @coverage_flags@ +coverageexts = .{da,bb,bbg} + # The warning flags are separate from BOOT_CFLAGS because people tend to # override optimization flags and we'd like them to still have warnings # turned on. These flags are also used to pass other stage dependent @@ -85,9 +92,17 @@ LOOSE_WARN = -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes STRICT_WARN = -Wtraditional @strict1_warn@ STRICT2_WARN = -Wtraditional -pedantic -Wno-long-long +# This is set by --enable-checking. The idea is to catch forgotten +# "extern" tags in header files. +NOCOMMON_FLAG = @nocommon_flag@ + +# These are set by --enable-checking=valgrind. +RUN_GEN = @valgrind_command@ +VALGRIND_DRIVER_DEFINES = @valgrind_path_defines@ + # This is how we control whether or not the additional warnings are applied. .-warn = $(STRICT_WARN) -GCC_WARN_CFLAGS = $(LOOSE_WARN) $($(@D)-warn) +GCC_WARN_CFLAGS = $(LOOSE_WARN) $($(@D)-warn) $(NOCOMMON_FLAG) # 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 @@ -101,6 +116,7 @@ T_CFLAGS = X_CPPFLAGS = T_CPPFLAGS = +ADAC = @ADAC@ AWK = @AWK@ CC = @CC@ BISON = @BISON@ @@ -111,7 +127,14 @@ AR = ar AR_FLAGS = rc DLLTOOL = dlltool RANLIB = @RANLIB@ -SHELL = /bin/sh +SHELL = @SHELL@ +# pwd command to use. Allow user to override default by setting PWDCMD in +# the environment to account for automounters. The make variable must not +# be called PWDCMD, otherwise the value set here is passed to make +# subprocesses and overrides the setting from the user's environment. +# Don't use PWD since it is a common shell environment variable and we +# don't want to corrupt it. +PWD_COMMAND = $${PWDCMD-pwd} # on sysV, define this as cp. INSTALL = @INSTALL@ # Some systems may be missing symbolic links, regular links, or both. @@ -154,15 +177,19 @@ 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/stdarg.h $(srcdir)/ginclude/stddef.h \ - $(srcdir)/ginclude/varargs.h \ - $(srcdir)/ginclude/stdbool.h $(srcdir)/ginclude/iso646.h \ - $(EXTRA_HEADERS) - -# The GCC to use for compiling libgcc.a, enquire, and crt*.o. +USER_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) + +# 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). -GCC_FOR_TARGET = ./xgcc -B./ -B$(build_tooldir)/bin/ -isystem $(build_tooldir)/include -isystem $(build_tooldir)/sys-include +GCC_FOR_TARGET = $(STAGE_CC_WRAPPER) ./xgcc -B./ -B$(build_tooldir)/bin/ -isystem $(build_tooldir)/include -isystem $(build_tooldir)/sys-include # This is used instead of ALL_CFLAGS when compiling with GCC_FOR_TARGET. # It omits XCFLAGS, and specifies -B./. @@ -230,6 +257,7 @@ HASHTAB_H = $(srcdir)/../include/hashtab.h 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 # Default native SYSTEM_HEADER_DIR, to be overridden by targets. NATIVE_SYSTEM_HEADER_DIR = /usr/include @@ -253,6 +281,7 @@ tmake_file=@dep_tmake_file@ out_file=$(srcdir)/config/@out_file@ out_object_file=@out_object_file@ md_file=$(srcdir)/config/@md_file@ +tm_defines=@tm_defines@ tm_p_file_list=@tm_p_file_list@ tm_p_file=@tm_p_file@ build_xm_file_list=@build_xm_file_list@ @@ -369,11 +398,12 @@ 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 + -finhibit-size-directive -fno-inline-functions -fno-exceptions \ + -fno-zero-initialized-in-bss # Additional sources to handle exceptions; overridden on ia64. LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \ - $(srcdir)/unwind-sjlj.c + $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h # nm flags to list global symbols in libgcc object files. @@ -415,19 +445,11 @@ LIB2FUNCS_EXTRA = # Assembler files should have names ending in `.asm'. LIB2FUNCS_STATIC_EXTRA = -# Handle cpp installation. -INSTALL_CPP= -UNINSTALL_CPP= - -# We do not try to build float.h anymore. Let configure select the -# appropriate pre-built float.h file for the target. -FLOAT_H=@float_h_file@ - # Program to convert libraries. LIBCONVERT = # Control whether header files are installed. -INSTALL_HEADERS=install-headers +INSTALL_HEADERS=install-headers install-mkheaders # Control whether Info documentation is built and installed. BUILD_INFO = @BUILD_INFO@ @@ -449,7 +471,7 @@ COMPILERS = cc1$(exeext) @all_compilers@ # List of things which should already be built whenever we try to use xgcc # to compile anything (without linking). -GCC_PASSES=xgcc$(exeext) cc1$(exeext) cpp0$(exeext) specs $(EXTRA_PASSES) +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. @@ -461,12 +483,12 @@ 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. -HOST_PREFIX = @HOST_PREFIX@ +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. -HOST_PREFIX_1 = @HOST_PREFIX_1@ +BUILD_PREFIX_1 = @BUILD_PREFIX_1@ # Native compiler for the build machine and its switches. HOST_CC = @HOST_CC@ HOST_CFLAGS= @HOST_CFLAGS@ -DGENERATOR_FILE @@ -533,7 +555,7 @@ all: all.indirect .NOEXPORT: # GCONFIG_H lists the config files that the generator files depend on, while -# CONFIG_H lists the the ones ordinary gcc files depend on, which includes +# CONFIG_H lists the ones ordinary gcc files depend on, which includes # several files generated by those generators. GCONFIG_H = config.h $(host_xm_file_list) HCONFIG_H = hconfig.h $(build_xm_file_list) @@ -541,16 +563,18 @@ CONFIG_H = $(GCONFIG_H) insn-constants.h insn-flags.h TCONFIG_H = tconfig.h $(xm_file_list) TARGET_H = target.h HOOKS_H = hooks.h -LANGHOOKS_DEF_H = langhooks.h $(HOOKS_H) +LANGHOOKS_DEF_H = langhooks-def.h $(HOOKS_H) TARGET_DEF_H = target-def.h $(HOOKS_H) TM_P_H = tm_p.h $(tm_p_file_list) tm-preds.h -MACHMODE_H = machmode.h machmode.def +MACHMODE_H = machmode.h machmode.def @extra_modes_file@ RTL_BASE_H = rtl.h rtl.def $(MACHMODE_H) RTL_H = $(RTL_BASE_H) genrtl.h PARAMS_H = params.h params.def -TREE_H = tree.h real.h tree.def $(MACHMODE_H) tree-check.h version.h builtins.def -BASIC_BLOCK_H = basic-block.h bitmap.h sbitmap.h varray.h +TREE_H = tree.h tree.def $(MACHMODE_H) tree-check.h version.h builtins.def \ + location.h +BASIC_BLOCK_H = basic-block.h bitmap.h sbitmap.h varray.h $(PARTITION_H) \ + hard-reg-set.h DEMANGLE_H = $(srcdir)/../include/demangle.h RECOG_H = recog.h EXPR_H = expr.h @@ -559,10 +583,10 @@ REGS_H = regs.h varray.h $(MACHMODE_H) INTEGRATE_H = integrate.h varray.h LOOP_H = loop.h varray.h bitmap.h GCC_H = gcc.h version.h -GGC_H = ggc.h varray.h +GGC_H = ggc.h varray.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) +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 PREDICT_H = predict.h predict.def @@ -587,8 +611,8 @@ INTERNAL_CFLAGS = -DIN_GCC @CROSS@ # This is the variable actually used when we compile. # If you change this line, you probably also need to change the definition # of HOST_CFLAGS in build-make to match. -ALL_CFLAGS = $(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) \ - $(CFLAGS) $(WARN_CFLAGS) $(XCFLAGS) @DEFS@ +ALL_CFLAGS = $(X_CFLAGS) $(T_CFLAGS) \ + $(CFLAGS) $(INTERNAL_CFLAGS) $(COVERAGE_FLAGS) $(WARN_CFLAGS) $(XCFLAGS) @DEFS@ # Likewise. ALL_CPPFLAGS = $(CPPFLAGS) $(X_CPPFLAGS) $(T_CPPFLAGS) @@ -609,15 +633,24 @@ HOST_LIBDEPS= $(BUILD_LIBIBERTY) # and the system's installed libraries. LIBS = $(INTLLIBS) @LIBS@ $(LIBIBERTY) +# Any system libraries needed just for GNAT. +SYSLIBS = @GNAT_LIBEXC@ + +# Libs needed (at present) just for jcf-dump. +LDEXP_LIB = @LDEXP_LIB@ + # Likewise, for use in the tools that must run on this machine # even if we are cross-building GCC. HOST_LIBS = $(BUILD_LIBIBERTY) -HOST_RTL = $(HOST_PREFIX)rtl.o read-rtl.o $(HOST_PREFIX)bitmap.o \ - $(HOST_PREFIX)ggc-none.o gensupport.o +HOST_RTL = $(BUILD_PREFIX)rtl.o read-rtl.o $(BUILD_PREFIX)bitmap.o \ + $(BUILD_PREFIX)ggc-none.o +HOST_SUPPORT = gensupport.o insn-conditions.o +HOST_EARLY_SUPPORT = gensupport.o dummy-conditions.o -HOST_PRINT = $(HOST_PREFIX)print-rtl.o -HOST_ERRORS = $(HOST_PREFIX)errors.o +HOST_PRINT = print-rtl1.o +HOST_ERRORS = $(BUILD_PREFIX)errors.o +HOST_VARRAY = $(BUILD_PREFIX)varray.o # Specify the directories to be searched for header files. # Both . and srcdir are used, in that order, @@ -704,60 +737,55 @@ CXX_TARGET_OBJS=@cxx_target_objs@ # 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-format.o c-semantics.o \ - c-objc-common.o libcpp.a $(C_TARGET_OBJS) + c-convert.o c-aux-info.o c-common.o c-opts.o c-format.o c-semantics.o \ + c-objc-common.o c-dump.o libcpp.a $(C_TARGET_OBJS) # Language-specific object files for C. -C_OBJS = c-parse.o c-lang.o $(C_AND_OBJC_OBJS) +C_OBJS = c-parse.o c-lang.o c-pretty-print.o $(C_AND_OBJC_OBJS) # Language-independent object files. -OBJS = 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 cfgrtl.o \ - combine.o conflict.o convert.o cse.o cselib.o dbxout.o debug.o dependence.o \ - df.o diagnostic.o doloop.o dominance.o dwarf2asm.o dwarf2out.o dwarfout.o \ - emit-rtl.o except.o explow.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 \ - haifa-sched.o hash.o hashtable.o hooks.o ifcvt.o insn-attrtab.o insn-emit.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 mbchar.o optabs.o params.o predict.o print-rtl.o print-tree.o \ - profile.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 ssa.o ssa-ccp.o ssa-dce.o stmt.o \ - stor-layout.o stringpool.o timevar.o toplev.o tree.o tree-dump.o \ +OBJS = 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 \ + cfgrtl.o combine.o conflict.o convert.o cse.o cselib.o dbxout.o \ + debug.o df.o diagnostic.o doloop.o dominance.o \ + dwarf2asm.o dwarf2out.o dwarfout.o emit-rtl.o except.o explow.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 hashtable.o hooks.o ifcvt.o insn-attrtab.o insn-emit.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 mbchar.o optabs.o params.o predict.o print-rtl.o print-tree.o \ + profile.o ra.o ra-build.o ra-colorize.o ra-debug.o ra-rewrite.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 ssa.o ssa-ccp.o ssa-dce.o stmt.o \ + stor-layout.o stringpool.o timevar.o toplev.o tracer.o tree.o tree-dump.o \ tree-inline.o unroll.o varasm.o varray.o version.o vmsdbgout.o xcoffout.o \ - $(GGC) $(out_object_file) $(EXTRA_OBJS) + et-forest.o $(GGC) $(out_object_file) $(EXTRA_OBJS) BACKEND = main.o libbackend.a -# GEN files are listed separately, so they can be built before doing parallel -# makes for cc1 or cc1plus. Otherwise sequent parallel make attempts to load -# them before rtl.o is compiled. -GEN= genemit$(build_exeext) genoutput$(build_exeext) genrecog$(build_exeext) \ - genextract$(build_exeext) genflags$(build_exeext) gencodes$(build_exeext) \ - genconfig$(build_exeext) genpeep$(build_exeext) gengenrtl$(build_exeext) \ - gencheck$(build_exeext) genpreds$(build_exeext) genconstants$(build_exeext) - # Files to be copied away after each stage in building. STAGESTUFF = *$(objext) 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 \ - s-flags s-config s-codes s-mlib s-under s-genrtl \ - s-output s-recog s-emit s-extract s-peep s-check \ + tree-check.h insn-conditions.c \ + s-flags s-config s-codes s-mlib s-genrtl 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) \ - genrtl.c genrtl.h \ - xgcc$(exeext) cpp$(exeext) cc1$(exeext) cpp0$(exeext) $(EXTRA_PASSES) \ + gengtype$(build_exeext) genconditions$(build_exeext) \ + genrtl.c genrtl.h gt-*.h gtype-*.h gtype-desc.c \ + xgcc$(exeext) cpp$(exeext) cc1$(exeext) $(EXTRA_PASSES) \ $(EXTRA_PARTS) $(EXTRA_PROGRAMS) gcc-cross$(exeext) cc1obj$(exeext) \ - enquire$(exeext) protoize$(exeext) unprotoize$(exeext) \ - specs collect2$(exeext) $(USE_COLLECT2) underscore.c tradcpp0$(exeext) \ + protoize$(exeext) unprotoize$(exeext) \ + specs collect2$(exeext) $(USE_COLLECT2) \ gcov$(exeext) *.[0-9][0-9].* *.[si] libcpp.a libbackend.a libgcc.mk \ $(LANG_STAGESTUFF) @@ -777,17 +805,30 @@ LIB2FUNCS_ST = _eprintf _bb __gcc_bcmp 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 \ _lt_sf _le_sf _unord_sf _si_to_sf _sf_to_si _negate_sf _make_sf \ - _sf_to_df _thenan_sf _sf_to_usi _usi_to_sf + _sf_to_df _sf_to_tf _thenan_sf _sf_to_usi _usi_to_sf DPBIT_FUNCS = _pack_df _unpack_df _addsub_df _mul_df _div_df \ _fpcmp_parts_df _compare_df _eq_df _ne_df _gt_df _ge_df \ _lt_df _le_df _unord_df _si_to_df _df_to_si _negate_df _make_df \ - _df_to_sf _thenan_df _df_to_usi _usi_to_df + _df_to_sf _df_to_tf _thenan_df _df_to_usi _usi_to_df + +TPBIT_FUNCS = _pack_tf _unpack_tf _addsub_tf _mul_tf _div_tf \ + _fpcmp_parts_tf _compare_tf _eq_tf _ne_tf _gt_tf _ge_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 # 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 +# The only suffixes we want for implicit rules are .c and .o, so clear +# the list and add them. This speeds up GNU Make, and allows -r to work. +# For i18n support, we also need .gmo, .po, .pox. +# This must come before the language makefile fragments to allow them to +# add suffixes and rules of their own. +.SUFFIXES: +.SUFFIXES: .c .o .po .pox .gmo + # # Language makefile fragments. @@ -813,11 +854,6 @@ LIB2_DIVMOD_FUNCS = _divdi3 _moddi3 _udivdi3 _umoddi3 _udiv_w_sdiv _udivmoddi4 # End of language makefile fragments. # -# The only suffixes we want for implicit rules are .c and .o, so clear -# the list and add them. This speeds up GNU Make, and allows -r to work. -# For i18n support, we also need .gmo, .po, .pox. -.SUFFIXES: -.SUFFIXES: .c .o .po .pox .gmo Makefile: $(srcdir)/Makefile.in config.status $(srcdir)/version.c \ $(xmake_file) $(tmake_file) $(LANG_MAKEFILES) @@ -833,22 +869,26 @@ tconfig.h: cs-tconfig.h ; @true tm_p.h: cs-tm_p.h ; @true cs-config.h: Makefile - HEADERS="$(host_xm_file)" DEFINES="$(host_xm_defines)" \ + TM_DEFINES="$(tm_defines)" \ + HEADERS="$(host_xm_file)" XM_DEFINES="$(host_xm_defines)" \ TARGET_CPU_DEFAULT="$(target_cpu_default)" \ $(SHELL) $(srcdir)/mkconfig.sh config.h cs-hconfig.h: Makefile - HEADERS="$(build_xm_file)" DEFINES="$(build_xm_defines)" \ + TM_DEFINES="$(tm_defines)" \ + HEADERS="$(build_xm_file)" XM_DEFINES="$(build_xm_defines)" \ TARGET_CPU_DEFAULT="$(target_cpu_default)" \ $(SHELL) $(srcdir)/mkconfig.sh hconfig.h cs-tconfig.h: Makefile - HEADERS="$(xm_file)" DEFINES="$(xm_defines)" \ + TM_DEFINES="$(tm_defines)" \ + HEADERS="$(xm_file)" XM_DEFINES="$(xm_defines)" \ TARGET_CPU_DEFAULT="" \ $(SHELL) $(srcdir)/mkconfig.sh tconfig.h cs-tm_p.h: Makefile - HEADERS="$(tm_p_file)" DEFINES="" TARGET_CPU_DEFAULT="" \ + TM_DEFINES="" \ + HEADERS="$(tm_p_file)" XM_DEFINES="" TARGET_CPU_DEFAULT="" \ $(SHELL) $(srcdir)/mkconfig.sh tm_p.h # Don't automatically run autoconf, since configure.in might be accidentally @@ -865,6 +905,9 @@ 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 @@ -899,8 +942,6 @@ 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. -# Note that we can compile enquire using the cross-compiler just built, -# although we can't run it on this machine. all.cross: native gcc-cross cpp$(exeext) specs \ $(LIBGCC) $(EXTRA_PARTS) lang.all.cross doc # This is what must be made before installing GCC and converting libraries. @@ -914,7 +955,7 @@ native: config.status auto-host.h intl.all build-@POSUB@ $(LANGUAGES) \ $(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(USE_COLLECT2) # Define the names for selecting languages in LANGUAGES. -C c: cc1$(exeext) tradcpp0$(exeext) +C c: cc1$(exeext) PROTO: proto # Tell GNU make these are phony targets. @@ -979,7 +1020,7 @@ xlimits.h: glimits.h limitx.h limity.h LIB2ADD = $(LIB2FUNCS_EXTRA) LIB2ADD_ST = $(LIB2FUNCS_STATIC_EXTRA) -libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) $(LIB2ADD_ST) xgcc$(exeext) +libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) $(LIB2ADD_ST) xgcc$(exeext) specs objext='$(objext)' \ LIB1ASMFUNCS='$(LIB1ASMFUNCS)' \ LIB2FUNCS_1='$(LIB2FUNCS_1)' \ @@ -994,6 +1035,8 @@ libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) $(LIB2ADD_ST) xgcc$(exeext LIB2_DIVMOD_FUNCS='$(LIB2_DIVMOD_FUNCS)' \ DPBIT='$(DPBIT)' \ DPBIT_FUNCS='$(DPBIT_FUNCS)' \ + TPBIT='$(TPBIT)' \ + TPBIT_FUNCS='$(TPBIT_FUNCS)' \ MULTILIBS=`$(GCC_FOR_TARGET) --print-multi-lib` \ EXTRA_MULTILIB_PARTS='$(EXTRA_MULTILIB_PARTS)' \ SHLIB_LINK='$(SHLIB_LINK)' \ @@ -1013,12 +1056,13 @@ libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) $(LIB2ADD_ST) xgcc$(exeext LIBGCC_DEPS = $(GCC_PASSES) $(LANGUAGES) stmp-int-hdrs $(STMP_FIXPROTO) \ libgcc.mk $(srcdir)/libgcc2.c $(TCONFIG_H) \ $(MACHMODE_H) longlong.h gbl-ctors.h config.status stmp-int-hdrs \ - tsystem.h $(FPBIT) $(DPBIT) $(LIB2ADD) $(LIB2ADD_ST) $(LIB2ADDEH) \ - $(LIB2ADDEHDEP) $(EXTRA_PARTS) $(srcdir)/config/$(LIB1ASMSRC) + tsystem.h $(FPBIT) $(DPBIT) $(TPBIT) $(LIB2ADD) \ + $(LIB2ADD_ST) $(LIB2ADDEH) $(LIB2ADDEHDEP) $(EXTRA_PARTS) \ + $(srcdir)/config/$(LIB1ASMSRC) libgcc.a: $(LIBGCC_DEPS) $(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \ - HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \ + BUILD_PREFIX="$(BUILD_PREFIX)" BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \ AR_FOR_TARGET="$(AR_FOR_TARGET)" \ AR_CREATE_FOR_TARGET="$(AR_CREATE_FOR_TARGET)" \ AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" \ @@ -1060,7 +1104,7 @@ s-mlib: $(srcdir)/genmultilib Makefile # Build multiple copies of libgcc.a, one for each target switch. stmp-multilib: $(LIBGCC_DEPS) $(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \ - HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \ + BUILD_PREFIX="$(BUILD_PREFIX)" BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \ AR_FOR_TARGET="$(AR_FOR_TARGET)" \ AR_CREATE_FOR_TARGET="$(AR_CREATE_FOR_TARGET)" \ AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" \ @@ -1132,8 +1176,9 @@ s-crt0: $(CRT0_S) $(MCRT0_S) $(GCC_PASSES) $(CONFIG_H) c-errors.o: c-errors.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) flags.h \ diagnostic.h $(TM_P_H) -c-parse.o : $(srcdir)/c-parse.c $(CONFIG_H) $(TREE_H) c-lex.h $(GGC_H) intl.h \ - $(C_TREE_H) input.h flags.h $(SYSTEM_H) toplev.h output.h $(CPPLIB_H) +c-parse.o : $(srcdir)/c-parse.c $(CONFIG_H) $(TREE_H) $(GGC_H) intl.h \ + $(C_TREE_H) input.h flags.h $(SYSTEM_H) toplev.h output.h $(CPPLIB_H) \ + gt-c-parse.h $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -c $(srcdir)/c-parse.c $(OUTPUT_OPTION) @@ -1155,32 +1200,34 @@ $(srcdir)/c-parse.y: c-parse.in $(SHELL) $(srcdir)/move-if-change tmp-c-parse.y $(srcdir)/c-parse.y c-decl.o : c-decl.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) $(C_TREE_H) \ - $(GGC_H) $(TARGET_H) c-lex.h flags.h function.h output.h $(EXPR_H) \ - debug.h toplev.h intl.h $(TM_P_H) tree-inline.h $(TIMEVAR_H) c-pragma.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) c-pragma.h \ + gt-c-decl.h libfuncs.h except.h c-typeck.o : c-typeck.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \ $(TARGET_H) flags.h intl.h output.h $(EXPR_H) $(RTL_H) toplev.h $(TM_P_H) c-lang.o : c-lang.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \ - langhooks.h langhooks-def.h -c-lex.o : c-lex.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) c-lex.h \ - debug.h $(C_TREE_H) \ + $(GGC_H) langhooks.h $(LANGHOOKS_DEF_H) c-common.h gtype-c.h +c-lex.o : c-lex.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) \ + debug.h $(C_TREE_H) c-common.h real.h \ c-pragma.h input.h intl.h flags.h toplev.h output.h \ mbchar.h $(CPPLIB_H) $(EXPR_H) $(TM_P_H) c-objc-common.o : c-objc-common.c $(CONFIG_H) $(SYSTEM_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 integrate.h $(VARRAY_H) \ - $(GGC_H) + langhooks.h $(GGC_H) gt-c-objc-common.h $(TARGET_H) c-aux-info.o : c-aux-info.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \ flags.h toplev.h -c-convert.o : c-convert.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h toplev.h +c-convert.o : c-convert.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h toplev.h \ + $(C_COMMON_H) c-pragma.o: c-pragma.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) function.h \ - c-pragma.h toplev.h output.h $(GGC_H) $(TM_P_H) $(C_COMMON_H) + c-pragma.h toplev.h output.h $(GGC_H) $(TM_P_H) $(C_COMMON_H) gt-c-pragma.h mbchar.o: mbchar.c $(CONFIG_H) $(SYSTEM_H) mbchar.h graph.o: graph.c $(CONFIG_H) $(SYSTEM_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) $(RTL_H) flags.h hard-reg-set.h \ $(BASIC_BLOCK_H) -COLLECT2_OBJS = collect2.o tlink.o hash.o intl.o underscore.o version.o +COLLECT2_OBJS = collect2.o tlink.o intl.o version.o COLLECT2_LIBS = @COLLECT2_LIBS@ collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS) # Don't try modifying collect2 (aka ld) in place--it might be linking this. @@ -1194,44 +1241,36 @@ collect2.o : collect2.c $(CONFIG_H) $(SYSTEM_H) gstab.h intl.h \ -DTARGET_MACHINE=\"$(target_alias)\" \ -c $(srcdir)/collect2.c $(OUTPUT_OPTION) -tlink.o: tlink.c $(DEMANGLE_H) hash.h $(CONFIG_H) $(SYSTEM_H) collect2.h intl.h -hash.o: hash.c hash.h $(SYSTEM_H) toplev.h $(GCONFIG_H) - $(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION) - -underscore.c: s-under ; @true - -s-under: $(GCC_PASSES) - echo "int xxy_us_dummy;" >tmp-dum.c - $(GCC_FOR_TARGET) -S tmp-dum.c - echo '/*WARNING: This file is automatically generated!*/' >tmp-under.c - if grep _xxy_us_dummy tmp-dum.s > /dev/null ; then \ - echo "int prepends_underscore = 1;" >>tmp-under.c; \ - else \ - echo "int prepends_underscore = 0;" >>tmp-under.c; \ - fi - $(SHELL) $(srcdir)/move-if-change tmp-under.c underscore.c - -rm -f tmp-dum.c tmp-dum.s - $(STAMP) s-under +tlink.o: tlink.c $(DEMANGLE_H) $(HASHTAB_H) $(CONFIG_H) $(SYSTEM_H) \ + $(OBSTACK_H) collect2.h intl.h # A file used by all variants of C. c-common.o : c-common.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(OBSTACK_H) \ $(C_COMMON_H) flags.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \ $(EXPR_H) $(TM_P_H) builtin-types.def builtin-attrs.def $(TARGET_H) \ - diagnostic.h tree-inline.h $(LANGHOOKS_DEF_H) + diagnostic.h except.h gt-c-common.h real.h langhooks.h c-tree.h +c-pretty-print.o : c-pretty-print.c c-pretty-print.h pretty-print.h \ + $(C_COMMON_H) $(CONFIG_H) $(SYSTEM_H) real.h + +c-opts.o : c-opts.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_COMMON_H) \ + c-pragma.h flags.h toplev.h langhooks.h tree-inline.h diagnostic.h \ + intl.h # A file used by all variants of C and some other languages. -attribs.o : attribs.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(OBSTACK_H) flags.h \ +attribs.o : attribs.c $(CONFIG_H) $(SYSTEM_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) + builtin-types.def $(TARGET_H) langhooks.h -c-format.o : c-format.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \ +c-format.o : c-format.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) langhooks.h \ $(C_COMMON_H) flags.h toplev.h intl.h diagnostic.h c-semantics.o : c-semantics.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \ - c-lex.h flags.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \ - $(EXPR_H) + flags.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \ + $(EXPR_H) $(PREDICT_H) + +c-dump.o : c-dump.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) tree-dump.h # Language-independent files. @@ -1242,6 +1281,7 @@ DRIVER_DEFINES = \ -DDEFAULT_TARGET_MACHINE=\"$(target_alias)\" \ -DSTANDARD_BINDIR_PREFIX=\"$(bindir)/\" \ -DTOOLDIR_BASE_PREFIX=\"$(unlibsubdir)/../\" \ + $(VALGRIND_DRIVER_DEFINES) \ `test "X$${SHLIB_LINK}" = "X" || test "@enable_shared@" != "yes" || echo "-DENABLE_SHARED_LIBGCC"` \ `test "X$${SHLIB_MULTILIB}" = "X" || echo "-DNO_SHARED_LIBGCC_MULTILIB"` @@ -1264,7 +1304,7 @@ cppspec.o: cppspec.c $(CONFIG_H) $(SYSTEM_H) $(GCC_H) tree-check.h: s-check ; @true s-check : gencheck$(build_exeext) $(srcdir)/move-if-change - ./gencheck$(build_exeext) > tmp-check.h + $(RUN_GEN) ./gencheck$(build_exeext) > tmp-check.h $(SHELL) $(srcdir)/move-if-change tmp-check.h tree-check.h $(STAMP) s-check @@ -1305,17 +1345,23 @@ dumpvers: dumpvers.c version.o: version.c version.h +gtype-desc.o: gtype-desc.c $(CONFIG_H) $(SYSTEM_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 \ + ssa.h cselib.h insn-addr.h + ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \ - flags.h $(GGC_H) varray.h hash.h $(HASHTAB_H) $(TM_P_H) + flags.h $(GGC_H) varray.h $(HASHTAB_H) $(TM_P_H) langhooks.h \ + $(PARAMS_H) ggc-simple.o: ggc-simple.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \ - $(GGC_H) varray.h $(TIMEVAR_H) $(TM_P_H) + $(GGC_H) varray.h $(TIMEVAR_H) $(TM_P_H) $(PARAMS_H) ggc-page.o: ggc-page.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \ - toplev.h $(GGC_H) varray.h $(TIMEVAR_H) $(TM_P_H) + toplev.h $(GGC_H) $(TIMEVAR_H) $(TM_P_H) stringpool.o: stringpool.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(OBSTACK_H) \ - flags.h toplev.h + flags.h toplev.h $(GGC_H) hashtable.o: hashtable.c hashtable.h $(CONFIG_H) $(SYSTEM_H) $(OBSTACK_H) @@ -1329,13 +1375,15 @@ prefix.o: prefix.c $(CONFIG_H) $(SYSTEM_H) Makefile prefix.h -DPREFIX=\"$(prefix)\" \ -c $(srcdir)/prefix.c $(OUTPUT_OPTION) -convert.o: convert.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h convert.h toplev.h +convert.o: convert.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h convert.h \ + toplev.h langhooks.h langhooks.o : langhooks.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) toplev.h \ tree-inline.h $(RTL_H) insn-config.h integrate.h langhooks.h \ $(LANGHOOKS_DEF_H) flags.h tree.o : tree.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h function.h toplev.h \ - $(GGC_H) $(HASHTAB_H) $(TARGET_H) output.h $(TM_P_H) langhooks.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) $(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 @@ -1344,21 +1392,22 @@ tree-inline.o : tree-inline.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) \ $(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) toplev.h langhooks.h \ $(C_COMMON_H) tree-inline.h print-tree.o : print-tree.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(GGC_H) \ - langhooks.h + langhooks.h real.h stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h \ - function.h $(EXPR_H) $(RTL_H) toplev.h $(GGC_H) $(TM_P_H) $(TARGET_H) -fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h \ - toplev.h $(HASHTAB_H) $(EXPR_H) $(RTL_H) $(GGC_H) $(TM_P_H) + function.h $(EXPR_H) $(RTL_H) toplev.h $(GGC_H) $(TM_P_H) $(TARGET_H) \ + langhooks.h +fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_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 diagnostic.def \ $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_P_H) flags.h $(GGC_H) \ - input.h toplev.h intl.h + input.h toplev.h intl.h langhooks.h $(LANGHOOKS_DEF_H) toplev.o : toplev.c $(CONFIG_H) $(SYSTEM_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) $(lang_options_files) \ - ssa.h $(PARAMS_H) $(TM_P_H) reload.h dwarf2asm.h $(TARGET_H) halfpic.h \ - langhooks.h insn-flags.h options.h + ssa.h $(PARAMS_H) $(TM_P_H) reload.h dwarf2asm.h $(TARGET_H) \ + langhooks.h insn-flags.h options.h cfglayout.h real.h $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -DTARGET_NAME=\"$(target_alias)\" \ -c $(srcdir)/toplev.c $(OUTPUT_OPTION) @@ -1370,69 +1419,73 @@ rtl-error.o: rtl-error.c system.h $(RTL_H) $(INSN_ATTR_H) insn-config.h \ rtl.o : rtl.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) real.h $(GGC_H) errors.h $(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION) -print-rtl.o : print-rtl.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \ - hard-reg-set.h $(BASIC_BLOCK_H) - $(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION) +print-rtl.o : print-rtl.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \ + hard-reg-set.h $(BASIC_BLOCK_H) real.h +rtlanal.o : rtlanal.c $(CONFIG_H) $(SYSTEM_H) toplev.h $(RTL_H) \ + hard-reg-set.h $(TM_P_H) insn-config.h $(RECOG_H) real.h flags.h -rtlanal.o : rtlanal.c $(CONFIG_H) $(SYSTEM_H) toplev.h $(RTL_H) hard-reg-set.h $(TM_P_H) errors.o : errors.c $(GCONFIG_H) $(SYSTEM_H) errors.h $(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION) varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) flags.h \ - function.h $(EXPR_H) hard-reg-set.h $(REGS_H) $(OBSTACK_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 + $(HASHTAB_H) $(TARGET_H) langhooks.h gt-varasm.h real.h function.o : function.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \ function.h $(EXPR_H) libfuncs.h $(REGS_H) hard-reg-set.h \ - insn-config.h $(RECOG_H) output.h toplev.h except.h hash.h $(GGC_H) \ - $(TM_P_H) langhooks.h + insn-config.h $(RECOG_H) output.h toplev.h except.h $(HASHTAB_H) $(GGC_H) \ + $(TM_P_H) langhooks.h gt-function.h stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_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) + $(LOOP_H) $(RECOG_H) toplev.h output.h varray.h $(GGC_H) $(TM_P_H) \ + langhooks.h $(PREDICT_H) gt-stmt.h except.o : except.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \ - except.h function.h $(EXPR_H) libfuncs.h integrate.h \ + except.h function.h $(EXPR_H) libfuncs.h integrate.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) + dwarf2asm.h dwarf2out.h toplev.h $(HASHTAB_H) intl.h $(GGC_H) \ + gt-except.h expr.o : expr.c $(CONFIG_H) $(SYSTEM_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) + except.h reload.h $(GGC_H) langhooks.h intl.h $(TM_P_H) real.h builtins.o : builtins.c $(CONFIG_H) $(SYSTEM_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 -calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h $(EXPR_H) \ - libfuncs.h $(REGS_H) toplev.h output.h function.h $(TIMEVAR_H) $(TM_P_H) + except.h $(TM_P_H) $(PREDICT_H) libfuncs.h real.h langhooks.h +calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \ + $(EXPR_H) langhooks.h $(TARGET_H) \ + libfuncs.h $(REGS_H) toplev.h output.h function.h $(TIMEVAR_H) $(TM_P_H) \ + except.h expmed.o : expmed.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \ insn-config.h $(EXPR_H) $(OPTABS_H) $(RECOG_H) real.h \ - toplev.h $(TM_P_H) + toplev.h $(TM_P_H) langhooks.h explow.o : explow.c $(CONFIG_H) $(SYSTEM_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) + toplev.h function.h ggc.h $(TM_P_H) gt-explow.h optabs.o : optabs.c $(CONFIG_H) $(SYSTEM_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 hard-reg-set.h $(BASIC_BLOCK_H) + toplev.h $(GGC_H) real.h $(TM_P_H) except.h gt-optabs.h $(BASIC_BLOCK_H) dbxout.o : dbxout.c $(CONFIG_H) $(SYSTEM_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 -debug.o : debug.c $(CONFIG_H) $(SYSTEM_H) +debug.o : debug.c debug.h $(CONFIG_H) $(SYSTEM_H) sdbout.o : sdbout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) flags.h \ function.h $(EXPR_H) output.h hard-reg-set.h $(REGS_H) real.h \ - insn-config.h $(OBSTACK_H) xcoffout.h c-pragma.h ggc.h \ - sdbout.h toplev.h $(TM_P_H) except.h debug.h + insn-config.h xcoffout.h c-pragma.h ggc.h \ + sdbout.h toplev.h $(TM_P_H) except.h debug.h langhooks.h gt-sdbout.h dwarfout.o : dwarfout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) dwarf.h \ flags.h insn-config.h reload.h output.h toplev.h $(TM_P_H) \ debug.h langhooks.h dwarf2out.o : dwarf2out.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) dwarf2.h \ - debug.h flags.h insn-config.h reload.h output.h diagnostic.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 + $(GGC_H) except.h dwarf2asm.h $(TM_P_H) langhooks.h $(HASHTAB_H) gt-dwarf2out.h dwarf2asm.o : dwarf2asm.c $(CONFIG_H) $(SYSTEM_H) flags.h $(RTL_H) $(TREE_H) \ - output.h dwarf2asm.h $(TM_P_H) + output.h dwarf2asm.h $(TM_P_H) $(GGC_H) vmsdbgout.o : vmsdbgout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) flags.h \ - output.h vmsdbg.h debug.h langhooks.h + output.h vmsdbg.h debug.h langhooks.h function.h xcoffout.o : xcoffout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) xcoffout.h \ - flags.h toplev.h output.h dbxout.h $(GGC_H) + flags.h toplev.h output.h dbxout.h $(GGC_H) $(TARGET_H) emit-rtl.o : emit-rtl.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \ function.h $(REGS_H) insn-config.h $(RECOG_H) real.h $(GGC_H) \ $(EXPR_H) $(srcdir)/../include/obstack.h hard-reg-set.h bitmap.h toplev.h \ @@ -1441,23 +1494,23 @@ real.o : real.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) toplev.h $(TM_P_H) integrate.o : integrate.c $(CONFIG_H) $(SYSTEM_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) + $(PARAMS_H) $(TM_P_H) $(TARGET_H) langhooks.h gt-integrate.h jump.o : jump.c $(CONFIG_H) $(SYSTEM_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) simplify-rtx.o : simplify-rtx.c $(CONFIG_H) $(SYSTEM_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) + output.h function.h $(GGC_H) $(OBSTACK_H) $(TM_P_H) $(TREE_H) cselib.o : cselib.c $(CONFIG_H) $(SYSTEM_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) $(OBSTACK_H) $(TM_P_H) + output.h function.h cselib.h $(GGC_H) $(TM_P_H) gt-cselib.h cse.o : cse.c $(CONFIG_H) $(SYSTEM_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) + $(BASIC_BLOCK_H) $(GGC_H) $(TM_P_H) $(TIMEVAR_H) gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_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 + function.h output.h toplev.h $(TM_P_H) $(PARAMS_H) except.h gt-gcse.h sibcall.o : sibcall.c $(CONFIG_H) $(SYSTEM_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) \ @@ -1466,7 +1519,7 @@ resource.o : resource.c $(CONFIG_H) $(RTL_H) hard-reg-set.h $(SYSTEM_H) \ lcm.o : lcm.c $(CONFIG_H) $(SYSTEM_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 -ssa.o : ssa.c $(CONFIG_H) $(SYSTEM_H) $(REGS_H) varray.h $(EXPR_H) \ +ssa.o : ssa.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) varray.h $(EXPR_H) \ hard-reg-set.h flags.h function.h real.h insn-config.h $(RECOG_H) \ $(BASIC_BLOCK_H) output.h ssa.h ssa-dce.o : ssa-dce.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) hard-reg-set.h \ @@ -1481,7 +1534,8 @@ conflict.o : conflict.c $(CONFIG_H) $(SYSTEM_H) $(OBSTACK_H) $(HASHTAB_H) \ $(RTL_H) hard-reg-set.h $(BASIC_BLOCK_H) profile.o : profile.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \ insn-config.h output.h $(REGS_H) $(EXPR_H) function.h \ - gcov-io.h toplev.h $(GGC_H) hard-reg-set.h $(BASIC_BLOCK_H) $(TARGET_H) + gcov-io.h toplev.h $(GGC_H) hard-reg-set.h $(BASIC_BLOCK_H) $(TARGET_H) \ + langhooks.h profile.h libfuncs.h gt-profile.h loop.o : loop.c $(CONFIG_H) $(SYSTEM_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 \ @@ -1490,7 +1544,7 @@ doloop.o : doloop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h $(LOOP_H) \ $(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) $(TM_P_H) toplev.h unroll.o : unroll.c $(CONFIG_H) $(SYSTEM_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) + hard-reg-set.h varray.h $(BASIC_BLOCK_H) $(TM_P_H) $(PREDICT_H) $(PARAMS_H) flow.o : flow.c $(CONFIG_H) $(SYSTEM_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) ssa.h $(GGC_H) $(TM_P_H) @@ -1499,19 +1553,20 @@ cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h insn-config.h \ function.h except.h $(GGC_H) $(TM_P_H) cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_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) + function.h except.h $(GGC_H) $(TM_P_H) insn-config.h cfganal.o : cfganal.c $(CONFIG_H) $(SYSTEM_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) $(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) + function.h except.h $(GGC_H) cfgcleanup.o : cfgcleanup.c $(CONFIG_H) $(SYSTEM_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) + $(GGC_H) insn-config.h cselib.h $(TARGET_H) $(TM_P_H) $(PARAMS_H) cfgloop.o : cfgloop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \ $(BASIC_BLOCK_H) hard-reg-set.h dominance.o : dominance.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) hard-reg-set.h \ - $(BASIC_BLOCK_H) + $(BASIC_BLOCK_H) et-forest.h +et-forest.o : et-forest.c $(CONFIG_H) $(SYSTEM_H) et-forest.h combine.o : combine.c $(CONFIG_H) $(SYSTEM_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) @@ -1521,14 +1576,27 @@ regclass.o : regclass.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) hard-reg-set.h flags.h local-alloc.o : local-alloc.c $(CONFIG_H) $(SYSTEM_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 $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h $(BASIC_BLOCK_H) \ - $(REGS_H) +bitmap.o : bitmap.c $(GCONFIG_H) $(SYSTEM_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) $(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) varray.h $(RTL_H) $(TREE_H) bitmap.h \ - errors.h +varray.o : varray.c $(CONFIG_H) $(SYSTEM_H) varray.h $(GGC_H) errors.h +ra.o : ra.c $(CONFIG_H) $(SYSTEM_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) $(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) $(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) $(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) $(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) $(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) @@ -1544,7 +1612,8 @@ reorg.o : reorg.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) conditions.h hard-reg-set.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) $(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 + $(GGC_H) function.h cselib.h $(TREE_H) $(TM_P_H) langhooks.h $(TARGET_H) \ + gt-alias.h regmove.o : regmove.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) insn-config.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 @@ -1556,28 +1625,33 @@ sched-deps.o : sched-deps.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) sched-int.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) $(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) + $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(TM_P_H) $(TARGET_H) sched-ebb.o : sched-ebb.c $(CONFIG_H) $(SYSTEM_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) sched-vis.o : sched-vis.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) sched-int.h \ - hard-reg-set.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(REGS_H) $(TM_P_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) $(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 \ + real.h output.h hard-reg-set.h except.h debug.h xcoffout.h profile.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) $(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) $(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) + varray.h function.h $(TM_P_H) $(GGC_H) gt-reg-stack.h predict.o: predict.c $(CONFIG_H) $(SYSTEM_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) + $(RECOG_H) function.h except.h $(EXPR_H) $(TM_P_H) $(PREDICT_H) real.h \ + $(PARAMS_H) $(TARGET_H) lists.o: lists.c $(CONFIG_H) $(SYSTEM_H) toplev.h $(RTL_H) $(GGC_H) bb-reorder.o : bb-reorder.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \ flags.h $(BASIC_BLOCK_H) hard-reg-set.h output.h cfglayout.h $(TARGET_H) +tracer.o : tracer.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \ + $(BASIC_BLOCK_H) hard-reg-set.h output.h cfglayout.h flags.h \ + $(PARAMS_H) profile.h cfglayout.o : cfglayout.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \ insn-config.h $(BASIC_BLOCK_H) hard-reg-set.h output.h function.h \ cfglayout.h @@ -1587,9 +1661,7 @@ regrename.o : regrename.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) insn-config.h \ resource.h $(OBSTACK_H) flags.h $(TM_P_H) ifcvt.o : ifcvt.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) toplev.h \ flags.h insn-config.h function.h $(RECOG_H) $(BASIC_BLOCK_H) $(EXPR_H) \ - output.h except.h $(TM_P_H) -dependence.o : dependence.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \ - $(C_COMMON_H) flags.h varray.h $(EXPR_H) + output.h except.h $(TM_P_H) real.h params.o : params.c $(CONFIG_H) $(SYSTEM_H) $(PARAMS_H) toplev.h hooks.o: hooks.c $(CONFIG_H) $(SYSTEM_H) $(HOOKS_H) @@ -1612,9 +1684,6 @@ mips-tdump: mips-tdump.o version.o $(LIBDEPS) mips-tdump.o : mips-tdump.c $(CONFIG_H) $(RTL_H) $(SYSTEM_H) -# Build file to support OSF/rose half-pic format. -halfpic.o: halfpic.c $(CONFIG_H) $(RTL_H) $(TREE_H) $(SYSTEM_H) halfpic.h - # # Generate header and source files from the machine description, # and compile them. @@ -1644,25 +1713,40 @@ halfpic.o: halfpic.c $(CONFIG_H) $(RTL_H) $(TREE_H) $(SYSTEM_H) halfpic.h insn-config.h: s-config ; @true s-config : $(md_file) genconfig$(build_exeext) $(srcdir)/move-if-change - ./genconfig$(build_exeext) $(md_file) > tmp-config.h + $(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-conditions.o : insn-conditions.c $(GCONFIG_H) $(SYSTEM_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 + $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) insn-conditions.c + +dummy-conditions.o : dummy-conditions.c $(HCONFIG_H) $(SYSTEM_H) gensupport.h + $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \ + $(srcdir)/dummy-conditions.c $(OUTPUT_OPTION) + insn-flags.h: s-flags ; @true s-flags : $(md_file) genflags$(build_exeext) $(srcdir)/move-if-change - ./genflags$(build_exeext) $(md_file) > tmp-flags.h + $(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 - ./gencodes$(build_exeext) $(md_file) > tmp-codes.h + $(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 - ./genconstants$(build_exeext) $(md_file) > tmp-constants.h + $(RUN_GEN) ./genconstants$(build_exeext) $(md_file) > tmp-constants.h $(SHELL) $(srcdir)/move-if-change tmp-constants.h insn-constants.h $(STAMP) s-constants @@ -1674,7 +1758,7 @@ insn-emit.o : insn-emit.c $(CONFIG_H) $(RTL_H) $(EXPR_H) real.h output.h \ insn-emit.c: s-emit ; @true s-emit : $(md_file) genemit$(build_exeext) $(srcdir)/move-if-change - ./genemit$(build_exeext) $(md_file) > tmp-emit.c + $(RUN_GEN) ./genemit$(build_exeext) $(md_file) > tmp-emit.c $(SHELL) $(srcdir)/move-if-change tmp-emit.c insn-emit.c $(STAMP) s-emit @@ -1686,7 +1770,7 @@ insn-recog.o : insn-recog.c $(CONFIG_H) $(RTL_H) insn-config.h $(RECOG_H) \ insn-recog.c: s-recog ; @true s-recog : $(md_file) genrecog$(build_exeext) $(srcdir)/move-if-change - ./genrecog$(build_exeext) $(md_file) > tmp-recog.c + $(RUN_GEN) ./genrecog$(build_exeext) $(md_file) > tmp-recog.c $(SHELL) $(srcdir)/move-if-change tmp-recog.c insn-recog.c $(STAMP) s-recog @@ -1697,7 +1781,7 @@ insn-opinit.o : insn-opinit.c $(CONFIG_H) $(RTL_H) \ insn-opinit.c: s-opinit ; @true s-opinit : $(md_file) genopinit$(build_exeext) $(srcdir)/move-if-change - ./genopinit$(build_exeext) $(md_file) > tmp-opinit.c + $(RUN_GEN) ./genopinit$(build_exeext) $(md_file) > tmp-opinit.c $(SHELL) $(srcdir)/move-if-change tmp-opinit.c insn-opinit.c $(STAMP) s-opinit @@ -1708,7 +1792,7 @@ insn-extract.o : insn-extract.c $(CONFIG_H) $(RTL_H) $(SYSTEM_H) toplev.h \ insn-extract.c: s-extract ; @true s-extract : $(md_file) genextract$(build_exeext) $(srcdir)/move-if-change - ./genextract$(build_exeext) $(md_file) > tmp-extract.c + $(RUN_GEN) ./genextract$(build_exeext) $(md_file) > tmp-extract.c $(SHELL) $(srcdir)/move-if-change tmp-extract.c insn-extract.c $(STAMP) s-extract @@ -1719,7 +1803,7 @@ insn-peep.o : insn-peep.c $(CONFIG_H) $(RTL_H) $(REGS_H) output.h real.h \ insn-peep.c: s-peep ; @true s-peep : $(md_file) genpeep$(build_exeext) $(srcdir)/move-if-change - ./genpeep$(build_exeext) $(md_file) > tmp-peep.c + $(RUN_GEN) ./genpeep$(build_exeext) $(md_file) > tmp-peep.c $(SHELL) $(srcdir)/move-if-change tmp-peep.c insn-peep.c $(STAMP) s-peep @@ -1731,13 +1815,13 @@ insn-attrtab.o : insn-attrtab.c $(CONFIG_H) $(RTL_H) $(REGS_H) real.h \ insn-attr.h: s-attr ; @true s-attr : $(md_file) genattr$(build_exeext) $(srcdir)/move-if-change - ./genattr$(build_exeext) $(md_file) > tmp-attr.h + $(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 - ./genattrtab$(build_exeext) $(md_file) > tmp-attrtab.c + $(RUN_GEN) ./genattrtab$(build_exeext) $(md_file) > tmp-attrtab.c $(SHELL) $(srcdir)/move-if-change tmp-attrtab.c insn-attrtab.c $(STAMP) s-attrtab @@ -1750,7 +1834,7 @@ insn-output.o : insn-output.c $(CONFIG_H) $(RTL_H) $(GGC_H) $(REGS_H) real.h \ insn-output.c: s-output ; @true s-output : $(md_file) genoutput$(build_exeext) $(srcdir)/move-if-change - ./genoutput$(build_exeext) $(md_file) > tmp-output.c + $(RUN_GEN) ./genoutput$(build_exeext) $(md_file) > tmp-output.c $(SHELL) $(srcdir)/move-if-change tmp-output.c insn-output.c $(STAMP) s-output @@ -1759,19 +1843,83 @@ genrtl.c genrtl.h : s-genrtl @true # force gnu make to recheck modification times. s-genrtl: gengenrtl$(build_exeext) $(srcdir)/move-if-change $(RTL_BASE_H) - ./gengenrtl$(build_exeext) -h > tmp-genrtl.h + $(RUN_GEN) ./gengenrtl$(build_exeext) -h > tmp-genrtl.h $(SHELL) $(srcdir)/move-if-change tmp-genrtl.h genrtl.h - ./gengenrtl$(build_exeext) > tmp-genrtl.c + $(RUN_GEN) ./gengenrtl$(build_exeext) > tmp-genrtl.c $(SHELL) $(srcdir)/move-if-change tmp-genrtl.c genrtl.c $(STAMP) s-genrtl tm-preds.h: s-preds; @true s-preds: genpreds$(build_exeext) $(srcdir)/move-if-change - ./genpreds$(build_exeext) > tmp-preds.h + $(RUN_GEN) ./genpreds$(build_exeext) > tmp-preds.h $(SHELL) $(srcdir)/move-if-change tmp-preds.h tm-preds.h $(STAMP) s-preds +GTFILES = $(GCONFIG_H) $(srcdir)/location.h \ + $(HASHTAB_H) \ + $(srcdir)/bitmap.h $(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)/ssa.h $(srcdir)/insn-addr.h $(srcdir)/cselib.h \ + $(srcdir)/c-common.h $(srcdir)/c-tree.h \ + $(srcdir)/basic-block.h \ + $(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c \ + $(srcdir)/dwarf2out.c $(srcdir)/emit-rtl.c \ + $(srcdir)/except.c $(srcdir)/explow.c $(srcdir)/expr.c \ + $(srcdir)/fold-const.c $(srcdir)/function.c \ + $(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)/sdbout.c $(srcdir)/stmt.c $(srcdir)/stor-layout.c \ + $(srcdir)/tree.c $(srcdir)/varasm.c \ + $(out_file) \ + @all_gtfiles@ + +GTFILES_FILES_LANGS = @all_gtfiles_files_langs@ +GTFILES_FILES_FILES = @all_gtfiles_files_files@ +GTFILES_LANG_DIR_NAMES = @subdirs@ +GTFILES_SRCDIR = @srcdir@ + +gtype-desc.h gtype-desc.c gt-except.h gt-function.h : s-gtype; @true +gt-integrate.h gt-stmt.h gt-tree.h gt-varasm.h gt-emit-rtl.h : s-gtype; @true +gt-explow.h gt-stor-layout.h gt-regclass.h gt-lists.h : s-gtype; @true +gt-alias.h gt-cselib.h gt-fold-const.h gt-gcse.h gt-profile.h : s-gtype; @true +gt-expr.h gt-sdbout.h gt-optabs.h gt-bitmap.h gt-dwarf2out.h : s-gtype ; @true +gt-ra-build.h gt-reg-stack.h : s-gtype ; @true +gt-c-common.h gt-c-decl.h gt-c-parse.h gt-c-pragma.h : s-gtype; @true +gt-c-objc-common.h gtype-c.h gt-location.h : s-gtype ; @true + +gtyp-gen.h: Makefile + echo "/* This file is machine generated. Do not edit. */" > tmp-gtyp.h + echo "static const char *srcdir = " >> tmp-gtyp.h + echo "\"$(GTFILES_SRCDIR)\"" >> tmp-gtyp.h + echo ";" >> tmp-gtyp.h + echo "static const char *lang_files[] = {" >> tmp-gtyp.h + ll="$(GTFILES_FILES_FILES)"; \ + for f in $$ll; do \ + echo "\"$$f\", "; done >> tmp-gtyp.h + echo "NULL};" >> tmp-gtyp.h + echo "static const char *langs_for_lang_files[] = {" >> tmp-gtyp.h + ff="$(GTFILES_FILES_LANGS)"; \ + for f in $$ff; do \ + echo "\"$$f\", " ; done >> tmp-gtyp.h + echo "NULL};" >> tmp-gtyp.h + echo "static const char *all_files[] = {" >> tmp-gtyp.h + gf="$(GTFILES)"; \ + for f in $$gf; do \ + echo "\"$$f\", "; done >> tmp-gtyp.h + echo " NULL};" >> tmp-gtyp.h + echo "static const char *lang_dir_names[] = { \"c\", " >> tmp-gtyp.h + gf="$(GTFILES_LANG_DIR_NAMES)"; \ + for l in $$gf; do \ + echo "\"$$l\", "; done >> tmp-gtyp.h + echo "NULL};" >> tmp-gtyp.h + $(SHELL) $(srcdir)/move-if-change tmp-gtyp.h gtyp-gen.h + +s-gtype: gengtype$(build_exeext) $(GTFILES) + $(RUN_GEN) ./gengtype + $(STAMP) s-gtype + # # Compile the programs that generate insn-* from the machine description. # They are compiled with $(HOST_CC), and associated libraries, @@ -1790,93 +1938,123 @@ read-rtl.o: read-rtl.c $(HCONFIG_H) $(SYSTEM_H) $(RTL_H) \ gensupport.o: gensupport.c $(RTL_H) $(OBSTACK_H) $(SYSTEM_H) errors.h gensupport.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/gensupport.c $(OUTPUT_OPTION) -genconfig$(build_exeext) : genconfig.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) +genconfig$(build_exeext) : genconfig.o $(HOST_RTL) $(HOST_SUPPORT) \ + $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genconfig.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS) + genconfig.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \ + $(HOST_ERRORS) $(HOST_LIBS) genconfig.o : genconfig.c $(RTL_H) $(HCONFIG_H) \ $(SYSTEM_H) errors.h gensupport.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genconfig.c $(OUTPUT_OPTION) -genflags$(build_exeext) : genflags.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) +genflags$(build_exeext) : genflags.o $(HOST_RTL) $(HOST_SUPPORT) \ + $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genflags.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS) + genflags.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \ + $(HOST_ERRORS) $(HOST_LIBS) genflags.o : genflags.c $(RTL_H) $(OBSTACK_H) $(HCONFIG_H) \ $(SYSTEM_H) errors.h gensupport.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genflags.c $(OUTPUT_OPTION) -gencodes$(build_exeext) : gencodes.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) +gencodes$(build_exeext) : gencodes.o $(HOST_RTL) $(HOST_SUPPORT) \ + $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - gencodes.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS) + gencodes.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \ + $(HOST_ERRORS) $(HOST_LIBS) gencodes.o : gencodes.c $(RTL_H) $(HCONFIG_H) \ $(SYSTEM_H) errors.h gensupport.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/gencodes.c $(OUTPUT_OPTION) -genconstants$(build_exeext) : genconstants.o $(HOST_RTL) $(HOST_ERRORS) $(HOST_LIBDEPS) +genconstants$(build_exeext) : genconstants.o $(HOST_RTL) $(HOST_EARLY_SUPPORT) \ + $(HOST_ERRORS) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genconstants.o $(HOST_RTL) $(HOST_ERRORS) $(HOST_LIBS) + genconstants.o $(HOST_EARLY_SUPPORT) $(HOST_RTL) \ + $(HOST_ERRORS) $(HOST_LIBS) genconstants.o : genconstants.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genconstants.c $(OUTPUT_OPTION) -genemit$(build_exeext) : genemit.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) +genemit$(build_exeext) : genemit.o $(HOST_RTL) $(HOST_SUPPORT) \ + $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genemit.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS) + genemit.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \ + $(HOST_ERRORS) $(HOST_LIBS) genemit.o : genemit.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h gensupport.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genemit.c $(OUTPUT_OPTION) -genopinit$(build_exeext) : genopinit.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) +genopinit$(build_exeext) : genopinit.o $(HOST_RTL) $(HOST_SUPPORT) \ + $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genopinit.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS) + genopinit.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \ + $(HOST_ERRORS) $(HOST_LIBS) genopinit.o : genopinit.c $(RTL_H) $(HCONFIG_H) \ $(SYSTEM_H) errors.h gensupport.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genopinit.c $(OUTPUT_OPTION) -genrecog$(build_exeext) : genrecog.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) +genrecog$(build_exeext) : genrecog.o $(HOST_RTL) $(HOST_SUPPORT) \ + $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genrecog.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS) + genrecog.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \ + $(HOST_ERRORS) $(HOST_LIBS) genrecog.o : genrecog.c $(RTL_H) $(HCONFIG_H) \ $(SYSTEM_H) errors.h gensupport.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genrecog.c $(OUTPUT_OPTION) -genextract$(build_exeext) : genextract.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) +genextract$(build_exeext) : genextract.o $(HOST_RTL) $(HOST_SUPPORT) \ + $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genextract.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS) + genextract.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \ + $(HOST_ERRORS) $(HOST_LIBS) genextract.o : genextract.c $(RTL_H) $(HCONFIG_H) \ $(SYSTEM_H) insn-config.h errors.h gensupport.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genextract.c $(OUTPUT_OPTION) -genpeep$(build_exeext) : genpeep.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) +genpeep$(build_exeext) : genpeep.o $(HOST_RTL) $(HOST_SUPPORT) \ + $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genpeep.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS) + genpeep.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \ + $(HOST_ERRORS) $(HOST_LIBS) genpeep.o : genpeep.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h gensupport.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genpeep.c $(OUTPUT_OPTION) -genattr$(build_exeext) : genattr.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) +genattr$(build_exeext) : genattr.o $(HOST_RTL) $(HOST_SUPPORT) \ + $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genattr.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS) + genattr.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \ + $(HOST_ERRORS) $(HOST_LIBS) genattr.o : genattr.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h gensupport.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genattr.c $(OUTPUT_OPTION) -genattrtab$(build_exeext) : genattrtab.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) +genattrtab$(build_exeext) : genattrtab.o genautomata.o \ + $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_VARRAY) \ + $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genattrtab.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS) + genattrtab.o genautomata.o \ + $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) \ + $(HOST_VARRAY) $(HOST_LIBS) -lm genattrtab.o : genattrtab.c $(RTL_H) $(OBSTACK_H) $(HCONFIG_H) \ - $(SYSTEM_H) errors.h $(GGC_H) gensupport.h + $(SYSTEM_H) errors.h $(GGC_H) gensupport.h genattrtab.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genattrtab.c $(OUTPUT_OPTION) -genoutput$(build_exeext) : genoutput.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) +genautomata.o : genautomata.c $(RTL_H) $(OBSTACK_H) $(HCONFIG_H) \ + $(SYSTEM_H) errors.h varray.h genattrtab.h $(HASHTAB_H) + $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genautomata.c $(OUTPUT_OPTION) + +genoutput$(build_exeext) : genoutput.o $(HOST_RTL) $(HOST_SUPPORT) \ + $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS) $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ - genoutput.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS) + genoutput.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \ + $(HOST_ERRORS) $(HOST_LIBS) genoutput.o : genoutput.c $(RTL_H) $(HCONFIG_H) \ $(SYSTEM_H) errors.h gensupport.h @@ -1896,38 +2074,92 @@ genpreds$(build_exeext) : genpreds.o $(HOST_LIBDEPS) genpreds.o : genpreds.c $(RTL_BASE_H) $(HCONFIG_H) $(SYSTEM_H) $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genpreds.c $(OUTPUT_OPTION) +gengtype$(build_exeext) : gengtype.o gengtype-lex.o gengtype-yacc.o \ + $(HOST_LIBDEPS) + $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ + gengtype.o gengtype-lex.o gengtype-yacc.o $(HOST_LIBS) + +gengtype.o : gengtype.c gengtype.h $(HCONFIG_H) $(SYSTEM_H) real.h rtl.def \ + gtyp-gen.h + $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \ + $(srcdir)/gengtype.c $(OUTPUT_OPTION) + +gengtype-lex.o : $(srcdir)/gengtype-lex.c gengtype.h $(srcdir)/gengtype-yacc.c \ + $(HCONFIG_H) $(SYSTEM_H) + $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \ + $(srcdir)/gengtype-lex.c $(OUTPUT_OPTION) + +gengtype-yacc.o : $(srcdir)/gengtype-yacc.c gengtype.h $(HCONFIG_H) $(SYSTEM_H) + $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \ + $(srcdir)/gengtype-yacc.c $(OUTPUT_OPTION) + +# The sed command works around a bug in flex-2.5.4. +$(srcdir)/gengtype-lex.c : $(srcdir)/gengtype-lex.l + cd $(srcdir) && \ + $(FLEX) $(FLEXFLAGS) -t -o$@ gengtype-lex.l | \ + sed 's/^\(char msg\[\];\)/yyconst \1/' > g-$$$$ ; \ + if test $$? -eq 0 ; then \ + mv -f g-$$$$ gengtype-lex.c ; \ + else \ + rm -f g-$$$$.* ; \ + false ; \ + fi + +$(srcdir)/gengtype-yacc.c: $(srcdir)/gengtype-yacc.y + (cd $(srcdir) && \ + $(BISON) $(BISONFLAGS) -d -o gengtype-yacc.c gengtype-yacc.y || \ + ( rm -f $@ && false ) ) + +genconditions$(build_exeext) : genconditions.o $(HOST_EARLY_SUPPORT) \ + $(HOST_RTL) $(HOST_ERRORS) $(HOST_LIBDEPS) + $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \ + genconditions.o $(HOST_EARLY_SUPPORT) $(HOST_RTL) \ + $(HOST_ERRORS) $(HOST_LIBS) + +genconditions.o : genconditions.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h + $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \ + $(srcdir)/genconditions.c $(OUTPUT_OPTION) + # # 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 HOST_PREFIX_1 is `loser-', just to ensure these rules don't conflict +# and BUILD_PREFIX_1 is `loser-', just to ensure these rules don't conflict # with the rules for rtl.o, etc. -$(HOST_PREFIX_1)rtl.o: $(srcdir)/rtl.c $(HCONFIG_H) $(SYSTEM_H) $(RTL_H) \ +$(BUILD_PREFIX_1)rtl.o: $(srcdir)/rtl.c $(HCONFIG_H) $(SYSTEM_H) $(RTL_H) \ real.h $(GGC_H) errors.h - rm -f $(HOST_PREFIX)rtl.c - sed -e 's/config[.]h/hconfig.h/' $(srcdir)/rtl.c > $(HOST_PREFIX)rtl.c - $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)rtl.c $(OUTPUT_OPTION) + rm -f $(BUILD_PREFIX)rtl.c + sed -e 's/config[.]h/hconfig.h/' $(srcdir)/rtl.c > $(BUILD_PREFIX)rtl.c + $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(BUILD_PREFIX)rtl.c $(OUTPUT_OPTION) -$(HOST_PREFIX_1)print-rtl.o: $(srcdir)/print-rtl.c $(HCONFIG_H) \ +print-rtl1.o: $(srcdir)/print-rtl.c $(HCONFIG_H) \ $(RTL_H) $(TREE_H) hard-reg-set.h $(BASIC_BLOCK_H) - rm -f $(HOST_PREFIX)print-rtl.c - sed -e 's/config[.]h/hconfig.h/' $(srcdir)/print-rtl.c > $(HOST_PREFIX)print-rtl.c - $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)print-rtl.c $(OUTPUT_OPTION) - -$(HOST_PREFIX_1)bitmap.o: $(srcdir)/bitmap.c $(HCONFIG_H) $(SYSTEM_H) $(RTL_H) \ - flags.h $(BASIC_BLOCK_H) $(REGS_H) - rm -f $(HOST_PREFIX)bitmap.c - sed -e 's/config[.]h/hconfig.h/' $(srcdir)/bitmap.c > $(HOST_PREFIX)bitmap.c - $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)bitmap.c $(OUTPUT_OPTION) - -$(HOST_PREFIX_1)errors.o: errors.c $(HCONFIG_H) $(SYSTEM_H) errors.h - rm -f $(HOST_PREFIX)errors.c - sed -e 's/config[.]h/hconfig.h/' $(srcdir)/errors.c > $(HOST_PREFIX)errors.c - $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)errors.c $(OUTPUT_OPTION) - -$(HOST_PREFIX_1)ggc-none.o: ggc-none.c $(HCONFIG_H) $(SYSTEM_H) $(GCC_H) - rm -f $(HOST_PREFIX)ggc-none.c - sed -e 's/config[.]h/hconfig.h/' $(srcdir)/ggc-none.c > $(HOST_PREFIX)ggc-none.c - $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)ggc-none.c $(OUTPUT_OPTION) + rm -f print-rtl1.c + sed -e 's/config[.]h/hconfig.h/' $(srcdir)/print-rtl.c > print-rtl1.c + $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) print-rtl1.c $(OUTPUT_OPTION) + +$(BUILD_PREFIX_1)bitmap.o: $(srcdir)/bitmap.c $(HCONFIG_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/hconfig.h/' $(srcdir)/bitmap.c > $(BUILD_PREFIX)bitmap.c + $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(BUILD_PREFIX)bitmap.c $(OUTPUT_OPTION) + +$(BUILD_PREFIX_1)errors.o: errors.c $(HCONFIG_H) $(SYSTEM_H) errors.h + rm -f $(BUILD_PREFIX)errors.c + sed -e 's/config[.]h/hconfig.h/' $(srcdir)/errors.c > $(BUILD_PREFIX)errors.c + $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(BUILD_PREFIX)errors.c $(OUTPUT_OPTION) + +$(BUILD_PREFIX_1)varray.o: varray.c $(HCONFIG_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/hconfig.h/' $(srcdir)/varray.c > \ + $(BUILD_PREFIX)varray.c + $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \ + $(BUILD_PREFIX)varray.c $(OUTPUT_OPTION) + +$(BUILD_PREFIX_1)ggc-none.o: ggc-none.c $(HCONFIG_H) $(SYSTEM_H) $(GGC_H) + rm -f $(BUILD_PREFIX)ggc-none.c + sed -e 's/config[.]h/hconfig.h/' $(srcdir)/ggc-none.c > $(BUILD_PREFIX)ggc-none.c + $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(BUILD_PREFIX)ggc-none.c $(OUTPUT_OPTION) # # Remake internationalization support. @@ -1953,7 +2185,7 @@ intl.all intl.install: config.h insn-flags.h insn-constants.h # Make-lang.in should add dependencies of po-generated on any generated # files which need to be scanned by gettext (usually Yacc-generated parsers). -po-generated: c-parse.c tradcif.c +po-generated: c-parse.c # # Remake cpp and protoize. @@ -1967,9 +2199,9 @@ PREPROCESSOR_DEFINES = \ -DCROSS_INCLUDE_DIR=\"$(gcc_tooldir)/sys-include\" \ -DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" -LIBCPP_OBJS = cpplib.o cpplex.o cppmacro.o cppexp.o cppfiles.o \ - cpphash.o cpperror.o cppinit.o cppdefault.o \ - hashtable.o line-map.o mkdeps.o prefix.o version.o mbchar.o +LIBCPP_OBJS = cpplib.o cpplex.o cppmacro.o cppexp.o cppfiles.o cpptrad.o \ + cpphash.o cpperror.o cppinit.o cppdefault.o cppmain.o \ + hashtable.o line-map.o mkdeps.o prefix.o mbchar.o LIBCPP_DEPS = $(CPPLIB_H) cpphash.h line-map.h hashtable.h intl.h \ $(OBSTACK_H) $(SYSTEM_H) @@ -1981,11 +2213,7 @@ libcpp.a: $(LIBCPP_OBJS) $(AR) $(AR_FLAGS) libcpp.a $(LIBCPP_OBJS) -$(RANLIB) libcpp.a -cpp0$(exeext): cppmain.o intl.o libcpp.a $(LIBDEPS) - $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o cpp0$(exeext) cppmain.o \ - intl.o libcpp.a $(LIBS) - -cppmain.o: cppmain.c $(CONFIG_H) $(CPPLIB_H) intl.h $(SYSTEM_H) +cppmain.o: cppmain.c $(CONFIG_H) $(LIBCPP_DEPS) cpperror.o: cpperror.c $(CONFIG_H) $(LIBCPP_DEPS) cppexp.o: cppexp.c $(CONFIG_H) $(LIBCPP_DEPS) @@ -1993,9 +2221,10 @@ cpplex.o: cpplex.c $(CONFIG_H) $(LIBCPP_DEPS) mbchar.h cppmacro.o: cppmacro.c $(CONFIG_H) $(LIBCPP_DEPS) cpplib.o: cpplib.c $(CONFIG_H) $(LIBCPP_DEPS) cpphash.o: cpphash.c $(CONFIG_H) $(LIBCPP_DEPS) +cpptrad.o: cpptrad.c $(CONFIG_H) $(LIBCPP_DEPS) cppfiles.o: cppfiles.c $(CONFIG_H) $(LIBCPP_DEPS) $(SPLAY_TREE_H) mkdeps.h cppinit.o: cppinit.c $(CONFIG_H) $(LIBCPP_DEPS) cppdefault.h \ - mkdeps.h prefix.h version.h except.h + mkdeps.h prefix.h cppdefault.o: cppdefault.c $(CONFIG_H) $(SYSTEM_H) cppdefault.h Makefile $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ @@ -2004,20 +2233,6 @@ cppdefault.o: cppdefault.c $(CONFIG_H) $(SYSTEM_H) cppdefault.h Makefile mkdeps.o: mkdeps.c $(CONFIG_H) $(SYSTEM_H) mkdeps.h -# The traditional mode preprocessor, a separate program for ease of -# maintenance. Some code is shared with the ISO-C cpp. -tradcpp0$(exeext): tradcpp.o tradcif.o cppdefault.o version.o intl.o \ - mkdeps.o $(LIBDEPS) - $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o tradcpp0$(exeext) \ - tradcpp.o tradcif.o mkdeps.o cppdefault.o version.o intl.o $(LIBS) - -tradcpp.o: tradcpp.c $(CONFIG_H) $(SYSTEM_H) version.h cppdefault.h tradcpp.h -tradcif.o: $(srcdir)/tradcif.c $(CONFIG_H) $(SYSTEM_H) tradcpp.h - -$(srcdir)/tradcif.c: $(srcdir)/tradcif.y - (cd $(srcdir) && $(BISON) $(BISONFLAGS) -o tr$$$$.c tradcif.y && \ - mv -f tr$$$$.c tradcif.c) - # Note for the stamp targets, we run the program `true' instead of # having an empty command (nothing following the semicolon). @@ -2099,8 +2314,7 @@ gcov$(exeext): $(GCOV_OBJS) $(LIBDEPS) # s-* so that mostlyclean does not force the include directory to # be rebuilt. -# Build the include directory including float.h (which no longer depends upon -# enquire). +# Build the include directory stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) xlimits.h # Copy in the headers provided with gcc. # The sed command gets just the last file name component; @@ -2120,11 +2334,6 @@ stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) xlimits.h rm -f include/limits.h cp xlimits.h include/limits.h chmod a+r include/limits.h - rm -f include/float.h - if [ x$(FLOAT_H) != xMakefile.in ]; then \ - cp $(srcdir)/config/$(FLOAT_H) include/float.h && \ - chmod a+r include/float.h; \ - else :; fi # Install the README rm -f include/README cp $(srcdir)/README-fixinc include/README @@ -2146,7 +2355,7 @@ fixinc.sh: $(FIXINCSRCDIR)/mkfixinc.sh $(FIXINCSRCDIR)/fixincl.c \ $(FIXINCSRCDIR)/procopen.c $(FIXINCSRCDIR)/gnu-regex.c \ $(FIXINCSRCDIR)/server.c $(FIXINCSRCDIR)/gnu-regex.h \ $(FIXINCSRCDIR)/server.h $(FIXINCSRCDIR)/inclhack.def specs.ready - (MAKE="$(MAKE)"; srcdir=`cd $(srcdir)/fixinc && pwd` ; \ + (MAKE="$(MAKE)"; srcdir=`cd $(srcdir)/fixinc && ${PWD_COMMAND}` ; \ CC="$(HOST_CC)"; CFLAGS="$(HOST_CFLAGS)"; LDFLAGS="$(HOST_LDFLAGS)"; \ WARN_CFLAGS="$(WARN_CFLAGS)"; \ export MAKE srcdir CC CFLAGS LDFLAGS WARN_CFLAGS; cd ./fixinc && \ @@ -2156,10 +2365,10 @@ fixinc.sh: $(FIXINCSRCDIR)/mkfixinc.sh $(FIXINCSRCDIR)/fixincl.c \ stmp-fixinc: fixinc.sh gsyslimits.h rm -rf include; mkdir include -chmod a+rx include - (TARGET_MACHINE='$(target)'; srcdir=`cd $(srcdir); pwd`; \ + (TARGET_MACHINE='$(target)'; srcdir=`cd $(srcdir); ${PWD_COMMAND}`; \ SHELL='$(SHELL)' ;\ export TARGET_MACHINE srcdir SHELL ; \ - $(SHELL) ./fixinc.sh `pwd`/include $(SYSTEM_HEADER_DIR) $(OTHER_FIXINCLUDES_DIRS); \ + $(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; \ @@ -2216,7 +2425,7 @@ xsys-protos.h: $(GCC_PASSES) $(srcdir)/sys-protos.h deduced.h gen-protos$(build_ 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/( )/()/' \ - | ./gen-protos >xsys-protos.hT + | $(RUN_GEN) ./gen-protos >xsys-protos.hT mv xsys-protos.hT xsys-protos.h rm -rf fixtmp.c @@ -2268,24 +2477,22 @@ stmp-fixproto: fixhdr.ready fixproto stmp-int-hdrs docdir = $(srcdir)/doc doc: $(BUILD_INFO) $(GENERATED_MANPAGES) gccbug -info: $(docdir)/cpp.info $(docdir)/gcc.info $(docdir)/gccint.info lang.info $(docdir)/cppinternals.info +info: $(docdir)/cpp.info $(docdir)/gcc.info $(docdir)/gccint.info $(docdir)/gccinstall.info lang.info $(docdir)/cppinternals.info -$(docdir)/cpp.info: $(docdir)/cpp.texi $(docdir)/include/fdl.texi \ +TEXI_CPP_FILES = $(docdir)/cpp.texi $(docdir)/include/fdl.texi \ $(docdir)/cppenv.texi $(docdir)/cppopts.texi - cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/cpp.info doc/cpp.texi -$(docdir)/gcc.info: $(docdir)/gcc.texi $(docdir)/include/gcc-common.texi \ +TEXI_GCC_FILES = $(docdir)/gcc.texi $(docdir)/include/gcc-common.texi \ $(docdir)/frontends.texi $(docdir)/standards.texi \ $(docdir)/invoke.texi $(docdir)/extend.texi $(docdir)/md.texi \ $(docdir)/objc.texi $(docdir)/gcov.texi $(docdir)/trouble.texi \ $(docdir)/bugreport.texi $(docdir)/service.texi \ - $(docdir)/contribute.texi $(docdir)/vms.texi $(docdir)/compat.texi \ + $(docdir)/contribute.texi $(docdir)/compat.texi \ $(docdir)/include/funding.texi $(docdir)/gnu.texi \ $(docdir)/include/gpl.texi $(docdir)/include/fdl.texi \ $(docdir)/contrib.texi $(docdir)/cppenv.texi $(docdir)/cppopts.texi - cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/gcc.info doc/gcc.texi -$(docdir)/gccint.info: $(docdir)/gccint.texi \ +TEXI_GCCINT_FILES = $(docdir)/gccint.texi \ $(docdir)/include/gcc-common.texi $(docdir)/contribute.texi \ $(docdir)/makefile.texi $(docdir)/configterms.texi \ $(docdir)/portability.texi $(docdir)/interface.texi \ @@ -2296,46 +2503,47 @@ $(docdir)/gccint.info: $(docdir)/gccint.texi \ $(docdir)/headerdirs.texi $(docdir)/include/funding.texi \ $(docdir)/gnu.texi $(docdir)/include/gpl.texi \ $(docdir)/include/fdl.texi $(docdir)/contrib.texi \ - $(docdir)/languages.texi $(docdir)/sourcebuild.texi + $(docdir)/languages.texi $(docdir)/sourcebuild.texi \ + $(docdir)/gty.texi + +TEXI_GCCINSTALL_FILES = $(docdir)/install.texi $(docdir)/install-old.texi \ + $(docdir)/include/fdl.texi + +TEXI_CPPINT_FILES = $(docdir)/cppinternals.texi + +$(docdir)/cpp.info: $(TEXI_CPP_FILES) + cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/cpp.info doc/cpp.texi + +$(docdir)/gcc.info: $(TEXI_GCC_FILES) + cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/gcc.info doc/gcc.texi + +$(docdir)/gccint.info: $(TEXI_GCCINT_FILES) cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/gccint.info doc/gccint.texi -$(docdir)/cppinternals.info: $(docdir)/cppinternals.texi +$(docdir)/gccinstall.info: $(TEXI_GCCINSTALL_FILES) + cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/gccinstall.info doc/install.texi + +$(docdir)/cppinternals.info: $(TEXI_CPPINT_FILES) cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/cppinternals.info \ doc/cppinternals.texi -dvi: gcc.dvi gccint.dvi cpp.dvi lang.dvi cppinternals.dvi +dvi: gcc.dvi gccint.dvi gccinstall.dvi cpp.dvi lang.dvi cppinternals.dvi # This works with GNU Make's default rule. -cpp.dvi: $(docdir)/cpp.texi $(docdir)/include/fdl.texi \ - $(docdir)/cppenv.texi $(docdir)/cppopts.texi +cpp.dvi: $(TEXI_CPP_FILES) $(TEXI2DVI) -I $(docdir) -I $(docdir)/include $(docdir)/cpp.texi -gcc.dvi: $(docdir)/gcc.texi $(docdir)/include/gcc-common.texi \ - $(docdir)/frontends.texi $(docdir)/standards.texi \ - $(docdir)/invoke.texi $(docdir)/extend.texi $(docdir)/md.texi \ - $(docdir)/objc.texi $(docdir)/gcov.texi $(docdir)/trouble.texi \ - $(docdir)/bugreport.texi $(docdir)/service.texi \ - $(docdir)/contribute.texi $(docdir)/vms.texi \ - $(docdir)/include/funding.texi $(docdir)/gnu.texi \ - $(docdir)/include/gpl.texi $(docdir)/include/fdl.texi \ - $(docdir)/contrib.texi $(docdir)/cppenv.texi $(docdir)/cppopts.texi +gcc.dvi: $(TEXI_GCC_FILES) $(TEXI2DVI) -I $(docdir) -I $(docdir)/include $(docdir)/gcc.texi -gccint.dvi: $(docdir)/gccint.texi \ - $(docdir)/include/gcc-common.texi $(docdir)/contribute.texi \ - $(docdir)/makefile.texi $(docdir)/configterms.texi \ - $(docdir)/portability.texi $(docdir)/interface.texi \ - $(docdir)/passes.texi $(docdir)/c-tree.texi \ - $(docdir)/rtl.texi $(docdir)/md.texi $(docdir)/tm.texi \ - $(docdir)/hostconfig.texi $(docdir)/fragments.texi \ - $(docdir)/configfiles.texi $(docdir)/collect2.texi \ - $(docdir)/headerdirs.texi $(docdir)/include/funding.texi \ - $(docdir)/gnu.texi $(docdir)/include/gpl.texi \ - $(docdir)/include/fdl.texi $(docdir)/contrib.texi \ - $(docdir)/languages.texi $(docdir)/sourcebuild.texi +gccint.dvi: $(TEXI_GCCINT_FILES) $(TEXI2DVI) -I $(docdir) -I $(docdir)/include $(docdir)/gccint.texi -cppinternals.dvi: $(docdir)/cppinternals.texi +gccinstall.dvi: $(TEXI_GCCINSTALL_FILES) + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + $(TEXI2DVI) -I $$s/doc -I $$s/doc/include -o $@ $$s/doc/install.texi + +cppinternals.dvi: $(TEXI_CPPINT_FILES) $(TEXI2DVI) -I $(docdir) -I $(docdir)/include $(docdir)/cppinternals.texi generated-manpages: $(docdir)/gcov.1 $(docdir)/cpp.1 $(docdir)/gcc.1 \ @@ -2410,22 +2618,24 @@ $(docdir)/fsf-funding.7: $(docdir)/include/funding.texi INTL_MOSTLYCLEAN = intl.mostlyclean mostlyclean: $(INTL_MOSTLYCLEAN) lang.mostlyclean -rm -f $(STAGESTUFF) + -rm -f *$(coverageexts) -rm -rf libgcc # Delete the temporary source copies for cross compilation. - -rm -f $(HOST_PREFIX_1)rtl.c $(HOST_PREFIX_1)print-rtl.c - -rm -f $(HOST_PREFIX_1)bitmap.c $(HOST_PREFIX_1)errors.c - -rm -f $(HOST_PREFIX_1)ggc-none.c + -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 # Delete the temp files made in the course of building libgcc.a. -rm -f xlimits.h # Delete other built files. - -rm -f t-float.h-cross xsys-protos.hT + -rm -f xsys-protos.hT + -rm -f specs.h options.h gencheck.h # Delete the stamp and temporary files. -rm -f s-* tmp-* stamp-* stmp-* -rm -f */stamp-* */tmp-* # Delete debugging dump files. -rm -f *.[0-9][0-9].* */*.[0-9][0-9].* # Delete some files made during installation. - -rm -f specs float.h-* enquire SYSCALLS.c.X SYSCALLS.c + -rm -f 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 \ @@ -2440,6 +2650,11 @@ mostlyclean: $(INTL_MOSTLYCLEAN) lang.mostlyclean -rm -f gcc.vrs gcc.kys gcc.tps gcc.pgs gcc.fns # Delete core dumps. -rm -f core */core +# Delete file generated for gengtype.c + -rm -f gtyp-gen.h +# Delete files generated by gengtype.c + -rm -f gtype-* + -rm -f gt-* # Delete all files made by compilation # that don't exist in the distribution. @@ -2474,20 +2689,24 @@ distclean: clean $(INTL_DISTCLEAN) lang.distclean -rm -f cstamp-h -rm -f config.status config.run config.cache config.bak -rm -f Make-lang Make-hooks Make-host Make-target - -rm -f Makefile specs.h options.h gencheck.h *.oaux + -rm -f Makefile *.oaux -rm -f gthr-default.h -rm -f */stage1 */stage2 */stage3 */stage4 */include -rm -f c-parse.output -rm -f *.asm - -rm -f float.h -rm -f site.exp site.bak testsuite/site.exp testsuite/site.bak - -rm -f testsuite/{gcc,g++}.{log,sum} + -rm -f testsuite/*.log testsuite/*.sum + -cd testsuite && rm -f x *.x *.x? *.exe *.rpo *.o *.s *.S *.c + -cd testsuite && rm -f *.out *.gcov *.bb *.bbg + -rm -rf ${QMTEST_DIR} stamp-qmtest -rm -f intl/libintl.h libintl.h -rm -f cxxmain.c - -rm -f mklibgcc gccbug .gdbinit configargs.h + -rm -f mklibgcc mkheaders gccbug .gdbinit configargs.h -rm -f gcov.pod -rm -f fixinc/Makefile - -rmdir ada cp f java objc fixinc intl po 2>/dev/null +# 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 # Delete anything likely to be found in the source directory # that shouldn't be in the distribution. @@ -2532,7 +2751,7 @@ maintainer-clean: # Install the driver last so that the window when things are # broken is small. install: install-common $(INSTALL_HEADERS) $(INSTALL_LIBGCC) \ - $(INSTALL_CPP) install-man install-info intl.install install-@POSUB@ \ + install-cpp install-man install-info intl.install install-@POSUB@ \ lang.install-normal install-driver # Handle cpp installation. @@ -2553,14 +2772,6 @@ install-cpp: cpp$(exeext) else true; fi; \ fi -uninstall-cpp: - -rm -f $(DESTDIR)$(bindir)/$(CPP_INSTALL_NAME)$(exeext) - -rm -f $(DESTDIR)$(bindir)/$(CPP_CROSS_NAME)$(exeext) - -if [ x$(cpp_install_dir) != x ]; then \ - rm -f $(DESTDIR)$(prefix)/$(cpp_install_dir)/$(CPP_INSTALL_NAME)$(exeext); \ - rm -f $(DESTDIR)$(prefix)/$(cpp_install_dir)/$(CPP_CROSS_NAME)$(exeext); \ - else true; fi - # Create the installation directories. # $(libdir)/gcc-lib/include isn't currently searched by cpp. installdirs: @@ -2618,10 +2829,6 @@ install-common: native $(EXTRA_PARTS) lang.install-common $(INSTALL_DATA) SYSCALLS.c.X $(DESTDIR)$(libsubdir)/SYSCALLS.c.X; \ chmod a-x $(DESTDIR)$(libsubdir)/SYSCALLS.c.X; \ fi - -rm -f $(DESTDIR)$(libsubdir)/cpp0$(exeext) - $(INSTALL_PROGRAM) cpp0$(exeext) $(DESTDIR)$(libsubdir)/cpp0$(exeext) - -rm -f $(DESTDIR)$(libsubdir)/tradcpp0$(exeext) - $(INSTALL_PROGRAM) tradcpp0$(exeext) $(DESTDIR)$(libsubdir)/tradcpp0$(exeext) # Install gcov if it was compiled. -if [ -f gcov$(exeext) ]; \ then \ @@ -2630,12 +2837,16 @@ install-common: native $(EXTRA_PARTS) lang.install-common fi $(INSTALL_SCRIPT) gccbug $(DESTDIR)$(bindir)/$(GCCBUG_INSTALL_NAME) -# Install the driver program as $(target_alias)-gcc +# Install the driver program as $(target_alias)-gcc, +# $(target-alias)-gcc-$(version) # and also as either gcc (if native) or $(gcc_tooldir)/bin/gcc. install-driver: installdirs xgcc$(exeext) -if [ -f gcc-cross$(exeext) ] ; then \ rm -f $(DESTDIR)$(bindir)/$(GCC_CROSS_NAME)$(exeext); \ $(INSTALL_PROGRAM) gcc-cross$(exeext) $(DESTDIR)$(bindir)/$(GCC_CROSS_NAME)$(exeext); \ + rm -f $(DESTDIR)$(bindir)/$(target_alias)-gcc-$(version); \ + ( cd $(DESTDIR)$(bindir) && \ + $(LN) $(GCC_CROSS_NAME)$(exeext) $(target_alias)-gcc-$(version) ); \ if [ -d $(DESTDIR)$(gcc_tooldir)/bin/. ] ; then \ rm -f $(DESTDIR)$(gcc_tooldir)/bin/gcc$(exeext); \ $(INSTALL_PROGRAM) gcc-cross$(exeext) $(DESTDIR)$(gcc_tooldir)/bin/gcc$(exeext); \ @@ -2643,10 +2854,13 @@ install-driver: installdirs xgcc$(exeext) else \ rm -f $(DESTDIR)$(bindir)/$(GCC_INSTALL_NAME)$(exeext); \ $(INSTALL_PROGRAM) xgcc$(exeext) $(DESTDIR)$(bindir)/$(GCC_INSTALL_NAME)$(exeext); \ - rm -f $(DESTDIR)$(bindir)/$(target_alias)-gcc-1$(exeext); \ + rm -f $(DESTDIR)$(bindir)/$(target_alias)-gcc-$(version); \ ( cd $(DESTDIR)$(bindir) && \ - $(LN) $(GCC_INSTALL_NAME)$(exeext) $(target_alias)-gcc-1$(exeext) && \ - mv -f $(target_alias)-gcc-1$(exeext) $(GCC_TARGET_INSTALL_NAME)$(exeext) ); \ + $(LN) $(GCC_INSTALL_NAME)$(exeext) $(target_alias)-gcc-$(version) ); \ + rm -f $(DESTDIR)$(bindir)/$(target_alias)-gcc-tmp$(exeext); \ + ( cd $(DESTDIR)$(bindir) && \ + $(LN) $(GCC_INSTALL_NAME)$(exeext) $(target_alias)-gcc-tmp$(exeext) && \ + mv -f $(target_alias)-gcc-tmp$(exeext) $(GCC_TARGET_INSTALL_NAME)$(exeext) ); \ fi # Install the info files. @@ -2709,7 +2923,7 @@ install-libgcc: libgcc.mk libgcc.a installdirs r_f_t=: ; \ fi; \ $(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \ - HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \ + BUILD_PREFIX="$(BUILD_PREFIX)" BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \ AR_FOR_TARGET="$(AR_FOR_TARGET)" \ AR_CREATE_FOR_TARGET="$(AR_CREATE_FOR_TARGET)" \ AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" \ @@ -2736,7 +2950,7 @@ install-multilib: stmp-multilib installdirs r_f_t=: ; \ fi; \ $(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \ - HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \ + BUILD_PREFIX="$(BUILD_PREFIX)" BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \ AR_FOR_TARGET="$(AR_FOR_TARGET)" \ AR_CREATE_FOR_TARGET="$(AR_CREATE_FOR_TARGET)" \ AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" \ @@ -2762,7 +2976,7 @@ install-headers: $(INSTALL_HEADERS_DIR) # Don't need to use LN_S here since we really do need ln -s and no substitutes. -files=`cd $(DESTDIR)$(libsubdir)/include; find . -type l -print 2>/dev/null`; \ if [ $$? -eq 0 ]; then \ - dir=`cd include; pwd`; \ + dir=`cd include; ${PWD_COMMAND}`; \ for i in $$files; do \ dest=`ls -ld $(DESTDIR)$(libsubdir)/include/$$i | sed -n 's/.*-> //p'`; \ if expr "$$dest" : "$$dir.*" > /dev/null; then \ @@ -2784,7 +2998,7 @@ install-headers-tar: stmp-int-hdrs $(STMP_FIXPROTO) install-include-dir # Unless a full pathname is provided, some shells would print the new CWD, # found in CDPATH, corrupting the output. We could just redirect the # output of `cd', but some shells lose on redirection within `()'s - (cd `pwd`/include ; \ + (cd `${PWD_COMMAND}`/include ; \ tar -cf - .; exit 0) | (cd $(DESTDIR)$(libsubdir)/include; tar xpf - ) # /bin/sh on some systems returns the status of the first tar, # and that can lose with GNU tar which always writes a full block. @@ -2793,13 +3007,50 @@ install-headers-tar: stmp-int-hdrs $(STMP_FIXPROTO) install-include-dir # Install the include directory using cpio. install-headers-cpio: stmp-int-hdrs $(STMP_FIXPROTO) install-include-dir # See discussion about the use of `pwd` above - cd `pwd`/include ; \ + cd `${PWD_COMMAND}`/include ; \ find . -print | cpio -pdum $(DESTDIR)$(libsubdir)/include # Install the include directory using cp. install-headers-cp: stmp-int-hdrs $(STMP_FIXPROTO) install-include-dir cp -p -r include $(DESTDIR)$(libsubdir) +itoolsdir = $(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) + $(SHELL) $(srcdir)/mkinstalldirs $(DESTDIR)$(itoolsdir)/include + for file in $(USER_H); do \ + realfile=`echo $$file | sed -e 's|.*/\([^/]*\)$$|\1|'`; \ + $(INSTALL_DATA) $$file \ + $(DESTDIR)$(itoolsdir)/include/$$realfile ; \ + done + $(INSTALL_DATA) xlimits.h $(DESTDIR)$(itoolsdir)/include/limits.h + if [ x$(STMP_FIXINC) != x ] ; then \ + $(INSTALL_DATA) $(srcdir)/README-fixinc \ + $(DESTDIR)$(itoolsdir)/include/README ; \ + $(INSTALL_PROGRAM) fixinc.sh $(DESTDIR)$(itoolsdir)/fixinc.sh ; \ + $(INSTALL_PROGRAM) fixinc/fixincl $(DESTDIR)$(itoolsdir)/fixincl ; \ + $(INSTALL_DATA) $(srcdir)/gsyslimits.h $(DESTDIR)$(itoolsdir)/gsyslimits.h ; \ + else :; fi + if [ x$(STMP_FIXPROTO) != x ] ; then \ + $(INSTALL_PROGRAM) $(srcdir)/mkinstalldirs \ + $(DESTDIR)$(itoolsdir)/mkinstalldirs ; \ + $(INSTALL_PROGRAM) $(srcdir)/fixproto $(DESTDIR)$(itoolsdir)/fixproto ; \ + $(INSTALL_PROGRAM) fix-header$(build_exeext) \ + $(DESTDIR)$(itoolsdir)/fix-header$(build_exeext) ; \ + else :; fi + $(INSTALL_PROGRAM) mkheaders $(DESTDIR)$(itoolsdir)/mkheaders + echo 'SYSTEM_HEADER_DIR="$(SYSTEM_HEADER_DIR)"' \ + > $(DESTDIR)$(itoolsdir)/mkheaders.conf + echo 'OTHER_FIXINCLUDES_DIRS="$(OTHER_FIXINCLUDES_DIRS)"' \ + >> $(DESTDIR)$(itoolsdir)/mkheaders.conf + echo 'FIXPROTO_DEFINES="$(FIXPROTO_DEFINES)"' \ + >> $(DESTDIR)$(itoolsdir)/mkheaders.conf + echo 'STMP_FIXPROTO="$(STMP_FIXPROTO)"' >> $(DESTDIR)$(itoolsdir)/mkheaders.conf + echo 'STMP_FIXINC="$(STMP_FIXINC)"' >> $(DESTDIR)$(itoolsdir)/mkheaders.conf + # Use this target to install the program `collect2' under the name `collect2'. install-collect2: collect2 installdirs $(INSTALL_PROGRAM) collect2$(exeext) $(DESTDIR)$(libsubdir)/collect2$(exeext) @@ -2807,10 +3058,16 @@ install-collect2: collect2 installdirs $(INSTALL_PROGRAM) xgcc$(exeext) $(DESTDIR)$(libsubdir)/gcc$(exeext) # Cancel installation by deleting the installed files. -uninstall: intl.uninstall lang.uninstall $(UNINSTALL_CPP) +uninstall: intl.uninstall lang.uninstall -rm -rf $(DESTDIR)$(libsubdir) -rm -rf $(DESTDIR)$(bindir)/$(GCC_INSTALL_NAME)$(exeext) -rm -rf $(DESTDIR)$(bindir)/$(GCC_CROSS_NAME)$(exeext) + -rm -f $(DESTDIR)$(bindir)/$(CPP_INSTALL_NAME)$(exeext) + -rm -f $(DESTDIR)$(bindir)/$(CPP_CROSS_NAME)$(exeext) + -if [ x$(cpp_install_dir) != x ]; then \ + rm -f $(DESTDIR)$(prefix)/$(cpp_install_dir)/$(CPP_INSTALL_NAME)$(exeext); \ + rm -f $(DESTDIR)$(prefix)/$(cpp_install_dir)/$(CPP_CROSS_NAME)$(exeext); \ + else true; fi -rm -rf $(DESTDIR)$(bindir)/$(PROTOIZE_INSTALL_NAME)$(exeext) -rm -rf $(DESTDIR)$(bindir)/$(PROTOIZE_CROSS_NAME)$(exeext) -rm -rf $(DESTDIR)$(bindir)/$(UNPROTOIZE_INSTALL_NAME)$(exeext) @@ -2838,8 +3095,8 @@ site.exp: ./config.status Makefile @echo "## these variables are automatically generated by make ##" > ./tmp0 @echo "# Do not edit here. If you wish to override these values" >> ./tmp0 @echo "# add them to the last section" >> ./tmp0 - @echo "set rootme \"`pwd`\"" >> ./tmp0 - @echo "set srcdir \"`cd ${srcdir}; pwd`\"" >> ./tmp0 + @echo "set rootme \"`${PWD_COMMAND}`\"" >> ./tmp0 + @echo "set srcdir \"`cd ${srcdir}; ${PWD_COMMAND}`\"" >> ./tmp0 @echo "set host_triplet $(host_canonical)" >> ./tmp0 @echo "set build_triplet $(build_canonical)" >> ./tmp0 @echo "set target_triplet $(target)" >> ./tmp0 @@ -2872,23 +3129,26 @@ site.exp: ./config.status Makefile fi echo "set tmpdir $(objdir)/testsuite" >> ./tmp0 @echo "set srcdir \"\$${srcdir}/testsuite\"" >> ./tmp0 + @if [ "X$(ALT_CXX_UNDER_TEST)" != "X" ] ; then \ + echo "set ALT_CXX_UNDER_TEST $(ALT_CXX_UNDER_TEST)" >> ./tmp0; \ + else true; \ + fi + @if [ "X$(COMPAT_OPTIONS)" != "X" ] ; then \ + echo "set COMPAT_OPTIONS $(COMPAT_OPTIONS)" >> ./tmp0; \ + else true; \ + fi @echo "## All variables above are generated by configure. Do Not Edit ##" >> ./tmp0 @cat ./tmp0 > site.exp @cat site.bak | sed \ -e '1,/^## All variables above are.*##/ d' >> site.exp -@rm -f ./tmp? -CHECK_TARGETS = check-gcc check-fixinc @check_languages@ +CHECK_TARGETS = check-gcc @check_languages@ check-c++ : check-g++ check-f77 : check-g77 check-java : -check-fixinc : - if (autogen --ver=v) > /dev/null 2>&1 ; \ - then cd fixinc && $(MAKE) check ; \ - else true ; fi - check: $(CHECK_TARGETS) # The idea is to parallelize testing of multilibs, for example: @@ -2912,55 +3172,132 @@ $(TESTSUITEDIR)/site.exp: site.exp sed '/set tmpdir/ s|testsuite|$(TESTSUITEDIR)|' < site.exp > $@ check-g++: $(TESTSUITEDIR)/site.exp - -(rootme=`pwd`; export rootme; \ - srcdir=`cd ${srcdir}; pwd` ; export srcdir ; \ + -(rootme=`${PWD_COMMAND}`; export rootme; \ + srcdir=`cd ${srcdir}; ${PWD_COMMAND}` ; export srcdir ; \ cd $(TESTSUITEDIR); \ EXPECT=${EXPECT} ; export EXPECT ; \ if [ -f $${rootme}/../expect/expect ] ; then \ - TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; pwd` ; \ + TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \ export TCL_LIBRARY ; fi ; \ $(RUNTEST) --tool g++ $(RUNTESTFLAGS)) check-gcc: $(TESTSUITEDIR)/site.exp - -(rootme=`pwd`; export rootme; \ - srcdir=`cd ${srcdir}; pwd` ; export srcdir ; \ + -(rootme=`${PWD_COMMAND}`; export rootme; \ + srcdir=`cd ${srcdir}; ${PWD_COMMAND}` ; export srcdir ; \ cd $(TESTSUITEDIR); \ EXPECT=${EXPECT} ; export EXPECT ; \ if [ -f $${rootme}/../expect/expect ] ; then \ - TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; pwd` ; \ + TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \ export TCL_LIBRARY ; fi ; \ $(RUNTEST) --tool gcc $(RUNTESTFLAGS)) check-g77: $(TESTSUITEDIR)/site.exp - -(rootme=`pwd`; export rootme; \ - srcdir=`cd ${srcdir}; pwd` ; export srcdir ; \ + -(rootme=`${PWD_COMMAND}`; export rootme; \ + srcdir=`cd ${srcdir}; ${PWD_COMMAND}` ; export srcdir ; \ cd $(TESTSUITEDIR); \ EXPECT=${EXPECT} ; export EXPECT ; \ if [ -f $${rootme}/../expect/expect ] ; then \ - TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; pwd` ; \ + TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \ export TCL_LIBRARY ; fi ; \ $(RUNTEST) --tool g77 $(RUNTESTFLAGS)) check-objc: $(TESTSUITEDIR)/site.exp - -(rootme=`pwd`; export rootme; \ - srcdir=`cd ${srcdir}; pwd` ; export srcdir ; \ + -(rootme=`${PWD_COMMAND}`; export rootme; \ + srcdir=`cd ${srcdir}; ${PWD_COMMAND}` ; export srcdir ; \ cd $(TESTSUITEDIR); \ EXPECT=${EXPECT} ; export EXPECT ; \ if [ -f $${rootme}/../expect/expect ] ; then \ - TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; pwd` ; \ + TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \ export TCL_LIBRARY ; fi ; \ $(RUNTEST) --tool objc $(RUNTESTFLAGS)) check-consistency: testsuite/site.exp - -rootme=`pwd`; export rootme; \ - srcdir=`cd ${srcdir}; pwd` ; export srcdir ; \ + -rootme=`${PWD_COMMAND}`; export rootme; \ + srcdir=`cd ${srcdir}; ${PWD_COMMAND}` ; export srcdir ; \ cd testsuite; \ EXPECT=${EXPECT} ; export EXPECT ; \ if [ -f $${rootme}/../expect/expect ] ; then \ - TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; pwd` ; \ + TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \ export TCL_LIBRARY ; fi ; \ $(RUNTEST) --tool consistency $(RUNTESTFLAGS) +# QMTest targets + +# The path to qmtest. +QMTEST_PATH=qmtest + +# The flags to pass to qmtest. +QMTESTFLAGS= + +# The flags to pass to "qmtest run". +QMTESTRUNFLAGS= + +# The command to use to invoke qmtest. +QMTEST=${QMTEST_PATH} ${QMTESTFLAGS} + +# The tests (or suites) to run. +QMTEST_GPP_TESTS=gpp + +# The subdirectory of the OBJDIR that will be used to store the QMTest +# test database configuration and that will be used for temporary +# scratch space during QMTest's execution. +QMTEST_DIR=qmtestsuite + +# Create the QMTest database configuration. +${QMTEST_DIR} stamp-qmtest: + debug_options=""; \ + ${STAMP} empty.C; \ + for option in \ + -gdwarf-2 -gstabs -gstabs+ -gxcoff -gxcoff+ -gcoff; do \ + (./cc1plus -q $${option} empty.C 2>&1 | \ + grep "unknown or unsupported -g option" > /dev/null) || \ + debug_options="$${debug_options}$${option} "; done; \ + ${QMTEST} -D ${QMTEST_DIR} create-tdb \ + -c gcc_database.GCCDatabase \ + -a GCCDatabase.testsuite_root=`cd ${srcdir}/testsuite && pwd` \ + -a GCCDatabase.debug_options="$${debug_options}" + rm -f empty.C empty.s + $(STAMP) stamp-qmtest + +# Create the QMTest context file. +${QMTEST_DIR}/context: stamp-qmtest + echo "GCCTest.flags=-B${objdir}" >> $@ + echo "GCCTest.objdir=${objdir}/.." >> $@ + echo "GCCTest.host=${host_canonical}" >> $@ + echo "GCCTest.target=${target}" >> $@ + echo "GCCTest.gcov=${objdir}/gcov" >> $@ + echo "GPPTest.gpp=${objdir}/g++" >> $@ + echo "DGTest.demangler=${objdir}/c++filt" >> $@ + +# Run the G++ testsuite using QMTest. +qmtest-g++: ${QMTEST_DIR}/context ${QMTEST_DIR}/gpp-expected.qmr + cd ${QMTEST_DIR} && ${QMTEST} run ${QMTESTRUNFLAGS} -C context \ + -o gpp.qmr -O gpp-expected.qmr \ + ${QMTEST_GPP_TESTS} + +# Use the QMTest GUI. +qmtest-gui: ${QMTEST_DIR}/context + cd ${QMTEST_DIR} && ${QMTEST} gui -C context + +# Build the set of expected G++ failures. +${QMTEST_DIR}/gpp-expected.qmr: ${QMTEST_DIR}/context + echo "Determining expected results..." + cd ${QMTEST_DIR} && ${QMTEST} run ${QMTESTRUNFLAGS} -C context \ + -c "GCCTest.generate_xfails=1" -o gpp-expected.qmr \ + ${QMTEST_GPP_TESTS} \ + > /dev/null + +.PHONY: qmtest-g++ + +# 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) + +paranoia: paranoia.o real.o $(LIBIBERTY) + g++ -o $@ paranoia.o real.o $(LIBIBERTY) + # These exist for maintenance purposes. # Update the tags table. @@ -2979,6 +3316,7 @@ VOL_FILES=`echo $(BACKEND) $(OBJS) $(C_OBJS) $(LIBCPP_OBJS) *.c *.h gen*` # WARN_CFLAGS setting can't be to the expansion of GCC_WARN_CFLAGS in # the context of the stage_x rule. STAGE2_FLAGS_TO_PASS = \ + ADAC="\$$(CC)" \ CFLAGS="$(BOOT_CFLAGS)" \ LDFLAGS="$(BOOT_LDFLAGS)" \ WARN_CFLAGS="\$$(GCC_WARN_CFLAGS)" \ @@ -2996,7 +3334,7 @@ STAGE2_FLAGS_TO_PASS = \ stage1_build: $(MAKE) CC="$(CC)" libdir=$(libdir) LANGUAGES="$(BOOT_LANGUAGES)" \ CFLAGS="$(STAGE1_CFLAGS)" MAKEINFO="$(MAKEINFO)" \ - MAKEINFOFLAGS="$(MAKEINFOFLAGS)" + MAKEINFOFLAGS="$(MAKEINFOFLAGS)" COVERAGE_FLAGS= $(STAMP) stage1_build echo stage1_build > stage_last @@ -3006,7 +3344,7 @@ stage1_copy: stage1_build echo stage2_build > stage_last stage2_build: stage1_copy - $(MAKE) CC="stage1/xgcc$(exeext) -Bstage1/ -B$(build_tooldir)/bin/" \ + $(MAKE) CC="$(STAGE_CC_WRAPPER) stage1/xgcc$(exeext) -Bstage1/ -B$(build_tooldir)/bin/" \ STAGE_PREFIX=stage1/ \ $(STAGE2_FLAGS_TO_PASS) $(STAMP) stage2_build @@ -3018,7 +3356,7 @@ stage2_copy: stage2_build echo stage3_build > stage_last stage3_build: stage2_copy - $(MAKE) CC="stage2/xgcc$(exeext) -Bstage2/ -B$(build_tooldir)/bin/" \ + $(MAKE) CC="$(STAGE_CC_WRAPPER) stage2/xgcc$(exeext) -Bstage2/ -B$(build_tooldir)/bin/" \ STAGE_PREFIX=stage2/ \ $(STAGE2_FLAGS_TO_PASS) $(STAMP) stage3_build @@ -3031,7 +3369,7 @@ stage3_copy: stage3_build echo stage4_build > stage_last stage4_build: stage3_copy - $(MAKE) CC="stage3/xgcc$(exeext) -Bstage3/ -B$(build_tooldir)/bin/" \ + $(MAKE) CC="$(STAGE_CC_WRAPPER) stage3/xgcc$(exeext) -Bstage3/ -B$(build_tooldir)/bin/" \ STAGE_PREFIX=stage3/ \ $(STAGE2_FLAGS_TO_PASS) $(STAMP) stage4_build @@ -3052,7 +3390,8 @@ bootstrap: stage3_build @echo @echo Bootstrap complete - make \"quickstrap\" to redo last build, @echo \"restage1\" through \"restage3\" to rebuild specific stages, - @echo or \"cleanstrap\" to redo the bootstrap from scratch. + @echo \"restrap\" to redo the bootstrap from stage1, or + @echo \"cleanstrap\" to redo the bootstrap from scratch. bootstrap-lean : clean_s1 clean_s2 stage3_build @echo @@ -3121,6 +3460,16 @@ cleanstrap: -$(MAKE) clean $(MAKE) LANGUAGES="$(LANGUAGES)" bootstrap +unstrap: + -rm -rf stage[234]* + $(MAKE) unstage1 + +# Differs from cleanstrap in that it starts from the earlier stage1 build, +# not from scratch. +restrap: + $(MAKE) unstrap + $(MAKE) LANGUAGES="$(LANGUAGES)" bootstrap + # Compare the object files in the current directory with those in the # stage2 directory. @@ -3159,18 +3508,21 @@ compare compare3 compare4 compare-lean compare3-lean compare4-lean: force # Compare the object files in the current directory with those in the # stage2 directory. Use gnu cmp (diffutils v2.4 or later) to avoid # running tail and the overhead of twice copying each object file. - +# An exit status of 1 is precisely the result we're looking for (other +# values mean other problems). gnucompare gnucompare3 gnucompare4 gnucompare-lean gnucompare3-lean gnucompare4-lean: force -rm -f .bad_compare case "$@" in gnucompare | gnucompare-lean ) stage=2 ;; * ) stage=`echo $@ | sed -e 's,^gnucompare\([0-9][0-9]*\).*,\1,'` ;; esac; \ for file in *$(objext); do \ - (cmp --ignore-initial=16 $$file stage$$stage/$$file > /dev/null 2>&1 || echo $$file differs >> .bad_compare) || true; \ + cmp --ignore-initial=16 $$file stage$$stage/$$file > /dev/null 2>&1; \ + test $$? -eq 1 && echo $$file differs >> .bad_compare || true; \ done case "$@" in gnucompare | gnucompare-lean ) stage=2 ;; * ) stage=`echo $@ | sed -e 's,^gnucompare\([0-9][0-9]*\).*,\1,'` ;; esac; \ for dir in tmp-foo intl $(SUBDIRS); do \ if [ "`echo $$dir/*$(objext)`" != "$$dir/*$(objext)" ] ; then \ for file in $$dir/*$(objext); do \ - (cmp --ignore-initial=16 $$file stage$$stage/$$file > /dev/null 2>&1 || echo $$file differs >> .bad_compare) || true; \ + cmp --ignore-initial=16 $$file stage$$stage/$$file > /dev/null 2>&1; \ + test $$? -eq 1 && echo $$file differs >> .bad_compare || true; \ done; \ else true; fi; \ done @@ -3323,59 +3675,6 @@ risky-stage4: stage4 force: -# --- -# The enquire rules are still useful for building new float-anything.h. -# Special flags for compiling enquire. -# We disable optimization to make floating point more reliable. -ENQUIRE_CFLAGS = -DNO_MEM -DNO_LONG_DOUBLE_IO -O0 -ENQUIRE_LDFLAGS = $(LDFLAGS) - -# Enquire target (This is a variable so that a target can choose not to -# build it.) -ENQUIRE = enquire - -# Test to see whether <float.h> exists in the system header files, -# and is not derived from GCC. -FLOAT_H_TEST = \ - [ -f $(SYSTEM_HEADER_DIR)/float.h ] && \ - if grep 'ifndef _FLOAT_H___' $(SYSTEM_HEADER_DIR)/float.h >/dev/null; \ - then false; \ - else :; fi -# We pretend to not having a usable <float.h>, hence disable the FLOAT_H_TEST -# to ensure, we're emitting a full blown <float.h> ourselves. -FLOAT_H_TEST = false - -# Used to compile enquire with standard cc, but have forgotten why. -# Let's try with GCC. -enquire: enquire.o $(GCC_PARTS) - $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ENQUIRE_LDFLAGS) enquire.o -o $@ -enquire.o: $(srcdir)/enquire.c $(GCC_PASSES) stmp-int-hdrs - if $(FLOAT_H_TEST); then \ - rm -f include/float.h; \ - SYS_FLOAT_H_WRAP=1; \ - else :; \ - SYS_FLOAT_H_WRAP=0; \ - fi; \ - $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ALL_CPPFLAGS) $(ENQUIRE_CFLAGS) \ - -DSYS_FLOAT_H_WRAP=$$SYS_FLOAT_H_WRAP \ - -I. -c $(srcdir)/enquire.c $(OUTPUT_OPTION) - -# Create float.h source for the native machine. -# Make it empty if we can use the system float.h without changes. -float.h-nat: enquire - -./enquire -f > tmp-float.h - grep '#define [^_]' tmp-float.h >/dev/null || true > tmp-float.h - mv tmp-float.h float.h-nat - -# Create a dummy float.h source for a cross-compiler. -# ??? This isn't used anymore. Should we create config/float-unkn.h -# and make that the default float_format in configure? -float.h-cross: - echo "#ifndef __GCC_FLOAT_NOT_NEEDED" > t-float.h-cross - echo "#error float.h values not known for cross-compiler" >> t-float.h-cross - echo "#endif" >> t-float.h-cross - mv t-float.h-cross float.h-cross - # Rules for generating translated message descriptions. # Disabled by autoconf if the tools are not available. @@ -3386,7 +3685,7 @@ MSGMERGE = msgmerge PACKAGE = @PACKAGE@ CATALOGS = @CATALOGS@ -.PHONY: build- install- build-po install-po update-po +.PHONY: build- install- build-po install-po update-po # Dummy rules to deal with dependencies produced by use of # "build-@POSUB@" and "install-@POSUB@" above, when NLS is disabled. diff --git a/contrib/gcc/builtins.c b/contrib/gcc/builtins.c index d8874d6..4c5650a 100644 --- a/contrib/gcc/builtins.c +++ b/contrib/gcc/builtins.c @@ -22,9 +22,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "config.h" #include "system.h" #include "machmode.h" +#include "real.h" #include "rtl.h" #include "tree.h" -#include "obstack.h" #include "flags.h" #include "regs.h" #include "hard-reg-set.h" @@ -41,6 +41,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "predict.h" #include "tm_p.h" #include "target.h" +#include "langhooks.h" #define CALLED_AS_BUILT_IN(NODE) \ (!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10)) @@ -61,7 +62,7 @@ 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) STRINGX(X), +#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT) STRINGX(X), const char *const built_in_names[(int) END_BUILTINS] = { #include "builtins.def" @@ -72,8 +73,6 @@ const char *const built_in_names[(int) END_BUILTINS] = initialized to NULL_TREE. */ tree built_in_decls[(int) END_BUILTINS]; -tree (*lang_type_promotes_to) PARAMS ((tree)); - static int get_pointer_alignment PARAMS ((tree, unsigned int)); static tree c_strlen PARAMS ((tree)); static const char *c_getstr PARAMS ((tree)); @@ -98,11 +97,11 @@ static rtx expand_builtin_mathfn PARAMS ((tree, rtx, rtx)); static rtx expand_builtin_constant_p PARAMS ((tree)); static rtx expand_builtin_args_info PARAMS ((tree)); static rtx expand_builtin_next_arg PARAMS ((tree)); -static rtx expand_builtin_va_start PARAMS ((int, tree)); +static rtx expand_builtin_va_start PARAMS ((tree)); static rtx expand_builtin_va_end PARAMS ((tree)); static rtx expand_builtin_va_copy PARAMS ((tree)); static rtx expand_builtin_memcmp PARAMS ((tree, tree, rtx, - enum machine_mode)); + enum machine_mode)); static rtx expand_builtin_strcmp PARAMS ((tree, rtx, enum machine_mode)); static rtx expand_builtin_strncmp PARAMS ((tree, rtx, @@ -118,17 +117,19 @@ static rtx expand_builtin_strspn PARAMS ((tree, rtx, static rtx expand_builtin_strcspn PARAMS ((tree, rtx, enum machine_mode)); static rtx expand_builtin_memcpy PARAMS ((tree, rtx, - enum machine_mode)); + enum machine_mode)); static rtx expand_builtin_strcpy PARAMS ((tree, rtx, - enum machine_mode)); + enum machine_mode)); static rtx builtin_strncpy_read_str PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode)); static rtx expand_builtin_strncpy PARAMS ((tree, rtx, enum machine_mode)); static rtx builtin_memset_read_str PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode)); +static rtx builtin_memset_gen_str PARAMS ((PTR, HOST_WIDE_INT, + enum machine_mode)); static rtx expand_builtin_memset PARAMS ((tree, rtx, - enum machine_mode)); + enum machine_mode)); static rtx expand_builtin_bzero PARAMS ((tree)); static rtx expand_builtin_strlen PARAMS ((tree, rtx)); static rtx expand_builtin_strstr PARAMS ((tree, rtx, @@ -147,6 +148,8 @@ static tree stabilize_va_list PARAMS ((tree, int)); static rtx expand_builtin_expect PARAMS ((tree, rtx)); static tree fold_builtin_constant_p PARAMS ((tree)); static tree fold_builtin_classify_type PARAMS ((tree)); +static tree fold_builtin_inf PARAMS ((tree, int)); +static tree fold_builtin_nan PARAMS ((tree, tree, int)); static tree build_function_call_expr PARAMS ((tree, tree)); static int validate_arglist PARAMS ((tree, ...)); @@ -511,7 +514,7 @@ expand_builtin_setjmp_setup (buf_addr, receiver_label) void expand_builtin_setjmp_receiver (receiver_label) - rtx receiver_label ATTRIBUTE_UNUSED; + rtx receiver_label ATTRIBUTE_UNUSED; { /* Clobber the FP when we get here, so we have to make sure it's marked as used by this function. */ @@ -639,7 +642,7 @@ void expand_builtin_longjmp (buf_addr, value) rtx buf_addr, value; { - rtx fp, lab, stack, insn; + rtx fp, lab, stack, insn, last; enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL); if (setjmp_alias_set == -1) @@ -662,6 +665,7 @@ expand_builtin_longjmp (buf_addr, value) current_function_calls_longjmp = 1; + last = get_last_insn (); #ifdef HAVE_builtin_longjmp if (HAVE_builtin_longjmp) emit_insn (gen_builtin_longjmp (buf_addr)); @@ -707,6 +711,8 @@ expand_builtin_longjmp (buf_addr, 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) { REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx, @@ -714,7 +720,7 @@ expand_builtin_longjmp (buf_addr, value) break; } else if (GET_CODE (insn) == CALL_INSN) - break; + break; } } @@ -740,7 +746,7 @@ expand_builtin_prefetch (arglist) { arg1 = TREE_VALUE (TREE_CHAIN (arglist)); if (TREE_CHAIN (TREE_CHAIN (arglist))) - arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); else arg2 = build_int_2 (3, 0); } @@ -756,8 +762,8 @@ expand_builtin_prefetch (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"); - arg1 = integer_zero_node; + error ("second arg to `__builtin_prefetch' must be a constant"); + arg1 = integer_zero_node; } op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); /* Argument 1 must be either zero or one. */ @@ -784,19 +790,26 @@ expand_builtin_prefetch (arglist) #ifdef HAVE_prefetch if (HAVE_prefetch) { - if (! (*insn_data[(int)CODE_FOR_prefetch].operand[0].predicate) - (op0, - insn_data[(int)CODE_FOR_prefetch].operand[0].mode)) - op0 = force_reg (Pmode, op0); + if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate) + (op0, + insn_data[(int) CODE_FOR_prefetch].operand[0].mode)) + || (GET_MODE(op0) != Pmode)) + { +#ifdef POINTERS_EXTEND_UNSIGNED + if (GET_MODE(op0) != Pmode) + op0 = convert_memory_address (Pmode, op0); +#endif + op0 = force_reg (Pmode, op0); + } 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)) - emit_insn (op0); + /* 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)) + emit_insn (op0); } /* Get a MEM rtx for expression EXP which is the address of an operand @@ -820,7 +833,7 @@ get_memory_rtx (exp) If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if we can. First remove any nops. */ while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR - || TREE_CODE (exp) == NON_LVALUE_EXPR) + || TREE_CODE (exp) == NON_LVALUE_EXPR) && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0)))) exp = TREE_OPERAND (exp, 0); @@ -874,7 +887,7 @@ apply_args_register_offset (regno) /* Arguments are always put in outgoing registers (in the argument block) if such make sense. */ #ifdef OUTGOING_REGNO - regno = OUTGOING_REGNO(regno); + regno = OUTGOING_REGNO (regno); #endif return apply_args_reg_offset[regno]; } @@ -1001,7 +1014,7 @@ apply_result_size () mode = GET_MODE_WIDER_MODE (mode)) if (HARD_REGNO_MODE_OK (regno, mode) && have_insn_for (SET, mode)) - best_mode = mode; + best_mode = mode; if (best_mode == VOIDmode) for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT); @@ -1147,12 +1160,12 @@ expand_builtin_apply_args () apply_args_value = temp; - /* Put the sequence after the NOTE that starts the function. - If this is inside a SEQUENCE, make the outer-level insn + /* Put the insns after the NOTE that starts the function. + If this 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_insns_before (seq, NEXT_INSN (get_insns ())); + emit_insn_before (seq, NEXT_INSN (get_insns ())); pop_topmost_sequence (); return temp; } @@ -1214,7 +1227,7 @@ expand_builtin_apply (function, arguments, argsize) set_mem_align (dest, PARM_BOUNDARY); src = gen_rtx_MEM (BLKmode, incoming_args); set_mem_align (src, PARM_BOUNDARY); - emit_block_move (dest, src, argsize); + emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL); /* Refer to the argument block. */ apply_args_size (); @@ -1249,7 +1262,7 @@ expand_builtin_apply (function, arguments, argsize) emit_move_insn (value, adjust_address (arguments, Pmode, size)); emit_move_insn (struct_value_rtx, value); if (GET_CODE (struct_value_rtx) == REG) - use_reg (&call_fusage, struct_value_rtx); + use_reg (&call_fusage, struct_value_rtx); size += GET_MODE_SIZE (Pmode); } @@ -1381,7 +1394,7 @@ expand_builtin_return (result) } /* Put the USE insns before the return. */ - emit_insns (call_fusage); + emit_insn (call_fusage); /* Return whatever values was restored by jumping directly to the end of the function. */ @@ -1470,6 +1483,7 @@ expand_builtin_mathfn (exp, target, subtarget) rtx op0, insns; tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); tree arglist = TREE_OPERAND (exp, 1); + enum machine_mode argmode; if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) return 0; @@ -1512,14 +1526,22 @@ expand_builtin_mathfn (exp, target, subtarget) case BUILT_IN_SQRTF: case BUILT_IN_SQRTL: builtin_optab = sqrt_optab; break; - default: + case BUILT_IN_EXP: + case BUILT_IN_EXPF: + case BUILT_IN_EXPL: + builtin_optab = exp_optab; break; + case BUILT_IN_LOG: + case BUILT_IN_LOGF: + case BUILT_IN_LOGL: + builtin_optab = log_optab; break; + default: abort (); } /* Compute into TARGET. Set TARGET to wherever the result comes back. */ - target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))), - builtin_optab, op0, target, 0); + argmode = TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))); + target = expand_unop (argmode, builtin_optab, op0, target, 0); /* If we were unable to expand via the builtin, stop the sequence (without outputting the insns) and return 0, causing @@ -1530,18 +1552,12 @@ expand_builtin_mathfn (exp, target, subtarget) return 0; } - /* If errno must be maintained and if we are not allowing unsafe - math optimizations, check the result. */ + /* If errno must be maintained, we must set it to EDOM for NaN results. */ - if (flag_errno_math && ! flag_unsafe_math_optimizations) + if (flag_errno_math && HONOR_NANS (argmode)) { rtx lab1; - /* Don't define the builtin FP instructions - if your machine is not IEEE. */ - if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT) - abort (); - lab1 = gen_label_rtx (); /* Test the result; if it is NaN, set errno=EDOM because @@ -1550,16 +1566,16 @@ expand_builtin_mathfn (exp, target, subtarget) 0, lab1); #ifdef TARGET_EDOM - { + { #ifdef GEN_ERRNO_RTX - rtx errno_rtx = GEN_ERRNO_RTX; + rtx errno_rtx = GEN_ERRNO_RTX; #else - rtx errno_rtx - = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno")); + rtx errno_rtx + = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno")); #endif - emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM)); - } + emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM)); + } #else /* We can't set errno=EDOM directly; let the library call do it. Pop the arguments right away in case the call gets deleted. */ @@ -1574,7 +1590,7 @@ expand_builtin_mathfn (exp, target, subtarget) /* Output the entire sequence. */ insns = get_insns (); end_sequence (); - emit_insns (insns); + emit_insn (insns); return target; } @@ -1636,7 +1652,7 @@ expand_builtin_strlen (exp, target) /* Mark the beginning of the strlen sequence so we can emit the source operand later. */ - before_strlen = get_last_insn(); + before_strlen = get_last_insn (); char_rtx = const0_rtx; char_mode = insn_data[(int) icode].operand[2].mode; @@ -1656,7 +1672,7 @@ expand_builtin_strlen (exp, target) expand_expr (src, src_reg, ptr_mode, EXPAND_SUM)); if (pat != src_reg) emit_move_insn (src_reg, pat); - pat = gen_sequence (); + pat = get_insns (); end_sequence (); if (before_strlen) @@ -1942,20 +1958,20 @@ expand_builtin_memcpy (arglist, target, mode) /* If DEST is not a pointer type, call the normal function. */ if (dest_align == 0) - return 0; + return 0; /* If the LEN parameter is zero, return DEST. */ if (host_integerp (len, 1) && 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); - } + { + /* 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) - return 0; + return 0; dest_mem = get_memory_rtx (dest); set_mem_align (dest_mem, dest_align); @@ -1974,17 +1990,29 @@ expand_builtin_memcpy (arglist, target, mode) store_by_pieces (dest_mem, INTVAL (len_rtx), builtin_memcpy_read_str, (PTR) src_str, dest_align); - return force_operand (XEXP (dest_mem, 0), NULL_RTX); + dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); +#ifdef POINTERS_EXTEND_UNSIGNED + if (GET_MODE (dest_mem) != ptr_mode) + dest_mem = convert_memory_address (ptr_mode, dest_mem); +#endif + return dest_mem; } src_mem = get_memory_rtx (src); set_mem_align (src_mem, src_align); /* Copy word part most expediently. */ - dest_addr = emit_block_move (dest_mem, src_mem, len_rtx); + dest_addr = emit_block_move (dest_mem, src_mem, len_rtx, + BLOCK_OP_NORMAL); if (dest_addr == 0) - dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX); + { + dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX); +#ifdef POINTERS_EXTEND_UNSIGNED + if (GET_MODE (dest_addr) != ptr_mode) + dest_addr = convert_memory_address (ptr_mode, dest_addr); +#endif + } return dest_addr; } @@ -2002,7 +2030,7 @@ expand_builtin_strcpy (exp, target, mode) enum machine_mode mode; { tree arglist = TREE_OPERAND (exp, 1); - tree fn, len; + tree fn, len, src, dst; if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) return 0; @@ -2011,14 +2039,18 @@ expand_builtin_strcpy (exp, target, mode) if (!fn) return 0; - len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist))); - if (len == 0) + src = TREE_VALUE (TREE_CHAIN (arglist)); + len = c_strlen (src); + if (len == 0 || TREE_SIDE_EFFECTS (len)) return 0; + dst = TREE_VALUE (arglist); len = size_binop (PLUS_EXPR, len, ssize_int (1)); - chainon (arglist, build_tree_list (NULL_TREE, len)); + 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); + target, mode, EXPAND_NORMAL); } /* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE) @@ -2063,9 +2095,9 @@ expand_builtin_strncpy (arglist, target, mode) /* If the len parameter is zero, return the dst parameter. */ if (integer_zerop (len)) - { - /* Evaluate and ignore the src argument in case it has - side-effects. */ + { + /* 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. */ @@ -2100,15 +2132,20 @@ expand_builtin_strncpy (arglist, target, mode) store_by_pieces (dest_mem, tree_low_cst (len, 1), builtin_strncpy_read_str, (PTR) p, dest_align); - return force_operand (XEXP (dest_mem, 0), NULL_RTX); + dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); +#ifdef POINTERS_EXTEND_UNSIGNED + if (GET_MODE (dest_mem) != ptr_mode) + dest_mem = convert_memory_address (ptr_mode, dest_mem); +#endif + return dest_mem; } /* OK transform into builtin memcpy. */ fn = built_in_decls[BUILT_IN_MEMCPY]; if (!fn) - return 0; + return 0; return expand_expr (build_function_call_expr (fn, arglist), - target, mode, EXPAND_NORMAL); + target, mode, EXPAND_NORMAL); } } @@ -2130,6 +2167,34 @@ builtin_memset_read_str (data, offset, mode) return c_readstr (p, mode); } +/* Callback routine for store_by_pieces. Return the RTL of a register + containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned + char value given in the RTL register data. For example, if mode is + 4 bytes wide, return the RTL for 0x01010101*data. */ + +static rtx +builtin_memset_gen_str (data, offset, mode) + PTR data; + HOST_WIDE_INT offset ATTRIBUTE_UNUSED; + enum machine_mode mode; +{ + rtx target, coeff; + size_t size; + char *p; + + size = GET_MODE_SIZE (mode); + if (size == 1) + return (rtx) data; + + p = alloca (size); + memset (p, 1, size); + coeff = c_readstr (p, mode); + + target = convert_to_mode (mode, (rtx) data, 1); + target = expand_mult (mode, target, coeff, NULL_RTX, 1); + return force_reg (mode, target); +} + /* Expand expression EXP, which is a call to the memset 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 @@ -2164,14 +2229,46 @@ expand_builtin_memset (exp, target, mode) /* If the LEN parameter is zero, return DEST. */ if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0) - { - /* Evaluate and ignore VAL in case it has side-effects. */ - expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL); - return expand_expr (dest, target, mode, EXPAND_NORMAL); - } + { + /* Evaluate and ignore VAL in case it has side-effects. */ + expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL); + return expand_expr (dest, target, mode, EXPAND_NORMAL); + } if (TREE_CODE (val) != INTEGER_CST) - return 0; + { + rtx val_rtx; + + if (!host_integerp (len, 1)) + return 0; + + if (optimize_size && tree_low_cst (len, 1) > 1) + return 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, + (PTR) &c, dest_align)) + return 0; + + 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, + (PTR) val_rtx, dest_align); + dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); +#ifdef POINTERS_EXTEND_UNSIGNED + if (GET_MODE (dest_mem) != ptr_mode) + dest_mem = convert_memory_address (ptr_mode, dest_mem); +#endif + return dest_mem; + } if (target_char_cast (val, &c)) return 0; @@ -2189,7 +2286,12 @@ expand_builtin_memset (exp, target, mode) store_by_pieces (dest_mem, tree_low_cst (len, 1), builtin_memset_read_str, (PTR) &c, dest_align); - return force_operand (XEXP (dest_mem, 0), NULL_RTX); + dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); +#ifdef POINTERS_EXTEND_UNSIGNED + if (GET_MODE (dest_mem) != ptr_mode) + dest_mem = convert_memory_address (ptr_mode, dest_mem); +#endif + return dest_mem; } len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0); @@ -2199,7 +2301,13 @@ expand_builtin_memset (exp, target, mode) dest_addr = clear_storage (dest_mem, len_rtx); if (dest_addr == 0) - dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX); + { + dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX); +#ifdef POINTERS_EXTEND_UNSIGNED + if (GET_MODE (dest_addr) != ptr_mode) + dest_addr = convert_memory_address (ptr_mode, dest_addr); +#endif + } return dest_addr; } @@ -2256,7 +2364,7 @@ expand_builtin_memcmp (exp, arglist, target, mode) const char *p1, *p2; if (!validate_arglist (arglist, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) + POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) return 0; arg1 = TREE_VALUE (arglist); @@ -2295,12 +2403,12 @@ expand_builtin_memcmp (exp, arglist, target, mode) 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)))); + 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)))); + 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); } @@ -2437,12 +2545,12 @@ expand_builtin_strcmp (exp, target, mode) if (!len || TREE_CODE (len) != INTEGER_CST) { if (len2 && !TREE_SIDE_EFFECTS (len2)) - len = len2; + len = len2; else if (len == 0) - return 0; + return 0; } else if (len2 && TREE_CODE (len2) == INTEGER_CST - && tree_int_cst_lt (len2, len)) + && tree_int_cst_lt (len2, len)) len = len2; /* If both arguments have side effects, we cannot optimize. */ @@ -2453,9 +2561,11 @@ expand_builtin_strcmp (exp, target, mode) if (!fn) return 0; - chainon (arglist, build_tree_list (NULL_TREE, len)); + arglist = build_tree_list (NULL_TREE, len); + arglist = tree_cons (NULL_TREE, arg2, arglist); + arglist = tree_cons (NULL_TREE, arg1, arglist); return expand_expr (build_function_call_expr (fn, arglist), - target, mode, EXPAND_NORMAL); + target, mode, EXPAND_NORMAL); } /* Expand expression EXP, which is a call to the strncmp builtin. Return 0 @@ -2483,23 +2593,23 @@ expand_builtin_strncmp (exp, target, mode) /* If the len parameter is zero, return zero. */ if (host_integerp (arg3, 1) && tree_low_cst (arg3, 1) == 0) - { - /* 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; - } + { + /* 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; + } 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)); - } + { + 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). */ @@ -2557,7 +2667,7 @@ expand_builtin_strncmp (exp, target, mode) newarglist = tree_cons (NULL_TREE, arg2, newarglist); newarglist = tree_cons (NULL_TREE, arg1, newarglist); return expand_expr (build_function_call_expr (fn, newarglist), - target, mode, EXPAND_NORMAL); + target, mode, EXPAND_NORMAL); } /* Expand expression EXP, which is a call to the strcat builtin. @@ -2609,7 +2719,7 @@ expand_builtin_strncat (arglist, target, mode) /* 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); @@ -2621,7 +2731,7 @@ expand_builtin_strncat (arglist, target, mode) 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 = built_in_decls[BUILT_IN_STRCAT]; @@ -2657,14 +2767,14 @@ expand_builtin_strspn (arglist, target, mode) /* 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); @@ -2694,14 +2804,14 @@ expand_builtin_strcspn (arglist, target, mode) /* 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); @@ -2710,7 +2820,7 @@ expand_builtin_strcspn (arglist, target, mode) /* If the second argument is "", return __builtin_strlen(s1). */ if (p2 && *p2 == '\0') - { + { tree newarglist = build_tree_list (NULL_TREE, s1), fn = built_in_decls[BUILT_IN_STRLEN]; @@ -2766,11 +2876,11 @@ expand_builtin_saveregs () saveregs_value = val; - /* Put the sequence after the NOTE that starts the function. If this - is inside a SEQUENCE, make the outer-level insn chain current, so + /* Put the insns after the NOTE that starts the function. If this + 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_insns_after (seq, get_insns ()); + emit_insn_after (seq, get_insns ()); pop_topmost_sequence (); return val; @@ -2838,10 +2948,9 @@ expand_builtin_next_arg (arglist) { tree fntype = TREE_TYPE (current_function_decl); - if ((TYPE_ARG_TYPES (fntype) == 0 - || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) - == void_type_node)) - && ! current_function_varargs) + 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; @@ -2864,7 +2973,7 @@ expand_builtin_next_arg (arglist) if (arg != last_parm) warning ("second parameter of `va_start' not last named argument"); } - else if (! current_function_varargs) + 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"); @@ -2928,25 +3037,12 @@ stabilize_va_list (valist, needs_lvalue) the variable. */ void -std_expand_builtin_va_start (stdarg_p, valist, nextarg) - int stdarg_p; +std_expand_builtin_va_start (valist, nextarg) tree valist; rtx nextarg; { tree t; - if (! stdarg_p) - { - /* The dummy named parameter is declared as a 'word' sized - object, but if a 'word' is smaller than an 'int', it would - have been promoted to int when it was added to the arglist. */ - int align = PARM_BOUNDARY / BITS_PER_UNIT; - int size = MAX (UNITS_PER_WORD, - GET_MODE_SIZE (TYPE_MODE (integer_type_node))); - int offset = ((size + align - 1) / align) * align; - nextarg = plus_constant (nextarg, -offset); - } - t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, make_tree (ptr_type_node, nextarg)); TREE_SIDE_EFFECTS (t) = 1; @@ -2954,31 +3050,27 @@ std_expand_builtin_va_start (stdarg_p, valist, nextarg) expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); } -/* Expand ARGLIST, which from a call to __builtin_stdarg_va_start or - __builtin_varargs_va_start, depending on STDARG_P. */ +/* Expand ARGLIST, from a call to __builtin_va_start. */ static rtx -expand_builtin_va_start (stdarg_p, arglist) - int stdarg_p; +expand_builtin_va_start (arglist) tree arglist; { rtx nextarg; - tree chain = arglist, valist; + tree chain, valist; - if (stdarg_p) - nextarg = expand_builtin_next_arg (chain = TREE_CHAIN (arglist)); - else - nextarg = expand_builtin_next_arg (NULL_TREE); + chain = TREE_CHAIN (arglist); if (TREE_CHAIN (chain)) error ("too many arguments to function `va_start'"); + nextarg = expand_builtin_next_arg (chain); valist = stabilize_va_list (TREE_VALUE (arglist), 1); #ifdef EXPAND_BUILTIN_VA_START - EXPAND_BUILTIN_VA_START (stdarg_p, valist, nextarg); + EXPAND_BUILTIN_VA_START (valist, nextarg); #else - std_expand_builtin_va_start (stdarg_p, valist, nextarg); + std_expand_builtin_va_start (valist, nextarg); #endif return const0_rtx; @@ -3078,7 +3170,8 @@ expand_builtin_va_arg (valist, type) /* 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_type_promotes_to) (type)) != NULL_TREE) + else if ((promoted_type = (*lang_hooks.types.type_promotes_to) (type)) + != type) { const char *name = "<anonymous type>", *pname = 0; static bool gave_help; @@ -3154,7 +3247,7 @@ expand_builtin_va_end (arglist) #ifdef EXPAND_BUILTIN_VA_END valist = stabilize_va_list (valist, 0); - EXPAND_BUILTIN_VA_END(arglist); + EXPAND_BUILTIN_VA_END (arglist); #else /* Evaluate for side effects, if needed. I hate macros that don't do that. */ @@ -3214,7 +3307,7 @@ expand_builtin_va_copy (arglist) set_mem_align (srcb, TYPE_ALIGN (va_list_type_node)); /* Copy. */ - emit_block_move (dstb, srcb, size); + emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL); } return const0_rtx; @@ -3385,8 +3478,12 @@ expand_builtin_fputs (arglist, ignore, unlocked) /* FALLTHROUGH */ case 1: /* length is greater than 1, call fwrite. */ { - tree string_arg = TREE_VALUE (arglist); + 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))); @@ -3432,7 +3529,7 @@ expand_builtin_expect (arglist, target) target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL); /* Don't bother with expected value notes for integral constants. */ - if (GET_CODE (target) != CONST_INT) + if (flag_guess_branch_prob && GET_CODE (target) != CONST_INT) { /* We do need to force this into a register so that we can be moderately sure to be able to correctly interpret the branch @@ -3450,7 +3547,7 @@ expand_builtin_expect (arglist, target) /* Like expand_builtin_expect, except do this in a jump context. This is called from do_jump if the conditional is a __builtin_expect. Return either - a SEQUENCE of insns to emit the jump or NULL if we cannot optimize + a list of insns to emit the jump or NULL if we cannot optimize __builtin_expect. We need to optimize this at jump time so that machines like the PowerPC don't turn the test into a SCC operation, and then jump based on the test being 0/1. */ @@ -3471,8 +3568,8 @@ expand_builtin_expect_jump (exp, if_false_label, if_true_label) if (TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE && (integer_zerop (arg1) || integer_onep (arg1))) { - int j; int num_jumps = 0; + rtx insn; /* If we fail to locate an appropriate conditional jump, we'll fall back to normal evaluation. Ensure that the expression @@ -3493,16 +3590,17 @@ expand_builtin_expect_jump (exp, if_false_label, if_true_label) /* Expand the jump insns. */ start_sequence (); do_jump (arg0, if_false_label, if_true_label); - ret = gen_sequence (); + ret = get_insns (); end_sequence (); /* Now that the __builtin_expect has been validated, go through and add the expect's to each of the conditional jumps. If we run into an error, just give up and generate the 'safe' code of doing a SCC operation and then doing a branch on that. */ - for (j = 0; j < XVECLEN (ret, 0); j++) + insn = ret; + while (insn != NULL_RTX) { - rtx insn = XVECEXP (ret, 0, j); + rtx next = NEXT_INSN (insn); rtx pattern; if (GET_CODE (insn) == JUMP_INSN && any_condjump_p (insn) @@ -3513,7 +3611,7 @@ expand_builtin_expect_jump (exp, if_false_label, if_true_label) int taken; if (GET_CODE (ifelse) != IF_THEN_ELSE) - continue; + goto do_next_insn; if (GET_CODE (XEXP (ifelse, 1)) == LABEL_REF) { @@ -3540,7 +3638,7 @@ expand_builtin_expect_jump (exp, if_false_label, if_true_label) label = NULL_RTX; } else - continue; + goto do_next_insn; /* If the test is expected to fail, reverse the probabilities. */ @@ -3554,11 +3652,14 @@ expand_builtin_expect_jump (exp, if_false_label, if_true_label) else if (label == if_false_label) taken = 1 - taken; else if (label != if_true_label) - continue; + goto do_next_insn; num_jumps++; predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken); } + + do_next_insn: + insn = next; } /* If no jumps were modified, fail and do __builtin_expect the normal @@ -3600,6 +3701,9 @@ expand_builtin (exp, target, subtarget, mode, ignore) tree arglist = TREE_OPERAND (exp, 1); enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); + /* 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); @@ -3608,11 +3712,18 @@ expand_builtin (exp, target, subtarget, mode, ignore) if (!optimize && !CALLED_AS_BUILT_IN (fndecl)) switch (fcode) { - case BUILT_IN_SIN: - case BUILT_IN_COS: case BUILT_IN_SQRT: case BUILT_IN_SQRTF: case BUILT_IN_SQRTL: + 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_MEMSET: case BUILT_IN_MEMCPY: case BUILT_IN_MEMCMP: @@ -3646,11 +3757,11 @@ expand_builtin (exp, target, subtarget, mode, ignore) case BUILT_IN_FPUTC_UNLOCKED: case BUILT_IN_FPUTS_UNLOCKED: case BUILT_IN_FWRITE_UNLOCKED: - return expand_call (exp, target, ignore); + return expand_call (exp, target, ignore); default: - break; - } + break; + } switch (fcode) { @@ -3683,6 +3794,12 @@ expand_builtin (exp, target, subtarget, mode, ignore) 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: /* Treat these like sqrt only if unsafe math optimizations are allowed, because of possible accuracy problems. */ if (! flag_unsafe_math_optimizations) @@ -3695,9 +3812,6 @@ expand_builtin (exp, target, subtarget, mode, ignore) return target; break; - case BUILT_IN_FMOD: - break; - case BUILT_IN_APPLY_ARGS: return expand_builtin_apply_args (); @@ -3762,11 +3876,11 @@ expand_builtin (exp, target, subtarget, mode, ignore) 0 otherwise. */ 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) - return const0_rtx; + || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))) + || GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM) + return const0_rtx; else - return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0); + return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0); case BUILT_IN_ALLOCA: target = expand_builtin_alloca (arglist, target); @@ -3918,15 +4032,6 @@ expand_builtin (exp, target, subtarget, mode, ignore) expand_builtin_trap (); return const0_rtx; - case BUILT_IN_PUTCHAR: - case BUILT_IN_PUTS: - case BUILT_IN_FPUTC: - case BUILT_IN_FWRITE: - case BUILT_IN_PUTCHAR_UNLOCKED: - case BUILT_IN_PUTS_UNLOCKED: - case BUILT_IN_FPUTC_UNLOCKED: - case BUILT_IN_FWRITE_UNLOCKED: - break; case BUILT_IN_FPUTS: target = expand_builtin_fputs (arglist, ignore,/*unlocked=*/ 0); if (target) @@ -3945,8 +4050,8 @@ expand_builtin (exp, target, subtarget, mode, ignore) case BUILT_IN_DWARF_CFA: return virtual_cfa_rtx; #ifdef DWARF2_UNWIND_INFO - case BUILT_IN_DWARF_FP_REGNUM: - return expand_builtin_dwarf_fp_regnum (); + case BUILT_IN_DWARF_SP_COLUMN: + return expand_builtin_dwarf_sp_column (); case BUILT_IN_INIT_DWARF_REG_SIZES: expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist)); return const0_rtx; @@ -3963,10 +4068,9 @@ expand_builtin (exp, target, subtarget, mode, ignore) case BUILT_IN_EH_RETURN_DATA_REGNO: return expand_builtin_eh_return_data_regno (arglist); #endif - case BUILT_IN_VARARGS_START: - return expand_builtin_va_start (0, arglist); + case BUILT_IN_VA_START: case BUILT_IN_STDARG_START: - return expand_builtin_va_start (1, arglist); + return expand_builtin_va_start (arglist); case BUILT_IN_VA_END: return expand_builtin_va_end (arglist); case BUILT_IN_VA_COPY: @@ -3978,9 +4082,10 @@ expand_builtin (exp, target, subtarget, mode, ignore) return const0_rtx; - default: /* just do library call, if unknown builtin */ - error ("built-in function `%s' not currently supported", - IDENTIFIER_POINTER (DECL_NAME (fndecl))); + 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))); } /* The switch statement above can drop through to cause the function @@ -4042,6 +4147,44 @@ fold_builtin_classify_type (arglist) return build_int_2 (type_to_class (TREE_TYPE (TREE_VALUE (arglist))), 0); } +/* Fold a call to __builtin_inf or __builtin_huge_val. */ + +static tree +fold_builtin_inf (type, warn) + tree type; + int warn; +{ + REAL_VALUE_TYPE real; + + if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn) + warning ("target format does not support infinity"); + + real_inf (&real); + return build_real (type, real); +} + +/* Fold a call to __builtin_nan or __builtin_nans. */ + +static tree +fold_builtin_nan (arglist, type, quiet) + tree arglist, type; + int quiet; +{ + REAL_VALUE_TYPE real; + const char *str; + + if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE)) + return 0; + str = c_getstr (TREE_VALUE (arglist)); + if (!str) + return 0; + + if (!real_nan (&real, str, quiet, TYPE_MODE (type))) + return 0; + + return build_real (type, real); +} + /* Used by constant folding to eliminate some builtin calls early. EXP is the CALL_EXPR of a call to a builtin function. */ @@ -4078,6 +4221,26 @@ fold_builtin (exp) } break; + case BUILT_IN_INF: + case BUILT_IN_INFF: + case BUILT_IN_INFL: + return fold_builtin_inf (TREE_TYPE (TREE_TYPE (fndecl)), true); + + case BUILT_IN_HUGE_VAL: + case BUILT_IN_HUGE_VALF: + case BUILT_IN_HUGE_VALL: + return fold_builtin_inf (TREE_TYPE (TREE_TYPE (fndecl)), false); + + case BUILT_IN_NAN: + case BUILT_IN_NANF: + case BUILT_IN_NANL: + return fold_builtin_nan (arglist, TREE_TYPE (TREE_TYPE (fndecl)), true); + + case BUILT_IN_NANS: + case BUILT_IN_NANSF: + case BUILT_IN_NANSL: + return fold_builtin_nan (arglist, TREE_TYPE (TREE_TYPE (fndecl)), false); + default: break; } @@ -4112,29 +4275,32 @@ validate_arglist VPARAMS ((tree arglist, ...)) VA_OPEN (ap, arglist); VA_FIXEDARG (ap, tree, arglist); - do { - code = va_arg (ap, enum tree_code); - switch (code) + do { - case 0: - /* This signifies an ellipses, any further arguments are all ok. */ - res = 1; - goto end; - case VOID_TYPE: - /* This signifies an endlink, if no arguments remain, return - true, otherwise return false. */ - res = arglist == 0; - goto end; - default: - /* 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)))) - goto end; - break; + code = va_arg (ap, enum tree_code); + switch (code) + { + case 0: + /* This signifies an ellipses, any further arguments are all ok. */ + res = 1; + goto end; + case VOID_TYPE: + /* This signifies an endlink, if no arguments remain, return + true, otherwise return false. */ + res = arglist == 0; + goto end; + default: + /* 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)))) + goto end; + break; + } + arglist = TREE_CHAIN (arglist); } - arglist = TREE_CHAIN (arglist); - } while (1); + while (1); /* We need gotos here since we can only have one VA_CLOSE in a function. */ diff --git a/contrib/gcc/c-common.c b/contrib/gcc/c-common.c index 3511f15..b40a35a 100644 --- a/contrib/gcc/c-common.c +++ b/contrib/gcc/c-common.c @@ -22,6 +22,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "config.h" #include "system.h" #include "tree.h" +#include "real.h" #include "flags.h" #include "toplev.h" #include "output.h" @@ -30,17 +31,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "ggc.h" #include "expr.h" #include "c-common.h" -#include "tree-inline.h" #include "diagnostic.h" #include "tm_p.h" #include "obstack.h" -#include "c-lex.h" #include "cpplib.h" #include "target.h" -cpp_reader *parse_in; /* Declared in c-lex.h. */ +#include "langhooks.h" +#include "except.h" /* For USING_SJLJ_EXCEPTIONS. */ +#include "tree-inline.h" +#include "c-tree.h" -#undef WCHAR_TYPE_SIZE -#define WCHAR_TYPE_SIZE TYPE_PRECISION (wchar_type_node) +cpp_reader *parse_in; /* Declared in c-pragma.h. */ /* We let tm.h override the types used here, to handle trivial differences such as the choice of unsigned int or long unsigned int for size_t. @@ -56,6 +57,10 @@ cpp_reader *parse_in; /* Declared in c-lex.h. */ #define WCHAR_TYPE "int" #endif +/* WCHAR_TYPE gets overridden by -fshort-wchar. */ +#define MODIFIED_WCHAR_TYPE \ + (flag_short_wchar ? "short unsigned int" : WCHAR_TYPE) + #ifndef PTRDIFF_TYPE #define PTRDIFF_TYPE "long int" #endif @@ -80,6 +85,10 @@ cpp_reader *parse_in; /* Declared in c-lex.h. */ : "long long unsigned int")) #endif +#ifndef REGISTER_PREFIX +#define REGISTER_PREFIX "" +#endif + /* The variant of the C language being processed. */ enum c_language_kind c_language; @@ -180,6 +189,22 @@ enum c_language_kind c_language; tree c_global_trees[CTI_MAX]; +/* Switches common to the C front ends. */ + +/* Nonzero if prepreprocessing only. */ +int flag_preprocess_only; + +/* Nonzero if an ISO standard was selected. It rejects macros in the + user's namespace. */ +int flag_iso; + +/* Nonzero whenever Objective-C functionality is being used. */ +int flag_objc; + +/* Nonzero if -undef was given. It suppresses target built-in macros + and assertions. */ +int flag_undef; + /* Nonzero means don't recognize the non-ANSI builtin functions. */ int flag_no_builtin; @@ -197,6 +222,180 @@ int flag_short_double; int flag_short_wchar; +/* Nonzero means allow Microsoft extensions without warnings or errors. */ +int flag_ms_extensions; + +/* Nonzero means don't recognize the keyword `asm'. */ + +int flag_no_asm; + +/* Nonzero means give string constants the type `const char *', as mandated + by the standard. */ + +int flag_const_strings; + +/* Nonzero means `$' can be in an identifier. */ + +#ifndef DOLLARS_IN_IDENTIFIERS +#define DOLLARS_IN_IDENTIFIERS 1 +#endif +int dollars_in_ident = DOLLARS_IN_IDENTIFIERS; + +/* 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 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. */ + +int warn_sign_compare; + +/* 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. */ + +int warn_unknown_pragmas; /* Tri state variable. */ + +/* Warn about format/argument anomalies in calls to formatted I/O functions + (*printf, *scanf, strftime, strfmon, etc.). */ + +int warn_format; + +/* Warn about Y2K problems with strftime formats. */ + +int warn_format_y2k; + +/* Warn about excess arguments to formats. */ + +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; + + +/* 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'. */ + +int flag_cond_mismatch; + +/* Nonzero means enable C89 Amendment 1 features. */ + +int flag_isoc94; + +/* Nonzero means use the ISO C99 dialect of C. */ + +int flag_isoc99; + +/* Nonzero means that we have builtin functions, and main is an int */ + +int flag_hosted = 1; + +/* Nonzero means add default format_arg attributes for functions not + in ISO C. */ + +int flag_noniso_default_format_attributes = 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 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; @@ -204,6 +403,254 @@ int warn_sequence_point; /* 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; + + +/* ObjC language option variables. */ + + +/* Open and close the file for outputting class declarations, if + requested (ObjC). */ + +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. */ + +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. */ + + +/* Nonzero means don't recognize any extension keywords. */ + +int flag_no_gnu_keywords; + +/* Nonzero means do emit exported implementations of functions even if + they can be inlined. */ + +int flag_implement_inlines = 1; + +/* Nonzero means do emit exported implementations of templates, instead of + multiple static copies in each file that needs a definition. */ + +int flag_external_templates; + +/* Nonzero means that the decision to emit or not emit the implementation of a + template depends on where the template is instantiated, rather than where + it is defined. */ + +int flag_alt_external_templates; + +/* Nonzero means that implicit instantiations will be emitted if needed. */ + +int flag_implicit_templates = 1; + +/* Nonzero means that implicit instantiations of inline templates will be + emitted if needed, even if instantiations of non-inline templates + aren't. */ + +int flag_implicit_inline_templates = 1; + +/* Nonzero means generate separate instantiation control files and + juggle them at link time. */ + +int flag_use_repository; + +/* Nonzero if we want to issue diagnostics that the standard says are not + required. */ + +int flag_optional_diags = 1; + +/* Nonzero means we should attempt to elide constructors when possible. */ + +int flag_elide_constructors = 1; + +/* Nonzero means that member functions defined in class scope are + inline by default. */ + +int flag_default_inline = 1; + +/* Controls whether compiler generates 'type descriptor' that give + run-time type information. */ + +int flag_rtti = 1; + +/* Nonzero if we want to conserve space in the .o files. We do this + by putting uninitialized data and runtime initialized data into + .common instead of .data at the expense of not flagging multiple + definitions. */ + +int flag_conserve_space; + +/* Nonzero if we want to obey access control semantics. */ + +int flag_access_control = 1; + +/* Nonzero if we want to check the return value of new and avoid calling + constructors if it is a null pointer. */ + +int flag_check_new; + +/* Nonzero if we want the new ISO rules for pushing a new scope for `for' + initialization variables. + 0: Old rules, set by -fno-for-scope. + 2: New ISO rules, set by -ffor-scope. + 1: Try to implement new ISO rules, but with backup compatibility + (and warnings). This is the default, for now. */ + +int flag_new_for_scope = 1; + +/* Nonzero if we want to emit defined symbols with common-like linkage as + weak symbols where possible, in order to conform to C++ semantics. + Otherwise, emit them as local symbols. */ + +int flag_weak = 1; + +/* Nonzero to use __cxa_atexit, rather than atexit, to register + destructors for local statics and global objects. */ + +int flag_use_cxa_atexit = DEFAULT_USE_CXA_ATEXIT; + +/* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc. */ + +int flag_vtable_gc; + +/* Nonzero means make the default pedwarns warnings instead of errors. + The value of this flag is ignored if -pedantic is specified. */ + +int flag_permissive; + +/* Nonzero means to implement standard semantics for exception + specifications, calling unexpected if an exception is thrown that + doesn't match the specification. Zero means to treat them as + assertions and optimize accordingly, but not check them. */ + +int flag_enforce_eh_specs = 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. + + Additional positive integers will be assigned as new versions of + the ABI become the default version of the ABI. */ + +int flag_abi_version = 1; + +/* Nonzero means warn about things that will change when compiling + with an ABI-compliant compiler. */ + +int warn_abi = 0; + +/* 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 = 1; + +/* 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. */ + +int max_tinst_depth = 500; + + + /* The elements of `ridpointers' are identifier nodes for the reserved type names and storage classes. It is indexed by a RID_... value. */ tree *ridpointers; @@ -267,6 +714,169 @@ static int if_stack_space = 0; /* Stack pointer. */ static int if_stack_pointer = 0; +static tree handle_packed_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_nocommon_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_common_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_noreturn_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_noinline_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_always_inline_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_used_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_unused_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_const_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_transparent_union_attribute PARAMS ((tree *, tree, tree, + int, bool *)); +static tree handle_constructor_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_destructor_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_mode_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_section_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_aligned_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_weak_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_alias_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_visibility_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_tls_model_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_no_instrument_function_attribute PARAMS ((tree *, tree, + tree, int, + bool *)); +static tree handle_malloc_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_no_limit_stack_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_pure_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_deprecated_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_vector_size_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_nonnull_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_nothrow_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree handle_cleanup_attribute PARAMS ((tree *, tree, tree, int, + bool *)); +static tree vector_size_helper PARAMS ((tree, tree)); + +static void check_function_nonnull PARAMS ((tree, tree)); +static void check_nonnull_arg PARAMS ((void *, tree, + unsigned HOST_WIDE_INT)); +static bool nonnull_check_p PARAMS ((tree, unsigned HOST_WIDE_INT)); +static bool get_nonnull_operand PARAMS ((tree, + unsigned HOST_WIDE_INT *)); +void builtin_define_std PARAMS ((const char *)); +static void builtin_define_with_value PARAMS ((const char *, const char *, + int)); +static void builtin_define_with_int_value PARAMS ((const char *, + HOST_WIDE_INT)); +static void builtin_define_with_hex_fp_value PARAMS ((const char *, tree, + int, const char *, + const char *)); +static void builtin_define_type_max PARAMS ((const char *, tree, int)); +static void builtin_define_type_precision PARAMS ((const char *, tree)); +static void builtin_define_float_constants PARAMS ((const char *, + const char *, tree)); + +/* Table of machine-independent attributes common to all C-like languages. */ +const struct attribute_spec c_common_attribute_table[] = +{ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ + { "packed", 0, 0, false, false, false, + handle_packed_attribute }, + { "nocommon", 0, 0, true, false, false, + handle_nocommon_attribute }, + { "common", 0, 0, true, false, false, + handle_common_attribute }, + /* FIXME: logically, noreturn attributes should be listed as + "false, true, true" and apply to function types. But implementing this + would require all the places in the compiler that use TREE_THIS_VOLATILE + on a decl to identify non-returning functions to be located and fixed + to check the function type instead. */ + { "noreturn", 0, 0, true, false, false, + handle_noreturn_attribute }, + { "volatile", 0, 0, true, false, false, + handle_noreturn_attribute }, + { "noinline", 0, 0, true, false, false, + handle_noinline_attribute }, + { "always_inline", 0, 0, true, false, false, + handle_always_inline_attribute }, + { "used", 0, 0, true, false, false, + handle_used_attribute }, + { "unused", 0, 0, false, false, false, + handle_unused_attribute }, + /* The same comments as for noreturn attributes apply to const ones. */ + { "const", 0, 0, true, false, false, + handle_const_attribute }, + { "transparent_union", 0, 0, false, false, false, + handle_transparent_union_attribute }, + { "constructor", 0, 0, true, false, false, + handle_constructor_attribute }, + { "destructor", 0, 0, true, false, false, + handle_destructor_attribute }, + { "mode", 1, 1, false, true, false, + handle_mode_attribute }, + { "section", 1, 1, true, false, false, + handle_section_attribute }, + { "aligned", 0, 1, false, false, false, + handle_aligned_attribute }, + { "weak", 0, 0, true, false, false, + handle_weak_attribute }, + { "alias", 1, 1, true, false, false, + handle_alias_attribute }, + { "no_instrument_function", 0, 0, true, false, false, + handle_no_instrument_function_attribute }, + { "malloc", 0, 0, true, false, false, + handle_malloc_attribute }, + { "no_stack_limit", 0, 0, true, false, false, + handle_no_limit_stack_attribute }, + { "pure", 0, 0, true, false, false, + handle_pure_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, + handle_visibility_attribute }, + { "tls_model", 1, 1, true, false, false, + handle_tls_model_attribute }, + { "nonnull", 0, -1, false, true, true, + handle_nonnull_attribute }, + { "nothrow", 0, 0, true, false, false, + handle_nothrow_attribute }, + { "may_alias", 0, 0, false, true, false, NULL }, + { "cleanup", 1, 1, true, false, false, + handle_cleanup_attribute }, + { NULL, 0, 0, false, false, false, NULL } +}; + +/* Give the specifications for the format attributes, used by C and all + descendents. */ + +const struct attribute_spec c_common_format_attribute_table[] = +{ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ + { "format", 3, 3, false, true, true, + handle_format_attribute }, + { "format_arg", 1, 1, false, true, true, + handle_format_arg_attribute }, + { NULL, 0, 0, false, false, false, NULL } +}; + /* Record the start of an if-then, and record the start of it for ambiguous else detection. @@ -483,7 +1093,7 @@ fname_as_string (pretty_p) if (pretty_p) name = (current_function_decl - ? (*decl_printable_name) (current_function_decl, 2) + ? (*lang_hooks.decl_printable_name) (current_function_decl, 2) : "top level"); else if (current_function_decl && DECL_NAME (current_function_decl)) name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl)); @@ -530,6 +1140,13 @@ fname_decl (rid, id) 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 = lineno; + lineno = 0; decl = (*make_fname_decl) (id, fname_vars[ix].pretty); if (last_tree != saved_last_tree) @@ -545,6 +1162,7 @@ fname_decl (rid, id) saved_function_name_decls); } *fname_vars[ix].decl = decl; + lineno = saved_lineno; } if (!ix && !current_function_decl) pedwarn_with_decl (decl, "`%s' is not defined outside of function scope"); @@ -552,136 +1170,152 @@ fname_decl (rid, id) return decl; } -/* Given a chain of STRING_CST nodes, - concatenate them into one STRING_CST - and give it a suitable array-of-chars data type. */ +/* Given a STRING_CST, give it a suitable array-of-chars data type. */ + +tree +fix_string_type (value) + 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; + + /* Compute the number of elements, for the array type. */ + nchars = wide_flag ? length / wchar_bytes : length; + + if (pedantic && nchars - 1 > nchars_max && c_language == clk_c) + 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))); + + TREE_CONSTANT (value) = 1; + TREE_READONLY (value) = ! flag_writable_strings; + TREE_STATIC (value) = 1; + return value; +} + +/* Given a VARRAY of STRING_CST nodes, concatenate them into one + STRING_CST. */ tree combine_strings (strings) - tree strings; + varray_type strings; { + const int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT; + const int nstrings = VARRAY_ACTIVE_SIZE (strings); tree value, t; int length = 1; int wide_length = 0; int wide_flag = 0; - int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT; - int nchars; - const int nchars_max = flag_isoc99 ? 4095 : 509; + int i; + char *p, *q; - if (TREE_CHAIN (strings)) + /* Don't include the \0 at the end of each substring. Count wide + strings and ordinary strings separately. */ + for (i = 0; i < nstrings; ++i) { - /* More than one in the chain, so concatenate. */ - char *p, *q; + t = VARRAY_TREE (strings, i); - /* Don't include the \0 at the end of each substring, - except for the last one. - Count wide strings and ordinary strings separately. */ - for (t = strings; t; t = TREE_CHAIN (t)) + if (TREE_TYPE (t) == wchar_array_type_node) { - if (TREE_TYPE (t) == wchar_array_type_node) - { - wide_length += (TREE_STRING_LENGTH (t) - wchar_bytes); - wide_flag = 1; - } - else - { - length += (TREE_STRING_LENGTH (t) - 1); - if (C_ARTIFICIAL_STRING_P (t) && !in_system_header) - warning ("concatenation of string literals with __FUNCTION__ is deprecated"); - } + wide_length += TREE_STRING_LENGTH (t) - wchar_bytes; + wide_flag = 1; + } + else + { + length += (TREE_STRING_LENGTH (t) - 1); + if (C_ARTIFICIAL_STRING_P (t) && !in_system_header) + warning ("concatenation of string literals with __FUNCTION__ is deprecated"); } + } + + /* If anything is wide, the non-wides will be converted, + which makes them take more space. */ + if (wide_flag) + length = length * wchar_bytes + wide_length; - /* If anything is wide, the non-wides will be converted, - which makes them take more space. */ - if (wide_flag) - length = length * wchar_bytes + wide_length; + p = xmalloc (length); - p = xmalloc (length); + /* Copy the individual strings into the new combined string. + If the combined string is wide, convert the chars to ints + for any individual strings that are not wide. */ - /* Copy the individual strings into the new combined string. - If the combined string is wide, convert the chars to ints - for any individual strings that are not wide. */ + q = p; + for (i = 0; i < nstrings; ++i) + { + int len, this_wide; - q = p; - for (t = strings; t; t = TREE_CHAIN (t)) + t = VARRAY_TREE (strings, i); + this_wide = TREE_TYPE (t) == wchar_array_type_node; + len = TREE_STRING_LENGTH (t) - (this_wide ? wchar_bytes : 1); + if (this_wide == wide_flag) { - int len = (TREE_STRING_LENGTH (t) - - ((TREE_TYPE (t) == wchar_array_type_node) - ? wchar_bytes : 1)); - if ((TREE_TYPE (t) == wchar_array_type_node) == wide_flag) + memcpy (q, TREE_STRING_POINTER (t), len); + q += len; + } + else + { + const int nzeros = (TYPE_PRECISION (wchar_type_node) + / BITS_PER_UNIT) - 1; + int j, k; + + if (BYTES_BIG_ENDIAN) { - memcpy (q, TREE_STRING_POINTER (t), len); - q += len; + for (k = 0; k < len; k++) + { + for (j = 0; j < nzeros; j++) + *q++ = 0; + *q++ = TREE_STRING_POINTER (t)[k]; + } } else { - int i, j; - for (i = 0; i < len; i++) + for (k = 0; k < len; k++) { - if (BYTES_BIG_ENDIAN) - { - for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; j++) - *q++ = 0; - *q++ = TREE_STRING_POINTER (t)[i]; - } - else - { - *q++ = TREE_STRING_POINTER (t)[i]; - for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; j++) - *q++ = 0; - } + *q++ = TREE_STRING_POINTER (t)[k]; + for (j = 0; j < nzeros; j++) + *q++ = 0; } } } - if (wide_flag) - { - int i; - for (i = 0; i < wchar_bytes; i++) - *q++ = 0; - } - else - *q = 0; - - value = build_string (length, p); - free (p); } - else + + /* Nul terminate the string. */ + if (wide_flag) { - value = strings; - length = TREE_STRING_LENGTH (value); - if (TREE_TYPE (value) == wchar_array_type_node) - wide_flag = 1; + for (i = 0; i < wchar_bytes; i++) + *q++ = 0; } + else + *q = 0; - /* Compute the number of elements, for the array type. */ - nchars = wide_flag ? length / wchar_bytes : length; - - if (pedantic && nchars - 1 > nchars_max && c_language == clk_c) - 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); + value = build_string (length, p); + free (p); - /* 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_traditional && ! 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))); - } + if (wide_flag) + TREE_TYPE (value) = wchar_array_type_node; else - TREE_TYPE (value) - = build_array_type (wide_flag ? wchar_type_node : char_type_node, - build_index_type (build_int_2 (nchars - 1, 0))); + TREE_TYPE (value) = char_array_type_node; - TREE_CONSTANT (value) = 1; - TREE_READONLY (value) = ! flag_writable_strings; - TREE_STATIC (value) = 1; return value; } @@ -755,13 +1389,15 @@ void unsigned_conversion_warning (result, operand) tree result, operand; { + tree type = TREE_TYPE (result); + if (TREE_CODE (operand) == INTEGER_CST - && TREE_CODE (TREE_TYPE (result)) == INTEGER_TYPE - && TREE_UNSIGNED (TREE_TYPE (result)) + && TREE_CODE (type) == INTEGER_TYPE + && TREE_UNSIGNED (type) && skip_evaluation == 0 - && !int_fits_type_p (operand, TREE_TYPE (result))) + && !int_fits_type_p (operand, type)) { - if (!int_fits_type_p (operand, signed_type (TREE_TYPE (result)))) + 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) @@ -810,7 +1446,8 @@ convert_and_check (type, expr) don't warn unless pedantic. */ if ((pedantic || TREE_UNSIGNED (type) - || ! constant_fits_type_p (expr, unsigned_type (type))) + || ! constant_fits_type_p (expr, + c_common_unsigned_type (type))) && skip_evaluation == 0) warning ("overflow in implicit constant conversion"); } @@ -1212,7 +1849,7 @@ verify_tree (x, pbefore_sp, pno_sp, writer) } } -/* Try to warn for undefined behaviour in EXPR due to missing sequence +/* Try to warn for undefined behavior in EXPR due to missing sequence points. */ static void @@ -1300,7 +1937,7 @@ check_case_value (value) that is unsigned if UNSIGNEDP is nonzero, otherwise signed. */ tree -type_for_size (bits, unsignedp) +c_common_type_for_size (bits, unsignedp) unsigned bits; int unsignedp; { @@ -1344,7 +1981,7 @@ type_for_size (bits, unsignedp) then UNSIGNEDP selects between signed and unsigned types. */ tree -type_for_mode (mode, unsignedp) +c_common_type_for_mode (mode, unsignedp) enum machine_mode mode; int unsignedp; { @@ -1399,41 +2036,44 @@ type_for_mode (mode, unsignedp) if (mode == TYPE_MODE (build_pointer_type (integer_type_node))) return build_pointer_type (integer_type_node); -#ifdef VECTOR_MODE_SUPPORTED_P - if (VECTOR_MODE_SUPPORTED_P (mode)) + switch (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 V2SImode: - return unsignedp ? unsigned_V2SI_type_node : V2SI_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 V16SFmode: - return V16SF_type_node; - case V4SFmode: - return V4SF_type_node; - case V2SFmode: - return V2SF_type_node; - default: - break; - } + 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; + default: + break; } -#endif return 0; } /* Return an unsigned type the same as TYPE in other respects. */ tree -unsigned_type (type) +c_common_unsigned_type (type) tree type; { tree type1 = TYPE_MAIN_VARIANT (type); @@ -1462,13 +2102,13 @@ unsigned_type (type) if (type1 == intQI_type_node) return unsigned_intQI_type_node; - return signed_or_unsigned_type (1, type); + return c_common_signed_or_unsigned_type (1, type); } /* Return a signed type the same as TYPE in other respects. */ tree -signed_type (type) +c_common_signed_type (type) tree type; { tree type1 = TYPE_MAIN_VARIANT (type); @@ -1497,14 +2137,14 @@ signed_type (type) if (type1 == unsigned_intQI_type_node) return intQI_type_node; - return signed_or_unsigned_type (0, type); + return c_common_signed_or_unsigned_type (0, type); } /* Return a type the same as TYPE except unsigned or signed according to UNSIGNEDP. */ tree -signed_or_unsigned_type (unsignedp, type) +c_common_signed_or_unsigned_type (unsignedp, type) int unsignedp; tree type; { @@ -1572,8 +2212,9 @@ min_precision (value, 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 truthvalue_conversion). */ +/* Print an error message for invalid operands to arith operation + CODE. NOP_EXPR is used as a special case (see + c_common_truthvalue_conversion). */ void binary_op_error (code) @@ -1753,19 +2394,20 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr) int unsignedp = TREE_UNSIGNED (*restype_ptr); tree val; - type = signed_or_unsigned_type (unsignedp0, TREE_TYPE (primop0)); + type = c_common_signed_or_unsigned_type (unsignedp0, + TREE_TYPE (primop0)); /* 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. */ if (TREE_CODE (type) == ENUMERAL_TYPE) - type = type_for_size (TYPE_PRECISION (type), unsignedp0); + type = c_common_type_for_size (TYPE_PRECISION (type), unsignedp0); maxval = TYPE_MAX_VALUE (type); minval = TYPE_MIN_VALUE (type); if (unsignedp && !unsignedp0) - *restype_ptr = signed_type (*restype_ptr); + *restype_ptr = c_common_signed_type (*restype_ptr); if (TREE_TYPE (primop1) != *restype_ptr) primop1 = convert (*restype_ptr, primop1); @@ -1862,22 +2504,11 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr) default: break; } - type = unsigned_type (type); - } - - if (!max_gt && !unsignedp0 && TREE_CODE (primop0) != INTEGER_CST) - { - /* This is the case of (char)x >?< 0x80, which people used to use - expecting old C compilers to change the 0x80 into -0x80. */ - if (val == boolean_false_node) - warning ("comparison is always false due to limited range of data type"); - if (val == boolean_true_node) - warning ("comparison is always true due to limited range of data type"); + type = c_common_unsigned_type (type); } - if (!min_lt && unsignedp0 && TREE_CODE (primop0) != INTEGER_CST) + if (TREE_CODE (primop0) != INTEGER_CST) { - /* This is the case of (unsigned char)x >?< -1 or < 0. */ if (val == boolean_false_node) warning ("comparison is always false due to limited range of data type"); if (val == boolean_true_node) @@ -1914,15 +2545,19 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr) && TYPE_PRECISION (TREE_TYPE (primop1)) < TYPE_PRECISION (*restype_ptr)) { type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1)); - type = signed_or_unsigned_type (unsignedp0 - || TREE_UNSIGNED (*restype_ptr), - type); + type = c_common_signed_or_unsigned_type (unsignedp0 + || TREE_UNSIGNED (*restype_ptr), + type); /* Make sure shorter operand is extended the right way to match the longer operand. */ - primop0 = convert (signed_or_unsigned_type (unsignedp0, TREE_TYPE (primop0)), - primop0); - primop1 = convert (signed_or_unsigned_type (unsignedp1, TREE_TYPE (primop1)), - primop1); + primop0 + = convert (c_common_signed_or_unsigned_type (unsignedp0, + TREE_TYPE (primop0)), + primop0); + primop1 + = convert (c_common_signed_or_unsigned_type (unsignedp1, + TREE_TYPE (primop1)), + primop1); } else { @@ -1945,7 +2580,7 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr) so suppress the warning. */ if (extra_warnings && !in_system_header && ! (TREE_CODE (primop0) == INTEGER_CST - && ! TREE_OVERFLOW (convert (signed_type (type), + && ! TREE_OVERFLOW (convert (c_common_signed_type (type), primop0)))) warning ("comparison of unsigned expression >= 0 is always true"); value = boolean_true_node; @@ -1954,7 +2589,7 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr) case LT_EXPR: if (extra_warnings && !in_system_header && ! (TREE_CODE (primop0) == INTEGER_CST - && ! TREE_OVERFLOW (convert (signed_type (type), + && ! TREE_OVERFLOW (convert (c_common_signed_type (type), primop0)))) warning ("comparison of unsigned expression < 0 is always false"); value = boolean_false_node; @@ -2063,8 +2698,8 @@ pointer_int_sum (resultcode, ptrop, intop) if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype) || TREE_UNSIGNED (TREE_TYPE (intop)) != TREE_UNSIGNED (sizetype)) - intop = convert (type_for_size (TYPE_PRECISION (sizetype), - TREE_UNSIGNED (sizetype)), intop); + intop = convert (c_common_type_for_size (TYPE_PRECISION (sizetype), + TREE_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 @@ -2096,7 +2731,7 @@ pointer_int_sum (resultcode, ptrop, intop) The resulting type should always be `boolean_type_node'. */ tree -truthvalue_conversion (expr) +c_common_truthvalue_conversion (expr) tree expr; { if (TREE_CODE (expr) == ERROR_MARK) @@ -2162,32 +2797,32 @@ truthvalue_conversion (expr) case COMPLEX_EXPR: return build_binary_op ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)) ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR), - truthvalue_conversion (TREE_OPERAND (expr, 0)), - truthvalue_conversion (TREE_OPERAND (expr, 1)), + c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)), + c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)), 0); case NEGATE_EXPR: case ABS_EXPR: case FLOAT_EXPR: case FFS_EXPR: - /* These don't change whether an object is non-zero or zero. */ - return truthvalue_conversion (TREE_OPERAND (expr, 0)); + /* These don't change whether an object is nonzero or zero. */ + return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)); case LROTATE_EXPR: case RROTATE_EXPR: - /* These don't change whether an object is zero or non-zero, but + /* 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, boolean_type_node, TREE_OPERAND (expr, 1), - truthvalue_conversion (TREE_OPERAND (expr, 0))); + c_common_truthvalue_conversion (TREE_OPERAND (expr, 0))); else - return truthvalue_conversion (TREE_OPERAND (expr, 0)); + 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, boolean_type_node, TREE_OPERAND (expr, 0), - truthvalue_conversion (TREE_OPERAND (expr, 1)), - truthvalue_conversion (TREE_OPERAND (expr, 2)))); + c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)), + c_common_truthvalue_conversion (TREE_OPERAND (expr, 2)))); case CONVERT_EXPR: /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE, @@ -2200,14 +2835,19 @@ truthvalue_conversion (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 truthvalue_conversion (TREE_OPERAND (expr, 0)); + return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)); break; case MINUS_EXPR: - /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize - this case. */ - if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT - && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE) + /* 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: @@ -2240,12 +2880,12 @@ truthvalue_conversion (expr) if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE) { - tree tem = save_expr (expr); + tree t = save_expr (expr); return (build_binary_op ((TREE_SIDE_EFFECTS (expr) ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR), - truthvalue_conversion (build_unary_op (REALPART_EXPR, tem, 0)), - truthvalue_conversion (build_unary_op (IMAGPART_EXPR, tem, 0)), + c_common_truthvalue_conversion (build_unary_op (REALPART_EXPR, t, 0)), + c_common_truthvalue_conversion (build_unary_op (IMAGPART_EXPR, t, 0)), 0)); } @@ -2254,7 +2894,7 @@ truthvalue_conversion (expr) static tree builtin_function_2 PARAMS ((const char *, const char *, tree, tree, int, enum built_in_class, int, int, - int)); + tree)); /* Make a variant type in the proper way for C/C++, propagating qualifiers down to the element type of an array. */ @@ -2316,7 +2956,6 @@ c_apply_type_quals_to_decl (type_quals, decl) } } - /* 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. */ @@ -2349,13 +2988,17 @@ c_common_get_alias_set (t) || t == signed_char_type_node || t == unsigned_char_type_node) return 0; - + + /* If it has the may_alias attribute, it can alias anything. */ + if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (t))) + return 0; + /* 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)) { - tree t1 = signed_type (t); + tree t1 = c_common_signed_type (t); /* t1 == t can happen for boolean nodes which are always unsigned. */ if (t1 != t) @@ -2396,36 +3039,66 @@ c_common_get_alias_set (t) return -1; } -/* Implement the __alignof keyword: Return the minimum required - alignment of TYPE, measured in bytes. */ - +/* Compute the value of 'sizeof (TYPE)' or '__alignof__ (TYPE)', where the + second parameter indicates which OPERATOR is being applied. The COMPLAIN + flag controls whether we should diagnose possibly ill-formed + constructs or not. */ tree -c_alignof (type) +c_sizeof_or_alignof_type (type, op, complain) tree type; + enum tree_code op; + int complain; { - enum tree_code code = TREE_CODE (type); - tree t; - - /* In C++, sizeof applies to the referent. Handle alignof the same way. */ - if (code == REFERENCE_TYPE) + 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__"; + + if (type_code == FUNCTION_TYPE) { - type = TREE_TYPE (type); - code = TREE_CODE (type); + if (op == SIZEOF_EXPR) + { + if (complain && (pedantic || warn_pointer_arith)) + pedwarn ("invalid application of `sizeof' to a function type"); + value = size_one_node; + } + else + value = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT); + } + else if (type_code == VOID_TYPE || type_code == ERROR_MARK) + { + if (type_code == VOID_TYPE + && complain && (pedantic || warn_pointer_arith)) + pedwarn ("invalid application of `%s' to a void type", op_name); + value = size_one_node; } - - if (code == FUNCTION_TYPE) - t = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT); - else if (code == VOID_TYPE || code == ERROR_MARK) - t = size_one_node; else if (!COMPLETE_TYPE_P (type)) { - error ("__alignof__ applied to an incomplete type"); - t = size_zero_node; + if (complain) + error ("invalid application of `%s' to an incomplete type", op_name); + value = size_zero_node; } else - t = size_int (TYPE_ALIGN (type) / BITS_PER_UNIT); + { + if (op == SIZEOF_EXPR) + /* 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); + } - return fold (build1 (NOP_EXPR, size_type_node, t)); + /* 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); + + return value; } /* Implement the __alignof keyword: Return the minimum required @@ -2476,19 +3149,30 @@ c_alignof_expr (expr) return fold (build1 (NOP_EXPR, size_type_node, t)); } -/* Give the specifications for the format attributes, used by C and all - descendents. */ +/* Handle C and C++ default attributes. */ -static const struct attribute_spec c_format_attribute_table[] = +enum built_in_attribute { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ - { "format", 3, 3, false, true, true, - handle_format_attribute }, - { "format_arg", 1, 1, false, true, true, - handle_format_arg_attribute }, - { NULL, 0, 0, false, false, false, NULL } +#define DEF_ATTR_NULL_TREE(ENUM) ENUM, +#define DEF_ATTR_INT(ENUM, VALUE) ENUM, +#define DEF_ATTR_IDENT(ENUM, STRING) ENUM, +#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM, +#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No entry needed in enum. */ +#include "builtin-attrs.def" +#undef DEF_ATTR_NULL_TREE +#undef DEF_ATTR_INT +#undef DEF_ATTR_IDENT +#undef DEF_ATTR_TREE_LIST +#undef DEF_FN_ATTR + ATTR_LAST }; +static GTY(()) tree built_in_attributes[(int) ATTR_LAST]; + +static bool c_attrs_initialized = false; + +static void c_init_attributes PARAMS ((void)); + /* Build tree nodes and builtin functions common to both C and C++ language frontends. */ @@ -2506,6 +3190,7 @@ c_common_nodes_and_builtins () #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_POINTER_TYPE(NAME, TYPE) NAME, #include "builtin-types.def" #undef DEF_PRIMITIVE_TYPE @@ -2517,6 +3202,7 @@ c_common_nodes_and_builtins () #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_POINTER_TYPE BT_LAST }; @@ -2526,18 +3212,9 @@ c_common_nodes_and_builtins () tree builtin_types[(int) BT_LAST]; int wchar_type_size; tree array_domain_type; - /* Either char* or void*. */ - tree traditional_ptr_type_node; - /* Either const char* or const void*. */ - tree traditional_cptr_type_node; - tree traditional_len_type_node; tree va_list_ref_type_node; tree va_list_arg_type_node; - /* We must initialize this before any builtin functions (which might have - attributes) are declared. (c_common_init is too late.) */ - format_attribute_table = c_format_attribute_table; - /* Define `int' and `char' first so that dbx will output them first. */ record_builtin_type (RID_INT, NULL, integer_type_node); record_builtin_type (RID_CHAR, "char", char_type_node); @@ -2571,41 +3248,52 @@ c_common_nodes_and_builtins () record_builtin_type (RID_MAX, "signed char", signed_char_type_node); record_builtin_type (RID_MAX, "unsigned char", unsigned_char_type_node); - /* These are types that type_for_size and type_for_mode use. */ - pushdecl (build_decl (TYPE_DECL, NULL_TREE, intQI_type_node)); - pushdecl (build_decl (TYPE_DECL, NULL_TREE, intHI_type_node)); - pushdecl (build_decl (TYPE_DECL, NULL_TREE, intSI_type_node)); - pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node)); + /* 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)); #if HOST_BITS_PER_WIDE_INT >= 64 - pushdecl (build_decl (TYPE_DECL, get_identifier ("__int128_t"), intTI_type_node)); + (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, + get_identifier ("__int128_t"), + intTI_type_node)); #endif - pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node)); - pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intHI_type_node)); - pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intSI_type_node)); - 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 - pushdecl (build_decl (TYPE_DECL, get_identifier ("__uint128_t"), unsigned_intTI_type_node)); + (*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); - 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); - 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', and this must agree, even if long and int are the same size. */ size_type_node = TREE_TYPE (identifier_global_value (get_identifier (SIZE_TYPE))); - signed_size_type_node = signed_type (size_type_node); - if (flag_traditional) - size_type_node = signed_size_type_node; + signed_size_type_node = c_common_signed_type (size_type_node); set_sizetype (size_type_node); build_common_tree_nodes_2 (flag_short_double); @@ -2614,14 +3302,18 @@ c_common_nodes_and_builtins () record_builtin_type (RID_DOUBLE, NULL, double_type_node); record_builtin_type (RID_MAX, "long double", long_double_type_node); - pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"), - complex_integer_type_node)); - pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"), - complex_float_type_node)); - pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"), - complex_double_type_node)); - pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"), - complex_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) + (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. */ @@ -2643,12 +3335,12 @@ c_common_nodes_and_builtins () if (g77_integer_type_node != NULL_TREE) { - pushdecl (build_decl (TYPE_DECL, - get_identifier ("__g77_integer"), - g77_integer_type_node)); - pushdecl (build_decl (TYPE_DECL, - get_identifier ("__g77_uinteger"), - g77_uinteger_type_node)); + (*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 @@ -2668,12 +3360,12 @@ c_common_nodes_and_builtins () if (g77_longint_type_node != NULL_TREE) { - pushdecl (build_decl (TYPE_DECL, - get_identifier ("__g77_longint"), - g77_longint_type_node)); - pushdecl (build_decl (TYPE_DECL, - get_identifier ("__g77_ulongint"), - g77_ulongint_type_node)); + (*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)); } record_builtin_type (RID_VOID, NULL, void_type_node); @@ -2705,19 +3397,8 @@ c_common_nodes_and_builtins () = build_pointer_type (build_qualified_type (char_type_node, TYPE_QUAL_CONST)); - traditional_ptr_type_node = ((flag_traditional && - c_language != clk_cplusplus) - ? string_type_node : ptr_type_node); - traditional_cptr_type_node = ((flag_traditional && - c_language != clk_cplusplus) - ? const_string_type_node : const_ptr_type_node); - - (*targetm.init_builtins) (); - /* This is special for C++ so functions can be overloaded. */ - wchar_type_node = get_identifier (flag_short_wchar - ? "short unsigned int" - : WCHAR_TYPE); + wchar_type_node = get_identifier (MODIFIED_WCHAR_TYPE); wchar_type_node = TREE_TYPE (identifier_global_value (wchar_type_node)); wchar_type_size = TYPE_PRECISION (wchar_type_node); if (c_language == clk_cplusplus) @@ -2730,8 +3411,8 @@ c_common_nodes_and_builtins () } else { - signed_wchar_type_node = signed_type (wchar_type_node); - unsigned_wchar_type_node = unsigned_type (wchar_type_node); + signed_wchar_type_node = c_common_signed_type (wchar_type_node); + unsigned_wchar_type_node = c_common_unsigned_type (wchar_type_node); } /* This is for wide string constants. */ @@ -2749,16 +3430,19 @@ c_common_nodes_and_builtins () default_function_type = build_function_type (integer_type_node, NULL_TREE); ptrdiff_type_node = TREE_TYPE (identifier_global_value (get_identifier (PTRDIFF_TYPE))); - unsigned_ptrdiff_type_node = unsigned_type (ptrdiff_type_node); + unsigned_ptrdiff_type_node = c_common_unsigned_type (ptrdiff_type_node); - 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_va_list"), + va_list_type_node)); - pushdecl (build_decl (TYPE_DECL, get_identifier ("__builtin_ptrdiff_t"), - ptrdiff_type_node)); + (*lang_hooks.decls.pushdecl) + (build_decl (TYPE_DECL, get_identifier ("__builtin_ptrdiff_t"), + ptrdiff_type_node)); - pushdecl (build_decl (TYPE_DECL, get_identifier ("__builtin_size_t"), - sizetype)); + (*lang_hooks.decls.pushdecl) + (build_decl (TYPE_DECL, get_identifier ("__builtin_size_t"), + sizetype)); if (TREE_CODE (va_list_type_node) == ARRAY_TYPE) { @@ -2771,10 +3455,6 @@ c_common_nodes_and_builtins () va_list_ref_type_node = build_reference_type (va_list_type_node); } - traditional_len_type_node = ((flag_traditional && - c_language != clk_cplusplus) - ? integer_type_node : sizetype); - #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \ builtin_types[(int) ENUM] = VALUE; #define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \ @@ -2840,6 +3520,19 @@ c_common_nodes_and_builtins () 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]); @@ -2851,10 +3544,15 @@ c_common_nodes_and_builtins () #undef DEF_FUNCTION_TYPE_4 #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_POINTER_TYPE -#define DEF_BUILTIN(ENUM, NAME, CLASS, \ - TYPE, LIBTYPE, BOTH_P, FALLBACK_P, NONANSI_P) \ + if (!c_attrs_initialized) + c_init_attributes (); + +#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, \ + BOTH_P, FALLBACK_P, NONANSI_P, ATTRS) \ if (NAME) \ { \ tree decl; \ @@ -2867,7 +3565,8 @@ c_common_nodes_and_builtins () CLASS, \ (FALLBACK_P \ ? (NAME + strlen ("__builtin_")) \ - : NULL)); \ + : NULL), \ + built_in_attributes[(int) ATTRS]); \ else \ decl = builtin_function_2 (NAME, \ NAME + strlen ("__builtin_"), \ @@ -2877,40 +3576,16 @@ c_common_nodes_and_builtins () CLASS, \ FALLBACK_P, \ NONANSI_P, \ - /*noreturn_p=*/0); \ + built_in_attributes[(int) ATTRS]); \ \ built_in_decls[(int) ENUM] = decl; \ } #include "builtins.def" #undef DEF_BUILTIN - /* Declare _exit and _Exit just to mark them as non-returning. */ - builtin_function_2 (NULL, "_exit", NULL_TREE, - builtin_types[BT_FN_VOID_INT], - 0, NOT_BUILT_IN, 0, 1, 1); - builtin_function_2 (NULL, "_Exit", NULL_TREE, - builtin_types[BT_FN_VOID_INT], - 0, NOT_BUILT_IN, 0, !flag_isoc99, 1); - - /* Declare these functions non-returning - to avoid spurious "control drops through" warnings. */ - builtin_function_2 (NULL, "abort", - NULL_TREE, ((c_language == clk_cplusplus) - ? builtin_types[BT_FN_VOID] - : builtin_types[BT_FN_VOID_VAR]), - 0, NOT_BUILT_IN, 0, 0, 1); - - builtin_function_2 (NULL, "exit", - NULL_TREE, ((c_language == clk_cplusplus) - ? builtin_types[BT_FN_VOID_INT] - : builtin_types[BT_FN_VOID_VAR]), - 0, NOT_BUILT_IN, 0, 0, 1); + (*targetm.init_builtins) (); main_identifier_node = get_identifier ("main"); - - /* ??? Perhaps there's a better place to do this. But it is related - to __builtin_va_arg, so it isn't that off-the-wall. */ - lang_type_promotes_to = simple_type_promotes_to; } tree @@ -2977,15 +3652,15 @@ builtin_function_disabled_p (name) 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; if - NORETURN_P is nonzero, the function is marked as non-returning. + 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. */ static tree builtin_function_2 (builtin_name, name, builtin_type, type, function_code, - class, library_name_p, nonansi_p, noreturn_p) + class, library_name_p, nonansi_p, attrs) const char *builtin_name; const char *name; tree builtin_type; @@ -2994,31 +3669,23 @@ builtin_function_2 (builtin_name, name, builtin_type, type, function_code, enum built_in_class class; int library_name_p; int nonansi_p; - int noreturn_p; + tree attrs; { tree bdecl = NULL_TREE; tree decl = NULL_TREE; if (builtin_name != 0) { bdecl = builtin_function (builtin_name, builtin_type, function_code, - class, library_name_p ? name : NULL); - if (noreturn_p) - { - TREE_THIS_VOLATILE (bdecl) = 1; - TREE_SIDE_EFFECTS (bdecl) = 1; - } + class, library_name_p ? name : NULL, + attrs); } if (name != 0 && !flag_no_builtin && !builtin_function_disabled_p (name) && !(nonansi_p && flag_no_nonansi_builtin)) { - decl = builtin_function (name, type, function_code, class, NULL); + decl = builtin_function (name, type, function_code, class, NULL, + attrs); if (nonansi_p) DECL_BUILT_IN_NONANSI (decl) = 1; - if (noreturn_p) - { - TREE_THIS_VOLATILE (decl) = 1; - TREE_SIDE_EFFECTS (decl) = 1; - } } return (bdecl != 0 ? bdecl : decl); } @@ -3054,34 +3721,6 @@ c_promoting_integer_type_p (t) } } -/* Given a type, apply default promotions wrt unnamed function arguments - and return the new type. Return NULL_TREE if no change. */ -/* ??? There is a function of the same name in the C++ front end that - does something similar, but is more thorough and does not return NULL - if no change. We could perhaps share code, but it would make the - self_promoting_type property harder to identify. */ - -tree -simple_type_promotes_to (type) - tree type; -{ - if (TYPE_MAIN_VARIANT (type) == float_type_node) - return double_type_node; - - if (c_promoting_integer_type_p (type)) - { - /* Traditionally, unsignedness is preserved in default promotions. - Also preserve unsignedness if not really getting any wider. */ - if (TREE_UNSIGNED (type) - && (flag_traditional - || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))) - return unsigned_type_node; - return integer_type_node; - } - - return NULL_TREE; -} - /* Return 1 if PARMS specifies a fixed number of parameters and none of their types is affected by default promotions. */ @@ -3122,6 +3761,81 @@ strip_array_types (type) return type; } +static tree expand_unordered_cmp PARAMS ((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 (function, params, unordered_code, ordered_code) + tree function, params; + enum tree_code unordered_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. */ @@ -3134,8 +3848,6 @@ tree expand_tree_builtin (function, params, coerced_params) tree function, params, coerced_params; { - enum tree_code code; - if (DECL_BUILT_IN_CLASS (function) != BUILT_IN_NORMAL) return NULL_TREE; @@ -3174,72 +3886,22 @@ expand_tree_builtin (function, params, coerced_params) return build_unary_op (IMAGPART_EXPR, TREE_VALUE (coerced_params), 0); case BUILT_IN_ISGREATER: - if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT) - code = UNLE_EXPR; - else - code = LE_EXPR; - goto unordered_cmp; + return expand_unordered_cmp (function, params, UNLE_EXPR, LE_EXPR); case BUILT_IN_ISGREATEREQUAL: - if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT) - code = UNLT_EXPR; - else - code = LT_EXPR; - goto unordered_cmp; + return expand_unordered_cmp (function, params, UNLT_EXPR, LT_EXPR); case BUILT_IN_ISLESS: - if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT) - code = UNGE_EXPR; - else - code = GE_EXPR; - goto unordered_cmp; + return expand_unordered_cmp (function, params, UNGE_EXPR, GE_EXPR); case BUILT_IN_ISLESSEQUAL: - if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT) - code = UNGT_EXPR; - else - code = GT_EXPR; - goto unordered_cmp; + return expand_unordered_cmp (function, params, UNGT_EXPR, GT_EXPR); case BUILT_IN_ISLESSGREATER: - if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT) - code = UNEQ_EXPR; - else - code = EQ_EXPR; - goto unordered_cmp; + return expand_unordered_cmp (function, params, UNEQ_EXPR, EQ_EXPR); case BUILT_IN_ISUNORDERED: - if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT) - return integer_zero_node; - code = UNORDERED_EXPR; - goto unordered_cmp; - - unordered_cmp: - { - tree arg0, arg1; - - 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)); - arg0 = build_binary_op (code, arg0, arg1, 0); - if (code != UNORDERED_EXPR) - arg0 = build_unary_op (TRUTH_NOT_EXPR, arg0, 0); - return arg0; - } - break; + return expand_unordered_cmp (function, params, UNORDERED_EXPR, NOP_EXPR); default: break; @@ -3248,7 +3910,7 @@ expand_tree_builtin (function, params, coerced_params) return NULL_TREE; } -/* Returns non-zero if CODE is the code for a statement. */ +/* Returns nonzero if CODE is the code for a statement. */ int statement_code_p (code) @@ -3566,41 +4228,6 @@ finish_label_address_expr (label) return result; } -/* Mark P (a stmt_tree) for GC. The use of a `void *' for the - parameter allows this function to be used as a GC-marking - function. */ - -void -mark_stmt_tree (p) - void *p; -{ - stmt_tree st = (stmt_tree) p; - - ggc_mark_tree (st->x_last_stmt); - ggc_mark_tree (st->x_last_expr_type); -} - -/* Mark LD for GC. */ - -void -c_mark_lang_decl (c) - struct c_lang_decl *c ATTRIBUTE_UNUSED; -{ -} - -/* Mark F for GC. */ - -void -mark_c_language_function (f) - struct language_function *f; -{ - if (!f) - return; - - mark_stmt_tree (&f->x_stmt_tree); - ggc_mark_tree (f->x_scope_stmt_stack); -} - /* Hook used by expand_expr to expand language-specific tree codes. */ rtx @@ -3608,7 +4235,7 @@ c_expand_expr (exp, target, tmode, modifier) tree exp; rtx target; enum machine_mode tmode; - enum expand_modifier modifier; + int modifier; /* Actually enum_modifier. */ { switch (TREE_CODE (exp)) { @@ -3749,7 +4376,7 @@ c_safe_from_p (target, exp) /* Hook used by unsafe_for_reeval to handle language-specific tree codes. */ int -c_unsafe_for_reeval (exp) +c_common_unsafe_for_reeval (exp) tree exp; { /* Statement expressions may not be reevaluated, likewise compound @@ -3774,56 +4401,6 @@ c_staticp (exp) return 0; } -/* Tree code classes. */ - -#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE, - -static const char c_tree_code_type[] = { - 'x', -#include "c-common.def" -}; -#undef DEFTREECODE - -/* Table indexed by tree code giving number of expression - operands beyond the fixed part of the node structure. - Not used for types or decls. */ - -#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH, - -static const int c_tree_code_length[] = { - 0, -#include "c-common.def" -}; -#undef DEFTREECODE - -/* Names of tree components. - Used for printing out the tree and error messages. */ -#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME, - -static const char *const c_tree_code_name[] = { - "@@dummy", -#include "c-common.def" -}; -#undef DEFTREECODE - -/* Adds the tree codes specific to the C front end to the list of all - tree codes. */ - -void -add_c_tree_codes () -{ - memcpy (tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE, - c_tree_code_type, - (int) LAST_C_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE); - memcpy (tree_code_length + (int) LAST_AND_UNUSED_TREE_CODE, - c_tree_code_length, - (LAST_C_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE) * sizeof (int)); - memcpy (tree_code_name + (int) LAST_AND_UNUSED_TREE_CODE, - c_tree_code_name, - (LAST_C_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE) * sizeof (char *)); - lang_unsafe_for_reeval = c_unsafe_for_reeval; -} - #define CALLED_AS_BUILT_IN(NODE) \ (!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10)) @@ -4012,7 +4589,7 @@ c_expand_builtin_printf (arglist, target, tmode, modifier, ignore, unlocked) memcpy (newstr, TREE_STRING_POINTER (stripped_string), newlen - 1); newstr[newlen - 1] = 0; - arglist = combine_strings (build_string (newlen, newstr)); + arglist = fix_string_type (build_string (newlen, newstr)); arglist = build_tree_list (NULL_TREE, arglist); fn = fn_puts; } @@ -4151,112 +4728,449 @@ boolean_increment (code, arg) return val; } -/* Handle C and C++ default attributes. */ +/* Define NAME with value TYPE precision. */ +static void +builtin_define_type_precision (name, type) + const char *name; + tree type; +{ + builtin_define_with_int_value (name, TYPE_PRECISION (type)); +} -enum built_in_attribute +/* Define the float.h constants for TYPE using NAME_PREFIX and FP_SUFFIX. */ +static void +builtin_define_float_constants (name_prefix, fp_suffix, type) + const char *name_prefix; + const char *fp_suffix; + tree type; { -#define DEF_ATTR_NULL_TREE(ENUM) ENUM, -#define DEF_ATTR_INT(ENUM, VALUE) ENUM, -#define DEF_ATTR_IDENT(ENUM, STRING) ENUM, -#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM, -#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No entry needed in enum. */ -#include "builtin-attrs.def" -#undef DEF_ATTR_NULL_TREE -#undef DEF_ATTR_INT -#undef DEF_ATTR_IDENT -#undef DEF_ATTR_TREE_LIST -#undef DEF_FN_ATTR - ATTR_LAST -}; + /* Used to convert radix-based values to base 10 values in several cases. + + In the max_exp -> max_10_exp conversion for 128-bit IEEE, we need at + least 6 significant digits for correct results. Using the fraction + formed by (log(2)*1e6)/(log(10)*1e6) overflows a 32-bit integer as an + intermediate; perhaps someone can find a better approximation, in the + mean time, I suspect using doubles won't harm the bootstrap here. */ + + const double log10_2 = .30102999566398119521; + double log10_b; + const struct real_format *fmt; + + char name[64], buf[128]; + int dig, min_10_exp, max_10_exp; + int decimal_dig; + + fmt = real_format_for_mode[TYPE_MODE (type) - QFmode]; + + /* The radix of the exponent representation. */ + if (type == float_type_node) + builtin_define_with_int_value ("__FLT_RADIX__", fmt->b); + log10_b = log10_2 * fmt->log2_b; + + /* The number of radix digits, p, in the floating-point significand. */ + sprintf (name, "__%s_MANT_DIG__", name_prefix); + builtin_define_with_int_value (name, fmt->p); + + /* The number of decimal digits, q, such that any floating-point number + with q decimal digits can be rounded into a floating-point number with + p radix b digits and back again without change to the q decimal digits, + + p log10 b if b is a power of 10 + floor((p - 1) log10 b) otherwise + */ + dig = (fmt->p - 1) * log10_b; + sprintf (name, "__%s_DIG__", name_prefix); + builtin_define_with_int_value (name, dig); + + /* The minimum negative int x such that b**(x-1) is a normalized float. */ + sprintf (name, "__%s_MIN_EXP__", name_prefix); + sprintf (buf, "(%d)", fmt->emin); + builtin_define_with_value (name, buf, 0); + + /* The minimum negative int x such that 10**x is a normalized float, + + ceil (log10 (b ** (emin - 1))) + = ceil (log10 (b) * (emin - 1)) + + Recall that emin is negative, so the integer truncation calculates + the ceiling, not the floor, in this case. */ + min_10_exp = (fmt->emin - 1) * log10_b; + sprintf (name, "__%s_MIN_10_EXP__", name_prefix); + sprintf (buf, "(%d)", min_10_exp); + builtin_define_with_value (name, buf, 0); + + /* The maximum int x such that b**(x-1) is a representable float. */ + sprintf (name, "__%s_MAX_EXP__", name_prefix); + builtin_define_with_int_value (name, fmt->emax); + + /* The maximum int x such that 10**x is in the range of representable + finite floating-point numbers, + + floor (log10((1 - b**-p) * b**emax)) + = floor (log10(1 - b**-p) + log10(b**emax)) + = floor (log10(1 - b**-p) + log10(b)*emax) + + The safest thing to do here is to just compute this number. But since + we don't link cc1 with libm, we cannot. We could implement log10 here + a series expansion, but that seems too much effort because: + + Note that the first term, for all extant p, is a number exceedingly close + to zero, but slightly negative. Note that the second term is an integer + scaling an irrational number, and that because of the floor we are only + interested in its integral portion. + + In order for the first term to have any effect on the integral portion + of the second term, the second term has to be exceedingly close to an + integer itself (e.g. 123.000000000001 or something). Getting a result + that close to an integer requires that the irrational multiplicand have + a long series of zeros in its expansion, which doesn't occur in the + first 20 digits or so of log10(b). + + Hand-waving aside, crunching all of the sets of constants above by hand + does not yield a case for which the first term is significant, which + in the end is all that matters. */ + max_10_exp = fmt->emax * log10_b; + sprintf (name, "__%s_MAX_10_EXP__", name_prefix); + builtin_define_with_int_value (name, max_10_exp); + + /* The number of decimal digits, n, such that any floating-point number + can be rounded to n decimal digits and back again without change to + the value. + + p * log10(b) if b is a power of 10 + ceil(1 + p * log10(b)) otherwise + + The only macro we care about is this number for the widest supported + floating type, but we want this value for rendering constants below. */ + { + double d_decimal_dig = 1 + fmt->p * log10_b; + decimal_dig = d_decimal_dig; + if (decimal_dig < d_decimal_dig) + decimal_dig++; + } + if (type == long_double_type_node) + builtin_define_with_int_value ("__DECIMAL_DIG__", decimal_dig); + + /* Since, for the supported formats, B is always a power of 2, we + construct the following numbers directly as a hexadecimal + constants. */ + + /* The maximum representable finite floating-point number, + (1 - b**-p) * b**emax */ + { + int i, n; + char *p; + + strcpy (buf, "0x0."); + n = fmt->p * fmt->log2_b; + for (i = 0, p = buf + 4; i + 3 < n; i += 4) + *p++ = 'f'; + if (i < n) + *p++ = "08ce"[n - i]; + sprintf (p, "p%d", fmt->emax * fmt->log2_b); + } + sprintf (name, "__%s_MAX__", name_prefix); + builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix); + + /* The minimum normalized positive floating-point number, + b**(emin-1). */ + sprintf (name, "__%s_MIN__", name_prefix); + sprintf (buf, "0x1p%d", (fmt->emin - 1) * fmt->log2_b); + builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix); + + /* The difference between 1 and the least value greater than 1 that is + representable in the given floating point type, b**(1-p). */ + sprintf (name, "__%s_EPSILON__", name_prefix); + sprintf (buf, "0x1p%d", (1 - fmt->p) * fmt->log2_b); + builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix); + + /* For C++ std::numeric_limits<T>::denorm_min. The minimum denormalized + positive floating-point number, b**(emin-p). Zero for formats that + don't support denormals. */ + sprintf (name, "__%s_DENORM_MIN__", name_prefix); + if (fmt->has_denorm) + { + sprintf (buf, "0x1p%d", (fmt->emin - fmt->p) * fmt->log2_b); + builtin_define_with_hex_fp_value (name, type, decimal_dig, + buf, fp_suffix); + } + else + { + sprintf (buf, "0.0%s", fp_suffix); + builtin_define_with_value (name, buf, 0); + } +} -static tree built_in_attributes[(int) ATTR_LAST]; +/* Hook that registers front end and target-specific built-ins. */ +void +cb_register_builtins (pfile) + cpp_reader *pfile; +{ + /* -undef turns off target-specific built-ins. */ + if (flag_undef) + return; -static bool c_attrs_initialized = false; + if (c_language == clk_cplusplus) + { + if (SUPPORTS_ONE_ONLY) + cpp_define (pfile, "__GXX_WEAK__=1"); + else + cpp_define (pfile, "__GXX_WEAK__=0"); + if (warn_deprecated) + cpp_define (pfile, "__DEPRECATED"); + } + if (flag_exceptions) + cpp_define (pfile, "__EXCEPTIONS"); + + /* represents the C++ ABI version, always defined so it can be used while + preprocessing C and assembler. */ + cpp_define (pfile, "__GXX_ABI_VERSION=102"); + + /* libgcc needs to know this. */ + if (USING_SJLJ_EXCEPTIONS) + cpp_define (pfile, "__USING_SJLJ_EXCEPTIONS__"); + + /* stddef.h needs to know these. */ + builtin_define_with_value ("__SIZE_TYPE__", SIZE_TYPE, 0); + 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); + + /* limits.h needs to know these. */ + builtin_define_type_max ("__SCHAR_MAX__", signed_char_type_node, 0); + builtin_define_type_max ("__SHRT_MAX__", short_integer_type_node, 0); + builtin_define_type_max ("__INT_MAX__", integer_type_node, 0); + builtin_define_type_max ("__LONG_MAX__", long_integer_type_node, 1); + builtin_define_type_max ("__LONG_LONG_MAX__", long_long_integer_type_node, 2); + builtin_define_type_max ("__WCHAR_MAX__", wchar_type_node, 0); + + builtin_define_type_precision ("__CHAR_BIT__", char_type_node); + + /* float.h needs to know these. */ + + builtin_define_with_int_value ("__FLT_EVAL_METHOD__", + TARGET_FLT_EVAL_METHOD); + + builtin_define_float_constants ("FLT", "F", float_type_node); + builtin_define_float_constants ("DBL", "", double_type_node); + builtin_define_float_constants ("LDBL", "L", long_double_type_node); + + /* For use in assembly language. */ + builtin_define_with_value ("__REGISTER_PREFIX__", REGISTER_PREFIX, 0); + builtin_define_with_value ("__USER_LABEL_PREFIX__", user_label_prefix, 0); + + /* Misc. */ + builtin_define_with_value ("__VERSION__", version_string, 1); + + /* Other target-independent built-ins determined by command-line + options. */ + if (optimize_size) + cpp_define (pfile, "__OPTIMIZE_SIZE__"); + if (optimize) + cpp_define (pfile, "__OPTIMIZE__"); + + if (flag_hosted) + cpp_define (pfile, "__STDC_HOSTED__=1"); + else + cpp_define (pfile, "__STDC_HOSTED__=0"); + + if (fast_math_flags_set_p ()) + cpp_define (pfile, "__FAST_MATH__"); + if (flag_really_no_inline) + cpp_define (pfile, "__NO_INLINE__"); + if (flag_signaling_nans) + cpp_define (pfile, "__SUPPORT_SNAN__"); + if (flag_finite_math_only) + cpp_define (pfile, "__FINITE_MATH_ONLY__=1"); + else + cpp_define (pfile, "__FINITE_MATH_ONLY__=0"); -static void c_init_attributes PARAMS ((void)); + if (flag_iso) + cpp_define (pfile, "__STRICT_ANSI__"); -/* Common initialization before parsing options. */ -void -c_common_init_options (lang) - enum c_language_kind lang; -{ - c_language = lang; - parse_in = cpp_create_reader (lang == clk_c ? CLK_GNUC89: - lang == clk_cplusplus ? CLK_GNUCXX: CLK_OBJC); + if (!flag_signed_char) + cpp_define (pfile, "__CHAR_UNSIGNED__"); - /* Mark as "unspecified" (see c_common_post_options). */ - flag_bounds_check = -1; + if (c_language == clk_cplusplus && TREE_UNSIGNED (wchar_type_node)) + cpp_define (pfile, "__WCHAR_UNSIGNED__"); + + /* Make the choice of ObjC runtime visible to source code. */ + if (flag_objc && flag_next_runtime) + cpp_define (pfile, "__NEXT_RUNTIME__"); + + /* A straightforward target hook doesn't work, because of problems + linking that hook's body when part of non-C front ends. */ +# define preprocessing_asm_p() (cpp_get_options (pfile)->lang == CLK_ASM) +# define preprocessing_trad_p() (cpp_get_options (pfile)->traditional) +# define builtin_define(TXT) cpp_define (pfile, TXT) +# define builtin_assert(TXT) cpp_assert (pfile, TXT) + TARGET_CPU_CPP_BUILTINS (); + TARGET_OS_CPP_BUILTINS (); } -/* Post-switch processing. */ +/* Pass an object-like macro. If it doesn't lie in the user's + namespace, defines it unconditionally. Otherwise define a version + with two leading underscores, and another version with two leading + and trailing underscores, and define the original only if an ISO + standard was not nominated. + + e.g. passing "unix" defines "__unix", "__unix__" and possibly + "unix". Passing "_mips" defines "__mips", "__mips__" and possibly + "_mips". */ void -c_common_post_options () +builtin_define_std (macro) + const char *macro; { - cpp_post_options (parse_in); - - flag_inline_trees = 1; + size_t len = strlen (macro); + char *buff = alloca (len + 5); + char *p = buff + 2; + char *q = p + len; + + /* prepend __ (or maybe just _) if in user's namespace. */ + memcpy (p, macro, len + 1); + if (!( *p == '_' && (p[1] == '_' || ISUPPER (p[1])))) + { + if (*p != '_') + *--p = '_'; + if (p[1] != '_') + *--p = '_'; + } + cpp_define (parse_in, p); - /* 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) + /* If it was in user's namespace... */ + if (p != buff + 2) { - if (!flag_no_inline) - flag_no_inline = 1; - if (flag_inline_functions) - { - flag_inline_trees = 2; - flag_inline_functions = 0; - } + /* Define the macro with leading and following __. */ + if (q[-1] != '_') + *q++ = '_'; + if (q[-2] != '_') + *q++ = '_'; + *q = '\0'; + cpp_define (parse_in, p); + + /* Finally, define the original macro if permitted. */ + if (!flag_iso) + cpp_define (parse_in, macro); } +} + +/* Pass an object-like macro and a value to define it to. The third + parameter says whether or not to turn the value into a string + constant. */ +static void +builtin_define_with_value (macro, expansion, is_str) + const char *macro; + const char *expansion; + int is_str; +{ + char *buf; + size_t mlen = strlen (macro); + size_t elen = strlen (expansion); + size_t extra = 2; /* space for an = and a NUL */ - /* If still "unspecified", make it match -fbounded-pointers. */ - if (flag_bounds_check == -1) - flag_bounds_check = flag_bounded_pointers; - - /* 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_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 an error has occurred in cpplib, note it so we fail - immediately. */ - errorcount += cpp_errors (parse_in); + if (is_str) + extra += 2; /* space for two quote marks */ + + buf = alloca (mlen + elen + extra); + if (is_str) + sprintf (buf, "%s=\"%s\"", macro, expansion); + else + sprintf (buf, "%s=%s", macro, expansion); + + cpp_define (parse_in, buf); } -/* Front end initialization common to C, ObjC and C++. */ -const char * -c_common_init (filename) - const char *filename; +/* Pass an object-like macro and an integer value to define it to. */ +static void +builtin_define_with_int_value (macro, value) + const char *macro; + HOST_WIDE_INT value; { - /* Do this before initializing pragmas, as then cpplib's hash table - has been set up. */ - filename = init_c_lex (filename); + char *buf; + size_t mlen = strlen (macro); + size_t vlen = 18; + size_t extra = 2; /* space for = and NUL. */ - init_pragma (); + buf = alloca (mlen + vlen + extra); + memcpy (buf, macro, mlen); + buf[mlen] = '='; + sprintf (buf + mlen + 1, HOST_WIDE_INT_PRINT_DEC, value); - if (!c_attrs_initialized) - c_init_attributes (); + cpp_define (parse_in, buf); +} - return filename; +/* Pass an object-like macro a hexadecimal floating-point value. */ +static void +builtin_define_with_hex_fp_value (macro, type, digits, hex_str, fp_suffix) + const char *macro; + tree type ATTRIBUTE_UNUSED; + int digits; + const char *hex_str; + const char *fp_suffix; +{ + REAL_VALUE_TYPE real; + char dec_str[64], buf[256]; + + /* Hex values are really cool and convenient, except that they're + not supported in strict ISO C90 mode. First, the "p-" sequence + is not valid as part of a preprocessor number. Second, we get a + pedwarn from the preprocessor, which has no context, so we can't + suppress the warning with __extension__. + + So instead what we do is construct the number in hex (because + it's easy to get the exact correct value), parse it as a real, + then print it back out as decimal. */ + + real_from_string (&real, hex_str); + real_to_decimal (dec_str, &real, sizeof (dec_str), digits, 0); + + sprintf (buf, "%s=%s%s", macro, dec_str, fp_suffix); + cpp_define (parse_in, buf); } -/* Common finish hook for the C, ObjC and C++ front ends. */ -void -c_common_finish () +/* Define MAX for TYPE based on the precision of the type. IS_LONG is + 1 for type "long" and 2 for "long long". We have to handle + unsigned types, since wchar_t might be unsigned. */ + +static void +builtin_define_type_max (macro, type, is_long) + const char *macro; + tree type; + int is_long; { - cpp_finish (parse_in); + static const char *const values[] + = { "127", "255", + "32767", "65535", + "2147483647", "4294967295", + "9223372036854775807", "18446744073709551615", + "170141183460469231731687303715884105727", + "340282366920938463463374607431768211455" }; + static const char *const suffixes[] = { "", "U", "L", "UL", "LL", "ULL" }; + + const char *value, *suffix; + char *buf; + size_t idx; + + /* Pre-rendering the values mean we don't have to futz with printing a + multi-word decimal value. There are also a very limited number of + precisions that we support, so it's really a waste of time. */ + switch (TYPE_PRECISION (type)) + { + case 8: idx = 0; break; + case 16: idx = 2; break; + case 32: idx = 4; break; + case 64: idx = 6; break; + case 128: idx = 8; break; + default: abort (); + } + + value = values[idx + TREE_UNSIGNED (type)]; + suffix = suffixes[is_long * 2 + TREE_UNSIGNED (type)]; - /* For performance, avoid tearing down cpplib's internal structures. - Call cpp_errors () instead of cpp_destroy (). */ - errorcount += cpp_errors (parse_in); + buf = alloca (strlen (macro) + 1 + strlen (value) + strlen (suffix) + 1); + sprintf (buf, "%s=%s%s", macro, value, suffix); + + cpp_define (parse_in, buf); } static void @@ -4281,7 +5195,6 @@ c_init_attributes () #undef DEF_ATTR_IDENT #undef DEF_ATTR_TREE_LIST #undef DEF_FN_ATTR - ggc_add_tree_root (built_in_attributes, (int) ATTR_LAST); c_attrs_initialized = true; } @@ -4325,3 +5238,1447 @@ shadow_warning (msgid, name, decl) "shadowed declaration is here"); } +/* Attribute handlers common to C front ends. */ + +/* Handle a "packed" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_packed_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args ATTRIBUTE_UNUSED; + int flags; + bool *no_add_attrs; +{ + tree *type = NULL; + if (DECL_P (*node)) + { + if (TREE_CODE (*node) == TYPE_DECL) + type = &TREE_TYPE (*node); + } + else + type = node; + + if (type) + { + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *type = build_type_copy (*type); + TYPE_PACKED (*type) = 1; + } + else if (TREE_CODE (*node) == FIELD_DECL) + 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. */ + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "nocommon" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_nocommon_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args ATTRIBUTE_UNUSED; + int flags ATTRIBUTE_UNUSED; + bool *no_add_attrs; +{ + if (TREE_CODE (*node) == VAR_DECL) + DECL_COMMON (*node) = 0; + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "common" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_common_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args ATTRIBUTE_UNUSED; + int flags ATTRIBUTE_UNUSED; + bool *no_add_attrs; +{ + if (TREE_CODE (*node) == VAR_DECL) + DECL_COMMON (*node) = 1; + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "noreturn" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_noreturn_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args ATTRIBUTE_UNUSED; + int flags ATTRIBUTE_UNUSED; + bool *no_add_attrs; +{ + tree type = TREE_TYPE (*node); + + /* See FIXME comment in c_common_attribute_table. */ + if (TREE_CODE (*node) == FUNCTION_DECL) + TREE_THIS_VOLATILE (*node) = 1; + else if (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) + TREE_TYPE (*node) + = build_pointer_type + (build_type_variant (TREE_TYPE (type), + TREE_READONLY (TREE_TYPE (type)), 1)); + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "noinline" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_noinline_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args ATTRIBUTE_UNUSED; + int flags ATTRIBUTE_UNUSED; + bool *no_add_attrs; +{ + if (TREE_CODE (*node) == FUNCTION_DECL) + DECL_UNINLINABLE (*node) = 1; + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "always_inline" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_always_inline_attribute (node, name, args, flags, no_add_attrs) + 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 ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "used" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_used_attribute (pnode, name, args, flags, no_add_attrs) + tree *pnode; + tree name; + tree args ATTRIBUTE_UNUSED; + int flags ATTRIBUTE_UNUSED; + bool *no_add_attrs; +{ + tree node = *pnode; + + if (TREE_CODE (node) == FUNCTION_DECL + || (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node))) + TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (node)) + = TREE_USED (node) = 1; + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "unused" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_unused_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args ATTRIBUTE_UNUSED; + int flags; + bool *no_add_attrs; +{ + if (DECL_P (*node)) + { + tree decl = *node; + + if (TREE_CODE (decl) == PARM_DECL + || TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == LABEL_DECL + || TREE_CODE (decl) == TYPE_DECL) + TREE_USED (decl) = 1; + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + } + else + { + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *node = build_type_copy (*node); + TREE_USED (*node) = 1; + } + + return NULL_TREE; +} + +/* Handle a "const" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_const_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args ATTRIBUTE_UNUSED; + int flags ATTRIBUTE_UNUSED; + bool *no_add_attrs; +{ + tree type = TREE_TYPE (*node); + + /* See FIXME comment on noreturn in c_common_attribute_table. */ + if (TREE_CODE (*node) == FUNCTION_DECL) + TREE_READONLY (*node) = 1; + else if (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) + TREE_TYPE (*node) + = build_pointer_type + (build_type_variant (TREE_TYPE (type), 1, + TREE_THIS_VOLATILE (TREE_TYPE (type)))); + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "transparent_union" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_transparent_union_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args ATTRIBUTE_UNUSED; + int flags; + bool *no_add_attrs; +{ + tree decl = NULL_TREE; + tree *type = NULL; + int is_type = 0; + + if (DECL_P (*node)) + { + decl = *node; + type = &TREE_TYPE (decl); + is_type = TREE_CODE (*node) == TYPE_DECL; + } + else if (TYPE_P (*node)) + type = node, is_type = 1; + + if (is_type + && TREE_CODE (*type) == UNION_TYPE + && (decl == 0 + || (TYPE_FIELDS (*type) != 0 + && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type))))) + { + 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; + } + + return NULL_TREE; +} + +/* Handle a "constructor" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_constructor_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args ATTRIBUTE_UNUSED; + int flags ATTRIBUTE_UNUSED; + bool *no_add_attrs; +{ + tree decl = *node; + tree type = TREE_TYPE (decl); + + if (TREE_CODE (decl) == FUNCTION_DECL + && TREE_CODE (type) == FUNCTION_TYPE + && decl_function_context (decl) == 0) + { + DECL_STATIC_CONSTRUCTOR (decl) = 1; + TREE_USED (decl) = 1; + } + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "destructor" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_destructor_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args ATTRIBUTE_UNUSED; + int flags ATTRIBUTE_UNUSED; + bool *no_add_attrs; +{ + tree decl = *node; + tree type = TREE_TYPE (decl); + + if (TREE_CODE (decl) == FUNCTION_DECL + && TREE_CODE (type) == FUNCTION_TYPE + && decl_function_context (decl) == 0) + { + DECL_STATIC_DESTRUCTOR (decl) = 1; + TREE_USED (decl) = 1; + } + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "mode" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_mode_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args; + int flags ATTRIBUTE_UNUSED; + 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)); + else + { + int j; + const char *p = IDENTIFIER_POINTER (TREE_VALUE (args)); + int len = strlen (p); + enum machine_mode mode = VOIDmode; + tree typefm; + + if (len > 4 && p[0] == '_' && p[1] == '_' + && p[len - 1] == '_' && p[len - 2] == '_') + { + char *newp = (char *) alloca (len - 1); + + strcpy (newp, &p[2]); + newp[len - 4] = '\0'; + p = newp; + } + + /* Change this type to have a type with the specified mode. + First check for the special modes. */ + if (! strcmp (p, "byte")) + mode = byte_mode; + else if (!strcmp (p, "word")) + mode = word_mode; + else if (! strcmp (p, "pointer")) + mode = ptr_mode; + else + for (j = 0; j < NUM_MACHINE_MODES; j++) + if (!strcmp (p, GET_MODE_NAME (j))) + mode = (enum machine_mode) j; + + 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 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; + } + + *node = typefm; + /* No need to layout the type here. The caller should do this. */ + } + } + + return NULL_TREE; +} + +/* Handle a "section" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_section_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name ATTRIBUTE_UNUSED; + tree args; + int flags ATTRIBUTE_UNUSED; + bool *no_add_attrs; +{ + tree decl = *node; + + if (targetm.have_named_sections) + { + 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)) + { + error_with_decl (decl, + "section attribute cannot be specified for local variables"); + *no_add_attrs = true; + } + + /* The decl may have already been given a section attribute + from a previous declaration. Ensure they match. */ + else if (DECL_SECTION_NAME (decl) != NULL_TREE + && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)), + TREE_STRING_POINTER (TREE_VALUE (args))) != 0) + { + error_with_decl (*node, + "section of `%s' conflicts with previous declaration"); + *no_add_attrs = true; + } + else + DECL_SECTION_NAME (decl) = TREE_VALUE (args); + } + else + { + error_with_decl (*node, + "section attribute not allowed for `%s'"); + *no_add_attrs = true; + } + } + else + { + error_with_decl (*node, + "section attributes are not supported for this target"); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "aligned" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_aligned_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name ATTRIBUTE_UNUSED; + tree args; + int flags; + bool *no_add_attrs; +{ + tree decl = NULL_TREE; + tree *type = NULL; + int is_type = 0; + tree align_expr = (args ? TREE_VALUE (args) + : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); + int i; + + if (DECL_P (*node)) + { + decl = *node; + type = &TREE_TYPE (decl); + is_type = TREE_CODE (*node) == TYPE_DECL; + } + 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"); + *no_add_attrs = true; + } + else if ((i = tree_log2 (align_expr)) == -1) + { + error ("requested alignment is not a power of 2"); + *no_add_attrs = true; + } + else if (i > HOST_BITS_PER_INT - 2) + { + error ("requested alignment is too large"); + *no_add_attrs = true; + } + else if (is_type) + { + /* If we have a TYPE_DECL, then copy the type, so that we + don't accidentally modify a builtin type. See pushdecl. */ + if (decl && TREE_TYPE (decl) != error_mark_node + && DECL_ORIGINAL_TYPE (decl) == NULL_TREE) + { + tree tt = TREE_TYPE (decl); + *type = build_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_ALIGN (*type) = (1 << i) * BITS_PER_UNIT; + TYPE_USER_ALIGN (*type) = 1; + } + else if (TREE_CODE (decl) != VAR_DECL + && TREE_CODE (decl) != FIELD_DECL) + { + error_with_decl (decl, + "alignment may not be specified for `%s'"); + *no_add_attrs = true; + } + else + { + DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT; + DECL_USER_ALIGN (decl) = 1; + } + + return NULL_TREE; +} + +/* Handle a "weak" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_weak_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name ATTRIBUTE_UNUSED; + tree args ATTRIBUTE_UNUSED; + int flags ATTRIBUTE_UNUSED; + bool *no_add_attrs ATTRIBUTE_UNUSED; +{ + declare_weak (*node); + + return NULL_TREE; +} + +/* Handle an "alias" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_alias_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args; + int flags ATTRIBUTE_UNUSED; + 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_with_decl (decl, + "`%s' defined both normally and as an alias"); + *no_add_attrs = true; + } + else if (decl_function_context (decl) == 0) + { + tree id; + + id = TREE_VALUE (args); + if (TREE_CODE (id) != STRING_CST) + { + error ("alias arg not a string"); + *no_add_attrs = true; + return NULL_TREE; + } + id = get_identifier (TREE_STRING_POINTER (id)); + /* This counts as a use of the object pointed to. */ + TREE_USED (id) = 1; + + if (TREE_CODE (decl) == FUNCTION_DECL) + DECL_INITIAL (decl) = error_mark_node; + else + DECL_EXTERNAL (decl) = 0; + } + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle an "visibility" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_visibility_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args; + int flags ATTRIBUTE_UNUSED; + bool *no_add_attrs; +{ + tree decl = *node; + + if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl)) + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + else + { + tree id; + + id = TREE_VALUE (args); + if (TREE_CODE (id) != STRING_CST) + { + error ("visibility arg not a string"); + *no_add_attrs = true; + return NULL_TREE; + } + if (strcmp (TREE_STRING_POINTER (id), "hidden") + && strcmp (TREE_STRING_POINTER (id), "protected") + && strcmp (TREE_STRING_POINTER (id), "internal") + && strcmp (TREE_STRING_POINTER (id), "default")) + { + error ("visibility arg must be one of \"default\", \"hidden\", \"protected\" or \"internal\""); + *no_add_attrs = true; + return NULL_TREE; + } + } + + return NULL_TREE; +} + +/* Handle an "tls_model" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_tls_model_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args; + int flags ATTRIBUTE_UNUSED; + bool *no_add_attrs; +{ + tree decl = *node; + + if (! DECL_THREAD_LOCAL (decl)) + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + 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; + } + } + + return NULL_TREE; +} + +/* Handle a "no_instrument_function" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_no_instrument_function_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args ATTRIBUTE_UNUSED; + int flags ATTRIBUTE_UNUSED; + bool *no_add_attrs; +{ + tree decl = *node; + + if (TREE_CODE (decl) != FUNCTION_DECL) + { + error_with_decl (decl, + "`%s' attribute applies only to functions", + IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + else if (DECL_INITIAL (decl)) + { + error_with_decl (decl, + "can't set `%s' attribute after definition", + IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + else + DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1; + + return NULL_TREE; +} + +/* Handle a "malloc" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_malloc_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args ATTRIBUTE_UNUSED; + int flags ATTRIBUTE_UNUSED; + bool *no_add_attrs; +{ + if (TREE_CODE (*node) == FUNCTION_DECL) + DECL_IS_MALLOC (*node) = 1; + /* ??? TODO: Support types. */ + else + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "no_limit_stack" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_no_limit_stack_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args ATTRIBUTE_UNUSED; + int flags ATTRIBUTE_UNUSED; + bool *no_add_attrs; +{ + tree decl = *node; + + if (TREE_CODE (decl) != FUNCTION_DECL) + { + error_with_decl (decl, + "`%s' attribute applies only to functions", + IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + else if (DECL_INITIAL (decl)) + { + error_with_decl (decl, + "can't set `%s' attribute after definition", + IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + else + DECL_NO_LIMIT_STACK (decl) = 1; + + return NULL_TREE; +} + +/* Handle a "pure" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_pure_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args ATTRIBUTE_UNUSED; + int flags ATTRIBUTE_UNUSED; + 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)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "cleanup" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_cleanup_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args; + int flags ATTRIBUTE_UNUSED; + bool *no_add_attrs; +{ + tree decl = *node; + tree cleanup_id, cleanup_decl; + + /* ??? Could perhaps support cleanups on TREE_STATIC, much like we do + for global destructors in C++. This requires infrastructure that + we don't have generically at the moment. It's also not a feature + 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)); + *no_add_attrs = true; + return NULL_TREE; + } + + /* Verify that the argument is a function in scope. */ + /* ??? We could support pointers to functions here as well, if + that was considered desirable. */ + cleanup_id = TREE_VALUE (args); + if (TREE_CODE (cleanup_id) != IDENTIFIER_NODE) + { + error ("cleanup arg 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"); + *no_add_attrs = true; + return NULL_TREE; + } + + /* That the function has proper type is checked with the + eventual call to build_function_call. */ + + return NULL_TREE; +} + +/* Handle a "deprecated" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_deprecated_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args ATTRIBUTE_UNUSED; + int flags; + bool *no_add_attrs; +{ + tree type = NULL_TREE; + int warn = 0; + const char *what = NULL; + + if (DECL_P (*node)) + { + tree decl = *node; + type = TREE_TYPE (decl); + + if (TREE_CODE (decl) == TYPE_DECL + || TREE_CODE (decl) == PARM_DECL + || TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == FIELD_DECL) + TREE_DEPRECATED (decl) = 1; + else + warn = 1; + } + else if (TYPE_P (*node)) + { + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *node = build_type_copy (*node); + TREE_DEPRECATED (*node) = 1; + type = *node; + } + else + warn = 1; + + if (warn) + { + *no_add_attrs = true; + if (type && TYPE_NAME (type)) + { + if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) + what = IDENTIFIER_POINTER (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))); + } + if (what) + warning ("`%s' attribute ignored for `%s'", + IDENTIFIER_POINTER (name), what); + else + warning ("`%s' attribute ignored", + IDENTIFIER_POINTER (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 (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args; + int flags ATTRIBUTE_UNUSED; + 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; + + *no_add_attrs = true; + + if (! host_integerp (TREE_VALUE (args), 1)) + { + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); + return NULL_TREE; + } + + /* Get the vector size (in bytes). */ + vecsize = tree_low_cst (TREE_VALUE (args), 1); + + /* We need to provide for vector pointers, vector arrays, and + functions returning vectors. For example: + + __attribute__((vector_size(16))) short *foo; + + In this case, the mode is SI, but the type being modified is + HI, so we need to look further. */ + + while (POINTER_TYPE_P (type) + || TREE_CODE (type) == FUNCTION_TYPE + || TREE_CODE (type) == ARRAY_TYPE) + type = TREE_TYPE (type); + + /* Get the mode of the type being modified. */ + orig_mode = TYPE_MODE (type); + + if (TREE_CODE (type) == RECORD_TYPE + || (GET_MODE_CLASS (orig_mode) != MODE_FLOAT + && GET_MODE_CLASS (orig_mode) != MODE_INT) + || ! host_integerp (TYPE_SIZE_UNIT (type), 1)) + { + error ("invalid vector type for attribute `%s'", + IDENTIFIER_POINTER (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) + { + error ("no vector mode with the size and type specified could be found"); + return NULL_TREE; + } + + for (type_list_node = vector_type_node_list; type_list_node; + type_list_node = TREE_CHAIN (type_list_node)) + { + 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; + } + } + + if (new_type == NULL_TREE) + { + 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; + } + + /* Build back pointers if needed. */ + *node = vector_size_helper (*node, new_type); + + return NULL_TREE; +} + +/* HACK. GROSS. This is absolutely disgusting. I wish there was a + better way. + + If we requested a pointer to a vector, build up the pointers that + we stripped off while looking for the inner type. Similarly for + return values from functions. + + The argument "type" is the top of the chain, and "bottom" is the + new type which we will point to. */ + +static tree +vector_size_helper (type, bottom) + tree type, bottom; +{ + tree inner, outer; + + if (POINTER_TYPE_P (type)) + { + inner = vector_size_helper (TREE_TYPE (type), bottom); + outer = build_pointer_type (inner); + } + else if (TREE_CODE (type) == ARRAY_TYPE) + { + inner = vector_size_helper (TREE_TYPE (type), bottom); + outer = build_array_type (inner, TYPE_VALUES (type)); + } + else if (TREE_CODE (type) == FUNCTION_TYPE) + { + inner = vector_size_helper (TREE_TYPE (type), bottom); + outer = build_function_type (inner, TYPE_VALUES (type)); + } + else + return bottom; + + TREE_READONLY (outer) = TREE_READONLY (type); + TREE_THIS_VOLATILE (outer) = TREE_THIS_VOLATILE (type); + + return outer; +} + +/* Handle the "nonnull" attribute. */ +static tree +handle_nonnull_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name ATTRIBUTE_UNUSED; + tree args; + int flags ATTRIBUTE_UNUSED; + bool *no_add_attrs; +{ + tree type = *node; + unsigned HOST_WIDE_INT attr_arg_num; + + /* If no arguments are specified, all pointer arguments should be + non-null. Veryify a full prototype is given so that the arguments + will have the correct types when we actually check them later. */ + if (! args) + { + if (! TYPE_ARG_TYPES (type)) + { + error ("nonnull attribute without arguments on a non-prototype"); + *no_add_attrs = true; + } + return NULL_TREE; + } + + /* Argument list specified. Verify that each argument number references + a pointer argument. */ + for (attr_arg_num = 1; args; args = TREE_CHAIN (args)) + { + tree argument; + unsigned HOST_WIDE_INT arg_num, ck_num; + + if (! get_nonnull_operand (TREE_VALUE (args), &arg_num)) + { + error ("nonnull argument has invalid operand number (arg %lu)", + (unsigned long) attr_arg_num); + *no_add_attrs = true; + return NULL_TREE; + } + + argument = TYPE_ARG_TYPES (type); + if (argument) + { + for (ck_num = 1; ; ck_num++) + { + if (! argument || ck_num == arg_num) + break; + argument = TREE_CHAIN (argument); + } + + if (! argument + || TREE_CODE (TREE_VALUE (argument)) == VOID_TYPE) + { + error ("nonnull argument with out-of-range operand number (arg %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) + { + error ("nonnull argument references non-pointer operand (arg %lu, operand %lu)", + (unsigned long) attr_arg_num, (unsigned long) arg_num); + *no_add_attrs = true; + return NULL_TREE; + } + } + } + + return NULL_TREE; +} + +/* Check the argument list of a function call for null in argument slots + that are marked as requiring a non-null pointer argument. */ + +static void +check_function_nonnull (attrs, params) + tree attrs; + tree params; +{ + tree a, args, param; + int param_num; + + for (a = attrs; a; a = TREE_CHAIN (a)) + { + if (is_attribute_p ("nonnull", TREE_PURPOSE (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 + for pointer type is done in check_nonnull_arg). */ + for (param = params, param_num = 1; ; + param_num++, param = TREE_CHAIN (param)) + { + if (! param) + break; + if (! args || nonnull_check_p (args, param_num)) + check_function_arguments_recurse (check_nonnull_arg, NULL, + TREE_VALUE (param), + param_num); + } + } + } +} + +/* Helper for check_function_nonnull; given a list of operands which + must be non-null in ARGS, determine if operand PARAM_NUM should be + checked. */ + +static bool +nonnull_check_p (args, param_num) + tree args; + unsigned HOST_WIDE_INT param_num; +{ + unsigned HOST_WIDE_INT arg_num; + + for (; args; args = TREE_CHAIN (args)) + { + if (! get_nonnull_operand (TREE_VALUE (args), &arg_num)) + abort (); + + if (arg_num == param_num) + return true; + } + return false; +} + +/* Check that the function argument PARAM (which is operand number + PARAM_NUM) is non-null. This is called by check_function_nonnull + via check_function_arguments_recurse. */ + +static void +check_nonnull_arg (ctx, param, param_num) + void *ctx ATTRIBUTE_UNUSED; + tree param; + unsigned HOST_WIDE_INT param_num; +{ + /* Just skip checking the argument if it's not a pointer. This can + happen if the "nonnull" attribute was given without an operand + list (which means to check every pointer argument). */ + + if (TREE_CODE (TREE_TYPE (param)) != POINTER_TYPE) + return; + + if (integer_zerop (param)) + warning ("null argument where non-null required (arg %lu)", + (unsigned long) param_num); +} + +/* Helper for nonnull attribute handling; fetch the operand number + from the attribute argument list. */ + +static bool +get_nonnull_operand (arg_num_expr, valp) + 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); + + if (TREE_CODE (arg_num_expr) != INTEGER_CST + || TREE_INT_CST_HIGH (arg_num_expr) != 0) + return false; + + *valp = TREE_INT_CST_LOW (arg_num_expr); + return true; +} + +/* Handle a "nothrow" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_nothrow_attribute (node, name, args, flags, no_add_attrs) + tree *node; + tree name; + tree args ATTRIBUTE_UNUSED; + int flags ATTRIBUTE_UNUSED; + 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)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Check for valid arguments being passed to a function. */ +void +check_function_arguments (attrs, params) + tree attrs; + tree params; +{ + /* 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. */ + + if (warn_nonnull) + check_function_nonnull (attrs, params); + + /* Check for errors in format strings. */ + + if (warn_format) + check_function_format (NULL, attrs, params); +} + +/* Generic argument checking recursion routine. PARAM is the argument to + be checked. PARAM_NUM is the number of the argument. CALLBACK is invoked + once the argument is resolved. CTX is context for the callback. */ +void +check_function_arguments_recurse (callback, ctx, param, param_num) + void (*callback) PARAMS ((void *, tree, unsigned HOST_WIDE_INT)); + void *ctx; + tree param; + unsigned HOST_WIDE_INT param_num; +{ + if (TREE_CODE (param) == NOP_EXPR) + { + /* Strip coercion. */ + check_function_arguments_recurse (callback, ctx, + TREE_OPERAND (param, 0), param_num); + return; + } + + if (TREE_CODE (param) == CALL_EXPR) + { + tree type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (param, 0))); + tree attrs; + bool found_format_arg = false; + + /* See if this is a call to a known internationalization function + that modifies a format arg. Such a function may have multiple + format_arg attributes (for example, ngettext). */ + + for (attrs = TYPE_ATTRIBUTES (type); + attrs; + attrs = TREE_CHAIN (attrs)) + if (is_attribute_p ("format_arg", TREE_PURPOSE (attrs))) + { + tree inner_args; + tree format_num_expr; + int format_num; + int i; + + /* 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 (); + + format_num = TREE_INT_CST_LOW (format_num_expr); + + for (inner_args = TREE_OPERAND (param, 1), i = 1; + inner_args != 0; + inner_args = TREE_CHAIN (inner_args), i++) + if (i == format_num) + { + check_function_arguments_recurse (callback, ctx, + TREE_VALUE (inner_args), + param_num); + found_format_arg = true; + break; + } + } + + /* If we found a format_arg attribute and did a recursive check, + we are done with checking this argument. Otherwise, we continue + and this will be considered a non-literal. */ + if (found_format_arg) + return; + } + + if (TREE_CODE (param) == COND_EXPR) + { + /* Check both halves of the conditional expression. */ + check_function_arguments_recurse (callback, ctx, + TREE_OPERAND (param, 1), param_num); + check_function_arguments_recurse (callback, ctx, + TREE_OPERAND (param, 2), param_num); + return; + } + + (*callback) (ctx, param, param_num); +} + +#include "gt-c-common.h" diff --git a/contrib/gcc/c-tree.h b/contrib/gcc/c-tree.h index 54208db..159c235 100644 --- a/contrib/gcc/c-tree.h +++ b/contrib/gcc/c-tree.h @@ -34,16 +34,32 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA lang_identifier nodes, because some keywords are only special in a particular context. */ -struct lang_identifier +struct lang_identifier GTY(()) { - struct c_common_identifier ignore; - tree global_value, local_value, label_value, implicit_decl; - tree error_locus, limbo_value; + struct c_common_identifier common_id; + tree global_value; + tree local_value; + tree label_value; + tree implicit_decl; + tree error_locus; + tree limbo_value; +}; + +/* The resulting tree type. */ + +union lang_tree_node + GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), + chain_next ("(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; }; /* Language-specific declaration information. */ -struct lang_decl +struct lang_decl GTY(()) { struct c_lang_decl base; /* The return types and parameter types may have variable size. @@ -107,10 +123,10 @@ struct lang_decl (DECL_LANG_SPECIFIC (NODE)->base.declared_inline) /* In a RECORD_TYPE, a sorted array of the fields of the type. */ -struct lang_type +struct lang_type GTY(()) { int len; - tree elts[1]; + tree GTY((length ("%h.len"))) elts[1]; }; /* Record whether a type or decl was written with nonconstant size. @@ -150,29 +166,36 @@ struct lang_type /* in c-lang.c and objc-act.c */ extern tree lookup_interface PARAMS ((tree)); extern tree is_class_name PARAMS ((tree)); -extern void maybe_objc_check_decl PARAMS ((tree)); +extern tree objc_is_id PARAMS ((tree)); +extern void objc_check_decl PARAMS ((tree)); extern void finish_file PARAMS ((void)); -extern int maybe_objc_comptypes PARAMS ((tree, tree, int)); -extern tree maybe_building_objc_message_expr PARAMS ((void)); -extern int recognize_objc_keyword PARAMS ((void)); +extern int objc_comptypes PARAMS ((tree, tree, int)); +extern tree objc_message_selector PARAMS ((void)); extern tree lookup_objc_ivar PARAMS ((tree)); /* in c-parse.in */ extern void c_parse_init PARAMS ((void)); -extern void c_set_yydebug PARAMS ((int)); -extern int yyparse_1 PARAMS ((void)); /* in c-aux-info.c */ extern void gen_aux_info_record PARAMS ((tree, int, int, int)); /* in c-decl.c */ +extern int global_bindings_p PARAMS ((void)); +extern int kept_level_p PARAMS ((void)); +extern tree getdecls PARAMS ((void)); +extern void pushlevel PARAMS ((int)); +extern tree poplevel PARAMS ((int,int, int)); +extern void insert_block PARAMS ((tree)); +extern void set_block PARAMS ((tree)); +extern tree pushdecl PARAMS ((tree)); + +extern void c_insert_default_attributes PARAMS ((tree)); extern void c_init_decl_processing PARAMS ((void)); +extern void c_dup_lang_specific_decl PARAMS ((tree)); extern void c_print_identifier PARAMS ((FILE *, tree, int)); extern tree build_array_declarator PARAMS ((tree, tree, int, int)); extern tree build_enumerator PARAMS ((tree, tree)); -extern int c_decode_option PARAMS ((int, char **)); -extern void c_mark_varargs PARAMS ((void)); extern void check_for_loop_decls PARAMS ((void)); extern void clear_parm_order PARAMS ((void)); extern int complete_array_type PARAMS ((tree, tree, int)); @@ -191,14 +214,12 @@ extern tree implicitly_declare PARAMS ((tree)); extern void implicit_decl_warning PARAMS ((tree)); extern int in_parm_level_p PARAMS ((void)); extern void keep_next_level PARAMS ((void)); -extern int kept_level_p PARAMS ((void)); extern tree lookup_name PARAMS ((tree)); extern tree lookup_name_current_level PARAMS ((tree)); extern void parmlist_tags_warning PARAMS ((void)); extern void pending_xref_error PARAMS ((void)); -extern void mark_c_function_context PARAMS ((struct function *)); -extern void push_c_function_context PARAMS ((struct function *)); -extern void pop_c_function_context PARAMS ((struct function *)); +extern void c_push_function_context PARAMS ((struct function *)); +extern void c_pop_function_context PARAMS ((struct function *)); extern void pop_label_level PARAMS ((void)); extern void push_label_level PARAMS ((void)); extern void push_parm_decl PARAMS ((tree)); @@ -218,7 +239,7 @@ extern tree xref_tag PARAMS ((enum tree_code, tree)); extern tree c_begin_compound_stmt PARAMS ((void)); extern void c_expand_deferred_function PARAMS ((tree)); extern void c_expand_decl_stmt PARAMS ((tree)); - +extern tree make_pointer_declarator PARAMS ((tree, tree)); /* in c-objc-common.c */ extern int c_disregard_inline_limits PARAMS ((tree)); @@ -227,23 +248,28 @@ extern const char *c_objc_common_init PARAMS ((const char *)); extern int c_missing_noreturn_ok_p PARAMS ((tree)); extern void c_objc_common_finish_file PARAMS ((void)); extern int defer_fn PARAMS ((tree)); +extern bool c_warn_unused_global_decl PARAMS ((tree)); #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 tree require_complete_type PARAMS ((tree)); extern int comptypes PARAMS ((tree, tree)); -extern tree c_sizeof_nowarn PARAMS ((tree)); extern tree c_size_in_bytes PARAMS ((tree)); +extern bool c_mark_addressable PARAMS ((tree)); +extern void c_incomplete_type_error PARAMS ((tree, tree)); +extern tree c_type_promotes_to PARAMS ((tree)); extern tree build_component_ref PARAMS ((tree, tree)); extern tree build_indirect_ref PARAMS ((tree, const char *)); extern tree build_array_ref PARAMS ((tree, tree)); extern tree build_external_ref PARAMS ((tree, int)); extern tree parser_build_binary_op PARAMS ((enum tree_code, tree, tree)); +extern int c_tree_expr_nonnegative_p PARAMS ((tree)); extern void readonly_warning PARAMS ((tree, const char *)); extern tree build_conditional_expr PARAMS ((tree, tree, tree)); extern tree build_compound_expr PARAMS ((tree)); @@ -287,94 +313,14 @@ extern int current_function_returns_null; extern int current_function_returns_abnormally; -/* Nonzero means `$' can be in an identifier. */ - -extern int dollars_in_ident; - -/* Nonzero means allow type mismatches in conditional expressions; - just make their values `void'. */ - -extern int flag_cond_mismatch; - -/* Nonzero means don't recognize the keyword `asm'. */ - -extern int flag_no_asm; - -/* Nonzero means warn about implicit declarations. */ - -extern int warn_implicit; - -/* Nonzero means warn for all old-style non-prototype function decls. */ - -extern int warn_strict_prototypes; - -/* Nonzero means warn about multiple (redundant) decls for the same single - variable or function. */ - -extern int warn_redundant_decls; - -/* 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; - -/* Nonzero means warn about pointer casts that can drop a type qualifier - from the pointer target type. */ - -extern int warn_cast_qual; - -/* 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; - -/* Warn about a subscript that has type char. */ - -extern int warn_char_subscripts; - -/* Warn if main is suspicious. */ - -extern int warn_main; - -/* Nonzero means to allow single precision math even if we're generally - being traditional. */ -extern int flag_allow_single_precision; - -/* Warn if initializer is not completely bracketed. */ - -extern int warn_missing_braces; - -/* Warn about comparison of signed and unsigned values. */ - -extern int warn_sign_compare; - -/* Warn about testing equality of floating point numbers. */ - -extern int warn_float_equal; - -/* Warn about multicharacter constants. */ - -extern int warn_multichar; - /* Nonzero means we are reading code that came from a system header file. */ extern int system_header_p; -/* Warn about implicit declarations. 1 = warning, 2 = error. */ -extern int mesg_implicit_function_declaration; - /* In c-decl.c */ -extern void finish_incomplete_decl PARAMS ((tree)); +extern void c_finish_incomplete_decl PARAMS ((tree)); -extern tree static_ctors; -extern tree static_dtors; +extern GTY(()) tree static_ctors; +extern GTY(()) tree static_dtors; #endif /* ! GCC_C_TREE_H */ diff --git a/contrib/gcc/config/alpha/alpha.c b/contrib/gcc/config/alpha/alpha.c index 3bc8e4d..9657e56 100644 --- a/contrib/gcc/config/alpha/alpha.c +++ b/contrib/gcc/config/alpha/alpha.c @@ -1,6 +1,6 @@ /* Subroutines used for code generation on the DEC Alpha. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001 Free Software Foundation, Inc. + 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) This file is part of GNU CC. @@ -47,6 +47,7 @@ Boston, MA 02111-1307, USA. */ #include "target.h" #include "target-def.h" #include "debug.h" +#include "langhooks.h" /* Specify which cpu to schedule for. */ @@ -68,6 +69,10 @@ enum alpha_fp_rounding_mode alpha_fprm; enum alpha_fp_trap_mode alpha_fptm; +/* Specify bit size of immediate TLS offsets. */ + +int alpha_tls_size = 32; + /* Strings decoded into the above options. */ const char *alpha_cpu_string; /* -mcpu= */ @@ -76,13 +81,14 @@ const char *alpha_tp_string; /* -mtrap-precision=[p|s|i] */ const char *alpha_fprm_string; /* -mfp-rounding-mode=[n|m|c|d] */ const char *alpha_fptm_string; /* -mfp-trap-mode=[n|u|su|sui] */ const char *alpha_mlat_string; /* -mmemory-latency= */ +const char *alpha_tls_size_string; /* -mtls-size=[16|32|64] */ /* Save information from a "cmpxx" operation until the branch or scc is emitted. */ struct alpha_compare alpha_compare; -/* Non-zero if inside of a function, because the Alpha asm can't +/* Nonzero if inside of a function, because the Alpha asm can't handle .files inside of functions. */ static int inside_function = FALSE; @@ -112,14 +118,22 @@ int alpha_this_literal_sequence_number; int alpha_this_gpdisp_sequence_number; /* Declarations of static functions. */ +static int tls_symbolic_operand_1 + PARAMS ((rtx, enum machine_mode, int, int)); +static enum tls_model tls_symbolic_operand_type + PARAMS ((rtx)); static bool decl_in_text_section PARAMS ((tree)); +static bool alpha_in_small_data_p + PARAMS ((tree)); +static void alpha_encode_section_info + PARAMS ((tree, int)); +static const char *alpha_strip_name_encoding + PARAMS ((const char *)); static int some_small_symbolic_operand_1 PARAMS ((rtx *, void *)); static int split_small_symbolic_operand_1 PARAMS ((rtx *, void *)); -static bool local_symbol_p - PARAMS ((rtx)); static void alpha_set_memflags_1 PARAMS ((rtx, int, int, int)); static rtx alpha_emit_set_const_1 @@ -128,9 +142,13 @@ static void alpha_expand_unaligned_load_words PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs)); static void alpha_expand_unaligned_store_words PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs)); +static void alpha_init_builtins + PARAMS ((void)); +static rtx alpha_expand_builtin + PARAMS ((tree, rtx, rtx, enum machine_mode, int)); static void alpha_sa_mask PARAMS ((unsigned long *imaskP, unsigned long *fmaskP)); -static int find_lo_sum +static int find_lo_sum_using_gp PARAMS ((rtx *, void *)); static int alpha_does_function_need_gp PARAMS ((void)); @@ -140,6 +158,10 @@ static const char *get_trap_mode_suffix PARAMS ((void)); static const char *get_round_mode_suffix PARAMS ((void)); +static const char *get_some_local_dynamic_name + PARAMS ((void)); +static int get_some_local_dynamic_name_1 + PARAMS ((rtx *, void *)); static rtx set_frame_related_p PARAMS ((void)); static const char *alpha_lookup_xfloating_lib_func @@ -156,18 +178,31 @@ static int alpha_adjust_cost PARAMS ((rtx, rtx, rtx, int)); static int alpha_issue_rate PARAMS ((void)); -static int alpha_variable_issue - PARAMS ((FILE *, int, rtx, int)); +static int alpha_use_dfa_pipeline_interface + PARAMS ((void)); +static int alpha_multipass_dfa_lookahead + PARAMS ((void)); -#if TARGET_ABI_UNICOSMK -static void alpha_init_machine_status - PARAMS ((struct function *p)); -static void alpha_mark_machine_status - PARAMS ((struct function *p)); -static void alpha_free_machine_status - PARAMS ((struct function *p)); +#ifdef OBJECT_FORMAT_ELF +static void alpha_elf_select_rtx_section + PARAMS ((enum machine_mode, rtx, unsigned HOST_WIDE_INT)); +#endif + +#if TARGET_ABI_OPEN_VMS +static bool alpha_linkage_symbol_p + PARAMS ((const char *symname)); +static void alpha_write_linkage + PARAMS ((FILE *, const char *, tree)); +#endif + +#if TARGET_ABI_OSF +static void alpha_output_mi_thunk_osf + PARAMS ((FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree)); #endif +static struct machine_function * alpha_init_machine_status + PARAMS ((void)); + static void unicosmk_output_deferred_case_vectors PARAMS ((FILE *)); static void unicosmk_gen_dsib PARAMS ((unsigned long *imaskP)); static void unicosmk_output_ssib PARAMS ((FILE *, const char *)); @@ -196,15 +231,27 @@ static void vms_asm_out_destructor PARAMS ((rtx, int)); # define TARGET_SECTION_TYPE_FLAGS vms_section_type_flags #endif +#undef TARGET_IN_SMALL_DATA_P +#define TARGET_IN_SMALL_DATA_P alpha_in_small_data_p +#undef TARGET_ENCODE_SECTION_INFO +#define TARGET_ENCODE_SECTION_INFO alpha_encode_section_info +#undef TARGET_STRIP_NAME_ENCODING +#define TARGET_STRIP_NAME_ENCODING alpha_strip_name_encoding + #if TARGET_ABI_UNICOSMK static void unicosmk_asm_named_section PARAMS ((const char *, unsigned int)); static void unicosmk_insert_attributes PARAMS ((tree, tree *)); static unsigned int unicosmk_section_type_flags PARAMS ((tree, const char *, int)); +static void unicosmk_unique_section PARAMS ((tree, int)); # undef TARGET_INSERT_ATTRIBUTES # define TARGET_INSERT_ATTRIBUTES unicosmk_insert_attributes # undef TARGET_SECTION_TYPE_FLAGS # define TARGET_SECTION_TYPE_FLAGS unicosmk_section_type_flags +# undef TARGET_ASM_UNIQUE_SECTION +# define TARGET_ASM_UNIQUE_SECTION unicosmk_unique_section +# undef TARGET_ASM_GLOBALIZE_LABEL +# define TARGET_ASM_GLOBALIZE_LABEL hook_FILEptr_constcharptr_void #endif #undef TARGET_ASM_ALIGNED_HI_OP @@ -223,6 +270,11 @@ static unsigned int unicosmk_section_type_flags PARAMS ((tree, const char *, #define TARGET_ASM_UNALIGNED_DI_OP "\t.align 0\n\t.quad\t" #endif +#ifdef OBJECT_FORMAT_ELF +#undef TARGET_ASM_SELECT_RTX_SECTION +#define TARGET_ASM_SELECT_RTX_SECTION alpha_elf_select_rtx_section +#endif + #undef TARGET_ASM_FUNCTION_END_PROLOGUE #define TARGET_ASM_FUNCTION_END_PROLOGUE alpha_output_function_end_prologue @@ -230,8 +282,27 @@ static unsigned int unicosmk_section_type_flags PARAMS ((tree, const char *, #define TARGET_SCHED_ADJUST_COST alpha_adjust_cost #undef TARGET_SCHED_ISSUE_RATE #define TARGET_SCHED_ISSUE_RATE alpha_issue_rate -#undef TARGET_SCHED_VARIABLE_ISSUE -#define TARGET_SCHED_VARIABLE_ISSUE alpha_variable_issue +#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE +#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE \ + alpha_use_dfa_pipeline_interface +#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD +#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \ + alpha_multipass_dfa_lookahead + +#undef TARGET_HAVE_TLS +#define TARGET_HAVE_TLS HAVE_AS_TLS + +#undef TARGET_INIT_BUILTINS +#define TARGET_INIT_BUILTINS alpha_init_builtins +#undef TARGET_EXPAND_BUILTIN +#define TARGET_EXPAND_BUILTIN alpha_expand_builtin + +#if TARGET_ABI_OSF +#undef TARGET_ASM_OUTPUT_MI_THUNK +#define TARGET_ASM_OUTPUT_MI_THUNK alpha_output_mi_thunk_osf +#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK +#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true +#endif struct gcc_target targetm = TARGET_INITIALIZER; @@ -352,6 +423,18 @@ override_options () error ("bad value `%s' for -mfp-trap-mode switch", alpha_fptm_string); } + if (alpha_tls_size_string) + { + if (strcmp (alpha_tls_size_string, "16") == 0) + alpha_tls_size = 16; + else if (strcmp (alpha_tls_size_string, "32") == 0) + alpha_tls_size = 32; + else if (strcmp (alpha_tls_size_string, "64") == 0) + alpha_tls_size = 64; + else + error ("bad value `%s' for -mtls-size switch", alpha_tls_size_string); + } + alpha_cpu = TARGET_CPU_DEFAULT & MASK_CPU_EV6 ? PROCESSOR_EV6 : (TARGET_CPU_DEFAULT & MASK_CPU_EV5 ? PROCESSOR_EV5 : PROCESSOR_EV4); @@ -494,12 +577,16 @@ override_options () /* Register variables and functions with the garbage collector. */ -#if TARGET_ABI_UNICOSMK /* Set up function hooks. */ init_machine_status = alpha_init_machine_status; - mark_machine_status = alpha_mark_machine_status; - free_machine_status = alpha_free_machine_status; -#endif + + /* Tell the compiler when we're using VAX floating point. */ + if (TARGET_FLOAT_VAX) + { + real_format_for_mode[SFmode - QFmode] = &vax_f_format; + real_format_for_mode[DFmode - QFmode] = &vax_g_format; + real_format_for_mode[TFmode - QFmode] = NULL; + } } /* Returns 1 if VALUE is a mask that contains full bytes of zero or ones. */ @@ -526,7 +613,7 @@ reg_or_0_operand (op, mode) register rtx op; enum machine_mode mode; { - return op == const0_rtx || register_operand (op, mode); + return op == CONST0_RTX (mode) || register_operand (op, mode); } /* Return 1 if OP is a constant in the range of 0-63 (for a shift) or @@ -555,6 +642,16 @@ reg_or_8bit_operand (op, mode) || register_operand (op, mode)); } +/* Return 1 if OP is a constant or any register. */ + +int +reg_or_const_int_operand (op, mode) + register rtx op; + enum machine_mode mode; +{ + return GET_CODE (op) == CONST_INT || register_operand (op, mode); +} + /* Return 1 if OP is an 8-bit constant. */ int @@ -661,24 +758,26 @@ mode_mask_operand (op, mode) register rtx op; enum machine_mode mode ATTRIBUTE_UNUSED; { -#if HOST_BITS_PER_WIDE_INT == 32 - if (GET_CODE (op) == CONST_DOUBLE) - return (CONST_DOUBLE_LOW (op) == -1 - && (CONST_DOUBLE_HIGH (op) == -1 - || CONST_DOUBLE_HIGH (op) == 0)); -#else - if (GET_CODE (op) == CONST_DOUBLE) - return (CONST_DOUBLE_LOW (op) == -1 && CONST_DOUBLE_HIGH (op) == 0); -#endif + if (GET_CODE (op) == CONST_INT) + { + HOST_WIDE_INT value = INTVAL (op); - return (GET_CODE (op) == CONST_INT - && (INTVAL (op) == 0xff - || INTVAL (op) == 0xffff - || INTVAL (op) == (HOST_WIDE_INT)0xffffffff -#if HOST_BITS_PER_WIDE_INT == 64 - || INTVAL (op) == -1 -#endif - )); + if (value == 0xff) + return 1; + if (value == 0xffff) + return 1; + if (value == 0xffffffff) + return 1; + if (value == -1) + return 1; + } + else if (HOST_BITS_PER_WIDE_INT == 32 && GET_CODE (op) == CONST_DOUBLE) + { + if (CONST_DOUBLE_LOW (op) == 0xffffffff && CONST_DOUBLE_HIGH (op) == 0) + return 1; + } + + return 0; } /* Return 1 if OP is a multiple of 8 less than 64. */ @@ -693,25 +792,14 @@ mul8_operand (op, mode) && (INTVAL (op) & 7) == 0); } -/* Return 1 if OP is the constant zero in floating-point. */ - -int -fp0_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - return (GET_MODE (op) == mode - && GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode)); -} - -/* Return 1 if OP is the floating-point constant zero or a register. */ +/* Return 1 if OP is the zero constant for MODE. */ int -reg_or_fp0_operand (op, mode) +const0_operand (op, mode) register rtx op; enum machine_mode mode; { - return fp0_operand (op, mode) || register_operand (op, mode); + return op == CONST0_RTX (mode); } /* Return 1 if OP is a hard floating-point register. */ @@ -769,8 +857,15 @@ some_operand (op, mode) switch (GET_CODE (op)) { - case REG: case MEM: case CONST_DOUBLE: case CONST_INT: case LABEL_REF: - case SYMBOL_REF: case CONST: case HIGH: + case REG: + case MEM: + case CONST_INT: + case CONST_DOUBLE: + case CONST_VECTOR: + case LABEL_REF: + case SYMBOL_REF: + case CONST: + case HIGH: return 1; case SUBREG: @@ -824,7 +919,9 @@ input_operand (op, mode) symbolic operands to be reconstructed from their high/lo_sum form. */ return (small_symbolic_operand (op, mode) - || global_symbolic_operand (op, mode)); + || global_symbolic_operand (op, mode) + || gotdtp_symbolic_operand (op, mode) + || gottp_symbolic_operand (op, mode)); } /* This handles both the Windows/NT and OSF cases. */ @@ -847,7 +944,8 @@ input_operand (op, mode) && general_operand (op, mode)); case CONST_DOUBLE: - return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode); + case CONST_VECTOR: + return op == CONST0_RTX (mode); case CONST_INT: return mode == QImode || mode == HImode || add_operand (op, mode); @@ -911,31 +1009,15 @@ direct_call_operand (op, mode) } /* Return true if OP is a LABEL_REF, or SYMBOL_REF or CONST referencing - a variable known to be defined in this file. */ - -static bool -local_symbol_p (op) - rtx op; -{ - const char *str = XSTR (op, 0); - - /* ??? SYMBOL_REF_FLAG is set for local function symbols, but we - run into problems with the rtl inliner in that the symbol was - once external, but is local after inlining, which results in - unrecognizable insns. */ - - return (CONSTANT_POOL_ADDRESS_P (op) - /* If @, then ENCODE_SECTION_INFO sez it's local. */ - || str[0] == '@' - /* If *$, then ASM_GENERATE_INTERNAL_LABEL sez it's local. */ - || (str[0] == '*' && str[1] == '$')); -} + a (non-tls) variable known to be defined in this file. */ int local_symbolic_operand (op, mode) rtx op; enum machine_mode mode; { + const char *str; + if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) return 0; @@ -950,7 +1032,26 @@ local_symbolic_operand (op, mode) if (GET_CODE (op) != SYMBOL_REF) return 0; - return local_symbol_p (op); + /* Easy pickings. */ + if (CONSTANT_POOL_ADDRESS_P (op) || STRING_POOL_ADDRESS_P (op)) + return 1; + + /* ??? SYMBOL_REF_FLAG is set for local function symbols, but we + run into problems with the rtl inliner in that the symbol was + once external, but is local after inlining, which results in + unrecognizable insns. */ + + str = XSTR (op, 0); + + /* If @[LS], then alpha_encode_section_info sez it's local. */ + if (str[0] == '@' && (str[1] == 'L' || str[1] == 'S')) + return 1; + + /* If *$, then ASM_GENERATE_INTERNAL_LABEL sez it's local. */ + if (str[0] == '*' && str[1] == '$') + return 1; + + return 0; } /* Return true if OP is a SYMBOL_REF or CONST referencing a variable @@ -982,7 +1083,7 @@ small_symbolic_operand (op, mode) else { str = XSTR (op, 0); - return str[0] == '@' && str[1] == 's'; + return str[0] == '@' && str[1] == 'S'; } } @@ -994,6 +1095,8 @@ global_symbolic_operand (op, mode) rtx op; enum machine_mode mode; { + const char *str; + if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) return 0; @@ -1005,7 +1108,12 @@ global_symbolic_operand (op, mode) if (GET_CODE (op) != SYMBOL_REF) return 0; - return ! local_symbol_p (op); + if (local_symbolic_operand (op, mode)) + return 0; + + /* Also verify that it's not a TLS symbol. */ + str = XSTR (op, 0); + return str[0] != '%' && str[0] != '@'; } /* Return 1 if OP is a valid operand for the MEM of a CALL insn. */ @@ -1058,6 +1166,110 @@ symbolic_operand (op, mode) return 0; } +/* Return true if OP is valid for a particular TLS relocation. */ + +static int +tls_symbolic_operand_1 (op, mode, size, unspec) + rtx op; + enum machine_mode mode; + int size, unspec; +{ + const char *str; + int letter; + + if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) + return 0; + + if (GET_CODE (op) != CONST) + return 0; + op = XEXP (op, 0); + + if (GET_CODE (op) != UNSPEC || XINT (op, 1) != unspec) + return 0; + op = XVECEXP (op, 0, 0); + + if (GET_CODE (op) != SYMBOL_REF) + return 0; + str = XSTR (op, 0); + + if (str[0] == '%') + { + if (size != 64) + return 0; + } + else if (str[0] == '@') + { + if (alpha_tls_size > size) + return 0; + } + else + return 0; + + letter = (unspec == UNSPEC_DTPREL ? 'D' : 'T'); + + return str[1] == letter; +} + +/* Return true if OP is valid for 16-bit DTP relative relocations. */ + +int +dtp16_symbolic_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return tls_symbolic_operand_1 (op, mode, 16, UNSPEC_DTPREL); +} + +/* Return true if OP is valid for 32-bit DTP relative relocations. */ + +int +dtp32_symbolic_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return tls_symbolic_operand_1 (op, mode, 32, UNSPEC_DTPREL); +} + +/* Return true if OP is valid for 64-bit DTP relative relocations. */ + +int +gotdtp_symbolic_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return tls_symbolic_operand_1 (op, mode, 64, UNSPEC_DTPREL); +} + +/* Return true if OP is valid for 16-bit TP relative relocations. */ + +int +tp16_symbolic_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return tls_symbolic_operand_1 (op, mode, 16, UNSPEC_TPREL); +} + +/* Return true if OP is valid for 32-bit TP relative relocations. */ + +int +tp32_symbolic_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return tls_symbolic_operand_1 (op, mode, 32, UNSPEC_TPREL); +} + +/* Return true if OP is valid for 64-bit TP relative relocations. */ + +int +gottp_symbolic_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return tls_symbolic_operand_1 (op, mode, 64, UNSPEC_TPREL); +} + /* Return 1 if OP is a valid Alpha comparison operator. Here we know which comparisons are valid in which insn. */ @@ -1455,7 +1667,9 @@ alpha_extra_constraint (value, c) return GET_CODE (value) == HIGH; case 'U': return TARGET_ABI_UNICOSMK && symbolic_operand (value, VOIDmode); - + case 'W': + return (GET_CODE (value) == CONST_VECTOR + && value == CONST0_RTX (GET_MODE (value))); default: return false; } @@ -1528,6 +1742,54 @@ alpha_tablejump_best_label (insn) return best_label ? best_label : const0_rtx; } + +/* Return the TLS model to use for SYMBOL. */ + +static enum tls_model +tls_symbolic_operand_type (symbol) + rtx symbol; +{ + const char *str; + + if (GET_CODE (symbol) != SYMBOL_REF) + return 0; + str = XSTR (symbol, 0); + + if (str[0] == '%') + { + /* ??? Be prepared for -ftls-model=local-dynamic. Perhaps we shouldn't + have separately encoded local-ness. On well, maybe the user will use + attribute visibility next time. At least we don't crash... */ + if (str[1] == 'G' || str[1] == 'D') + return TLS_MODEL_GLOBAL_DYNAMIC; + if (str[1] == 'T') + return TLS_MODEL_INITIAL_EXEC; + } + else if (str[0] == '@') + { + if (str[1] == 'D') + { + /* Local dynamic is a waste if we're not going to combine + the __tls_get_addr calls. So avoid it if not optimizing. */ + if (optimize) + return TLS_MODEL_LOCAL_DYNAMIC; + else + return TLS_MODEL_GLOBAL_DYNAMIC; + } + if (str[1] == 'T') + { + /* 64-bit local exec is the same as initial exec except without + the dynamic relocation. In either case we use a got entry. */ + if (alpha_tls_size == 64) + return TLS_MODEL_INITIAL_EXEC; + else + return TLS_MODEL_LOCAL_EXEC; + } + } + + return 0; +} + /* Return true if the function DECL will be placed in the default text section. */ @@ -1545,6 +1807,36 @@ decl_in_text_section (decl) && DECL_ONE_ONLY (decl)))); } +/* Return true if EXP should be placed in the small data section. */ + +static bool +alpha_in_small_data_p (exp) + tree exp; +{ + /* We want to merge strings, so we never consider them small data. */ + if (TREE_CODE (exp) == STRING_CST) + return false; + + if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp)) + { + const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp)); + if (strcmp (section, ".sdata") == 0 + || strcmp (section, ".sbss") == 0) + return true; + } + else + { + HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp)); + + /* If this is an incomplete type with size 0, then we can't put it + in sdata because it might be too big when completed. */ + if (size > 0 && size <= g_switch_value) + return true; + } + + return false; +} + /* If we are referencing a function that is static, make the SYMBOL_REF special. We use this to see indicate we can branch to this function without setting PV or restoring GP. @@ -1553,25 +1845,38 @@ decl_in_text_section (decl) to the name. If in addition the variable is to go in .sdata/.sbss, then add "@s" instead. */ -void -alpha_encode_section_info (decl) +static void +alpha_encode_section_info (decl, first) tree decl; + int first ATTRIBUTE_UNUSED; { const char *symbol_str; - bool is_local, is_small; + bool is_local; + char encoding = 0; + rtx rtl, symbol; + + rtl = DECL_P (decl) ? DECL_RTL (decl) : TREE_CST_RTL (decl); + /* Careful not to prod global register variables. */ + if (GET_CODE (rtl) != MEM) + return; + symbol = XEXP (rtl, 0); + if (GET_CODE (symbol) != SYMBOL_REF) + return; + if (TREE_CODE (decl) == FUNCTION_DECL) { /* We mark public functions once they are emitted; otherwise we don't know that they exist in this unit of translation. */ if (TREE_PUBLIC (decl)) return; + /* Do not mark functions that are not in .text; otherwise we don't know that they are near enough for a direct branch. */ if (! decl_in_text_section (decl)) return; - SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1; + SYMBOL_REF_FLAG (symbol) = 1; return; } @@ -1579,98 +1884,100 @@ alpha_encode_section_info (decl) if (! TARGET_EXPLICIT_RELOCS) return; - /* Careful not to prod global register variables. */ - if (TREE_CODE (decl) != VAR_DECL - || GET_CODE (DECL_RTL (decl)) != MEM - || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF) - return; - - symbol_str = XSTR (XEXP (DECL_RTL (decl), 0), 0); + symbol_str = XSTR (symbol, 0); /* A variable is considered "local" if it is defined in this module. */ + is_local = (*targetm.binds_local_p) (decl); - if (DECL_EXTERNAL (decl)) - is_local = false; - /* Linkonce and weak data is never local. */ - else if (DECL_ONE_ONLY (decl) || DECL_WEAK (decl)) - is_local = false; - else if (! TREE_PUBLIC (decl)) - is_local = true; - /* If PIC, then assume that any global name can be overridden by - symbols resolved from other modules. */ - else if (flag_pic) - is_local = false; - /* Uninitialized COMMON variable may be unified with symbols - resolved from other modules. */ - else if (DECL_COMMON (decl) - && (DECL_INITIAL (decl) == NULL - || DECL_INITIAL (decl) == error_mark_node)) - is_local = false; - /* Otherwise we're left with initialized (or non-common) global data - which is of necessity defined locally. */ - else - is_local = true; - - /* Determine if DECL will wind up in .sdata/.sbss. */ - - is_small = false; - if (DECL_SECTION_NAME (decl)) + /* Care for TLS variables. */ + if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl)) { - const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (decl)); - if (strcmp (section, ".sdata") == 0 - || strcmp (section, ".sbss") == 0) - is_small = true; + switch (decl_tls_model (decl)) + { + case TLS_MODEL_GLOBAL_DYNAMIC: + encoding = 'G'; + break; + case TLS_MODEL_LOCAL_DYNAMIC: + encoding = 'D'; + break; + case TLS_MODEL_INITIAL_EXEC: + case TLS_MODEL_LOCAL_EXEC: + encoding = 'T'; + break; + } } - else + else if (is_local) { - HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl)); - - /* If the variable has already been defined in the output file, then it - is too late to put it in sdata if it wasn't put there in the first - place. The test is here rather than above, because if it is already - in sdata, then it can stay there. */ - - if (TREE_ASM_WRITTEN (decl)) - ; - - /* If this is an incomplete type with size 0, then we can't put it in - sdata because it might be too big when completed. */ - else if (size > 0 && size <= g_switch_value) - is_small = true; + /* Determine if DECL will wind up in .sdata/.sbss. */ + if (alpha_in_small_data_p (decl)) + encoding = 'S'; + else + encoding = 'L'; } /* Finally, encode this into the symbol string. */ - if (is_local) + if (encoding) { - const char *string; char *newstr; size_t len; + char want_prefix = (is_local ? '@' : '%'); + char other_prefix = (is_local ? '%' : '@'); - if (symbol_str[0] == '@') + if (symbol_str[0] == want_prefix) { - if (symbol_str[1] == (is_small ? 's' : 'v')) + if (symbol_str[1] == encoding) return; symbol_str += 2; } + else if (symbol_str[0] == other_prefix) + symbol_str += 2; len = strlen (symbol_str) + 1; newstr = alloca (len + 2); - newstr[0] = '@'; - newstr[1] = (is_small ? 's' : 'v'); + newstr[0] = want_prefix; + newstr[1] = encoding; memcpy (newstr + 2, symbol_str, len); - string = ggc_alloc_string (newstr, len + 2 - 1); - XSTR (XEXP (DECL_RTL (decl), 0), 0) = string; - } - else if (symbol_str[0] == '@') - { - /* We're hosed. This can happen when the user adds a weak - attribute after rtl generation. They should have gotten - a warning about unspecified behaviour from varasm.c. */ + XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2 - 1); } } +/* Undo the effects of the above. */ + +static const char * +alpha_strip_name_encoding (str) + const char *str; +{ + if (str[0] == '@' || str[0] == '%') + str += 2; + if (str[0] == '*') + str++; + return str; +} + +#if TARGET_ABI_OPEN_VMS +static bool +alpha_linkage_symbol_p (symname) + const char *symname; +{ + int symlen = strlen (symname); + + if (symlen > 4) + return strcmp (&symname [symlen - 4], "..lk") == 0; + + return false; +} + +#define LINKAGE_SYMBOL_REF_P(X) \ + ((GET_CODE (X) == SYMBOL_REF \ + && alpha_linkage_symbol_p (XSTR (X, 0))) \ + || (GET_CODE (X) == CONST \ + && GET_CODE (XEXP (X, 0)) == PLUS \ + && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF \ + && alpha_linkage_symbol_p (XSTR (XEXP (XEXP (X, 0), 0), 0)))) +#endif + /* legitimate_address_p recognizes an RTL expression that is a valid memory address for an instruction. The MODE argument is the machine mode for the MEM expression that wants to use this address. @@ -1710,6 +2017,11 @@ alpha_legitimate_address_p (mode, x, strict) if (CONSTANT_ADDRESS_P (x)) return true; +#if TARGET_ABI_OPEN_VMS + if (LINKAGE_SYMBOL_REF_P (x)) + return true; +#endif + /* Register plus a small constant offset is valid. */ if (GET_CODE (x) == PLUS) { @@ -1765,7 +2077,9 @@ alpha_legitimate_address_p (mode, x, strict) return false; /* The symbol must be local. */ - if (local_symbolic_operand (ofs, Pmode)) + if (local_symbolic_operand (ofs, Pmode) + || dtp32_symbolic_operand (ofs, Pmode) + || tp32_symbolic_operand (ofs, Pmode)) return true; } } @@ -1831,6 +2145,100 @@ alpha_legitimize_address (x, scratch, mode) /* If this is a local symbol, split the address into HIGH/LO_SUM parts. */ if (TARGET_EXPLICIT_RELOCS && symbolic_operand (x, Pmode)) { + rtx r0, r16, eqv, tga, tp, insn, dest, seq; + + switch (tls_symbolic_operand_type (x)) + { + case TLS_MODEL_GLOBAL_DYNAMIC: + start_sequence (); + + r0 = gen_rtx_REG (Pmode, 0); + r16 = gen_rtx_REG (Pmode, 16); + tga = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_addr"); + dest = gen_reg_rtx (Pmode); + seq = GEN_INT (alpha_next_sequence_number++); + + emit_insn (gen_movdi_er_tlsgd (r16, pic_offset_table_rtx, x, seq)); + insn = gen_call_value_osf_tlsgd (r0, tga, seq); + insn = emit_call_insn (insn); + CONST_OR_PURE_CALL_P (insn) = 1; + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16); + + insn = get_insns (); + end_sequence (); + + emit_libcall_block (insn, dest, r0, x); + return dest; + + case TLS_MODEL_LOCAL_DYNAMIC: + start_sequence (); + + r0 = gen_rtx_REG (Pmode, 0); + r16 = gen_rtx_REG (Pmode, 16); + tga = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_addr"); + scratch = gen_reg_rtx (Pmode); + seq = GEN_INT (alpha_next_sequence_number++); + + emit_insn (gen_movdi_er_tlsldm (r16, pic_offset_table_rtx, seq)); + insn = gen_call_value_osf_tlsldm (r0, tga, seq); + insn = emit_call_insn (insn); + CONST_OR_PURE_CALL_P (insn) = 1; + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16); + + insn = get_insns (); + end_sequence (); + + eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), + UNSPEC_TLSLDM_CALL); + emit_libcall_block (insn, scratch, r0, eqv); + + eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPREL); + eqv = gen_rtx_CONST (Pmode, eqv); + + if (alpha_tls_size == 64) + { + dest = gen_reg_rtx (Pmode); + emit_insn (gen_rtx_SET (VOIDmode, dest, eqv)); + emit_insn (gen_adddi3 (dest, dest, scratch)); + return dest; + } + if (alpha_tls_size == 32) + { + insn = gen_rtx_HIGH (Pmode, eqv); + insn = gen_rtx_PLUS (Pmode, scratch, insn); + scratch = gen_reg_rtx (Pmode); + emit_insn (gen_rtx_SET (VOIDmode, scratch, insn)); + } + return gen_rtx_LO_SUM (Pmode, scratch, eqv); + + case TLS_MODEL_INITIAL_EXEC: + eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_TPREL); + eqv = gen_rtx_CONST (Pmode, eqv); + tp = gen_reg_rtx (Pmode); + scratch = gen_reg_rtx (Pmode); + dest = gen_reg_rtx (Pmode); + + emit_insn (gen_load_tp (tp)); + emit_insn (gen_rtx_SET (VOIDmode, scratch, eqv)); + emit_insn (gen_adddi3 (dest, tp, scratch)); + return dest; + + case TLS_MODEL_LOCAL_EXEC: + eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_TPREL); + eqv = gen_rtx_CONST (Pmode, eqv); + tp = gen_reg_rtx (Pmode); + + emit_insn (gen_load_tp (tp)); + if (alpha_tls_size == 32) + { + insn = gen_rtx_HIGH (Pmode, eqv); + insn = gen_rtx_PLUS (Pmode, tp, insn); + tp = gen_reg_rtx (Pmode); + emit_insn (gen_rtx_SET (VOIDmode, tp, insn)); + } + return gen_rtx_LO_SUM (Pmode, tp, eqv); + } + if (local_symbolic_operand (x, Pmode)) { if (small_symbolic_operand (x, Pmode)) @@ -2156,6 +2564,8 @@ alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p) switch (GET_CODE (x)) { case SEQUENCE: + abort (); + case PARALLEL: for (i = XVECLEN (x, 0) - 1; i >= 0; i--) alpha_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p, @@ -2190,11 +2600,11 @@ alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p) } } -/* Given INSN, which is either an INSN or a SEQUENCE generated to - perform a memory operation, look for any MEMs in either a SET_DEST or - a SET_SRC and copy the in-struct, unchanging, and volatile flags from - REF into each of the MEMs found. If REF is not a MEM, don't do - anything. */ +/* Given INSN, which is an INSN list or the PATTERN of a single insn + generated to perform a memory operation, look for any MEMs in either + a SET_DEST or a SET_SRC and copy the in-struct, unchanging, and + volatile flags from REF into each of the MEMs found. If REF is not + a MEM, don't do anything. */ void alpha_set_memflags (insn, ref) @@ -2555,6 +2965,8 @@ alpha_expand_mov (mode, operands) tmp = alpha_legitimize_address (operands[1], operands[0], mode); if (tmp) { + if (tmp == operands[0]) + return true; operands[1] = tmp; return false; } @@ -2603,7 +3015,7 @@ alpha_expand_mov (mode, operands) } /* Otherwise we've nothing left but to drop the thing to memory. */ - operands[1] = force_const_mem (DImode, operands[1]); + operands[1] = force_const_mem (mode, operands[1]); if (reload_in_progress) { emit_move_insn (operands[0], XEXP (operands[1], 0)); @@ -2907,7 +3319,7 @@ alpha_emit_conditional_branch (code) } else { - /* ??? We mark the the branch mode to be CCmode to prevent the + /* ??? We mark the branch mode to be CCmode to prevent the compare and branch from being combined, since the compare insn follows IEEE rules that the branch does not. */ branch_mode = CCmode; @@ -3075,7 +3487,7 @@ alpha_emit_setcc (code) /* Rewrite a comparison against zero CMP of the form (CODE (cc0) (const_int 0)) so it can be written validly in a conditional move (if_then_else CMP ...). - If both of the operands that set cc0 are non-zero we must emit + If both of the operands that set cc0 are nonzero we must emit an insn to perform the compare (it can't be done within the conditional move). */ rtx @@ -3107,7 +3519,7 @@ alpha_emit_conditional_move (cmp, mode) /* If we have fp<->int register move instructions, do a cmov by performing the comparison in fp registers, and move the - zero/non-zero value to integer registers, where we can then + zero/nonzero value to integer registers, where we can then use a normal cmov, or vice-versa. */ switch (code) @@ -3639,7 +4051,7 @@ alpha_split_tfmode_frobsign (operands, operation) alpha_split_tfmode_pair (operands); - /* Detect three flavours of operand overlap. */ + /* Detect three flavors of operand overlap. */ move = 1; if (rtx_equal_p (operands[0], operands[2])) move = 0; @@ -3885,17 +4297,13 @@ alpha_expand_unaligned_store (dst, src, size, ofs) emit_insn (gen_mskxl_be (dsth, dsth, GEN_INT (0xffff), addr)); break; case 4: - emit_insn (gen_mskxl_be (dsth, dsth, GEN_INT (0xffffffff), addr)); - break; - case 8: { -#if HOST_BITS_PER_WIDE_INT == 32 - rtx msk = immed_double_const (0xffffffff, 0xffffffff, DImode); -#else - rtx msk = constm1_rtx; -#endif + rtx msk = immed_double_const (0xffffffff, 0, DImode); emit_insn (gen_mskxl_be (dsth, dsth, msk, addr)); + break; } + case 8: + emit_insn (gen_mskxl_be (dsth, dsth, constm1_rtx, addr)); break; } @@ -3932,17 +4340,13 @@ alpha_expand_unaligned_store (dst, src, size, ofs) emit_insn (gen_mskxl_le (dstl, dstl, GEN_INT (0xffff), addr)); break; case 4: - emit_insn (gen_mskxl_le (dstl, dstl, GEN_INT (0xffffffff), addr)); - break; - case 8: { -#if HOST_BITS_PER_WIDE_INT == 32 - rtx msk = immed_double_const (0xffffffff, 0xffffffff, DImode); -#else - rtx msk = constm1_rtx; -#endif + rtx msk = immed_double_const (0xffffffff, 0, DImode); emit_insn (gen_mskxl_le (dstl, dstl, msk, addr)); + break; } + case 8: + emit_insn (gen_mskxl_le (dstl, dstl, constm1_rtx, addr)); break; } } @@ -4068,11 +4472,6 @@ alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs) { rtx const im8 = GEN_INT (-8); rtx const i64 = GEN_INT (64); -#if HOST_BITS_PER_WIDE_INT == 32 - rtx const im1 = immed_double_const (0xffffffff, 0xffffffff, DImode); -#else - rtx const im1 = constm1_rtx; -#endif rtx ins_tmps[MAX_MOVE_WORDS]; rtx st_tmp_1, st_tmp_2, dreg; rtx st_addr_1, st_addr_2, dmema; @@ -4136,13 +4535,13 @@ alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs) /* Split and merge the ends with the destination data. */ if (WORDS_BIG_ENDIAN) { - emit_insn (gen_mskxl_be (st_tmp_2, st_tmp_2, im1, dreg)); + emit_insn (gen_mskxl_be (st_tmp_2, st_tmp_2, constm1_rtx, dreg)); emit_insn (gen_mskxh (st_tmp_1, st_tmp_1, i64, dreg)); } else { emit_insn (gen_mskxh (st_tmp_2, st_tmp_2, i64, dreg)); - emit_insn (gen_mskxl_le (st_tmp_1, st_tmp_1, im1, dreg)); + emit_insn (gen_mskxl_le (st_tmp_1, st_tmp_1, constm1_rtx, dreg)); } if (data_regs != NULL) @@ -4807,6 +5206,75 @@ alpha_expand_block_clear (operands) return 1; } + +/* Returns a mask so that zap(x, value) == x & mask. */ + +rtx +alpha_expand_zap_mask (value) + HOST_WIDE_INT value; +{ + rtx result; + int i; + + if (HOST_BITS_PER_WIDE_INT >= 64) + { + HOST_WIDE_INT mask = 0; + + for (i = 7; i >= 0; --i) + { + mask <<= 8; + if (!((value >> i) & 1)) + mask |= 0xff; + } + + result = gen_int_mode (mask, DImode); + } + else if (HOST_BITS_PER_WIDE_INT == 32) + { + HOST_WIDE_INT mask_lo = 0, mask_hi = 0; + + for (i = 7; i >= 4; --i) + { + mask_hi <<= 8; + if (!((value >> i) & 1)) + mask_hi |= 0xff; + } + + for (i = 3; i >= 0; --i) + { + mask_lo <<= 8; + if (!((value >> i) & 1)) + mask_lo |= 0xff; + } + + result = immed_double_const (mask_lo, mask_hi, DImode); + } + else + abort (); + + return result; +} + +void +alpha_expand_builtin_vector_binop (gen, mode, op0, op1, op2) + rtx (*gen) PARAMS ((rtx, rtx, rtx)); + enum machine_mode mode; + rtx op0, op1, op2; +{ + op0 = gen_lowpart (mode, op0); + + if (op1 == const0_rtx) + op1 = CONST0_RTX (mode); + else + op1 = gen_lowpart (mode, op1); + + if (op2 == const0_rtx) + op2 = CONST0_RTX (mode); + else + op2 = gen_lowpart (mode, op2); + + emit_insn ((*gen) (op0, op1, op2)); +} /* Adjust the cost of a scheduling dependency. Return the new cost of a dependency LINK or INSN on DEP_INSN. COST is the current cost. */ @@ -4818,15 +5286,13 @@ alpha_adjust_cost (insn, link, dep_insn, cost) rtx dep_insn; int cost; { - rtx set, set_src; enum attr_type insn_type, dep_insn_type; /* If the dependence is an anti-dependence, there is no cost. For an output dependence, there is sometimes a cost, but it doesn't seem worth handling those few cases. */ - if (REG_NOTE_KIND (link) != 0) - return 0; + return cost; /* If we can't recognize the insns, we can't really do anything. */ if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0) @@ -4841,122 +5307,13 @@ alpha_adjust_cost (insn, link, dep_insn, cost) || dep_insn_type == TYPE_LDSYM) cost += alpha_memory_latency-1; - switch (alpha_cpu) - { - case PROCESSOR_EV4: - /* On EV4, if INSN is a store insn and DEP_INSN is setting the data - being stored, we can sometimes lower the cost. */ - - if ((insn_type == TYPE_IST || insn_type == TYPE_FST) - && (set = single_set (dep_insn)) != 0 - && GET_CODE (PATTERN (insn)) == SET - && rtx_equal_p (SET_DEST (set), SET_SRC (PATTERN (insn)))) - { - switch (dep_insn_type) - { - case TYPE_ILD: - case TYPE_FLD: - /* No savings here. */ - return cost; - - case TYPE_IMUL: - /* In these cases, we save one cycle. */ - return cost - 1; - - default: - /* In all other cases, we save two cycles. */ - return MAX (0, cost - 2); - } - } - - /* Another case that needs adjustment is an arithmetic or logical - operation. It's cost is usually one cycle, but we default it to - two in the MD file. The only case that it is actually two is - for the address in loads, stores, and jumps. */ - - if (dep_insn_type == TYPE_IADD || dep_insn_type == TYPE_ILOG) - { - switch (insn_type) - { - case TYPE_ILD: - case TYPE_IST: - case TYPE_FLD: - case TYPE_FST: - case TYPE_JSR: - return cost; - default: - return 1; - } - } - - /* The final case is when a compare feeds into an integer branch; - the cost is only one cycle in that case. */ - - if (dep_insn_type == TYPE_ICMP && insn_type == TYPE_IBR) - return 1; - break; - - case PROCESSOR_EV5: - /* And the lord DEC saith: "A special bypass provides an effective - latency of 0 cycles for an ICMP or ILOG insn producing the test - operand of an IBR or ICMOV insn." */ - - if ((dep_insn_type == TYPE_ICMP || dep_insn_type == TYPE_ILOG) - && (set = single_set (dep_insn)) != 0) - { - /* A branch only has one input. This must be it. */ - if (insn_type == TYPE_IBR) - return 0; - /* A conditional move has three, make sure it is the test. */ - if (insn_type == TYPE_ICMOV - && GET_CODE (set_src = PATTERN (insn)) == SET - && GET_CODE (set_src = SET_SRC (set_src)) == IF_THEN_ELSE - && rtx_equal_p (SET_DEST (set), XEXP (set_src, 0))) - return 0; - } - - /* "The multiplier is unable to receive data from IEU bypass paths. - The instruction issues at the expected time, but its latency is - increased by the time it takes for the input data to become - available to the multiplier" -- which happens in pipeline stage - six, when results are comitted to the register file. */ - - if (insn_type == TYPE_IMUL) - { - switch (dep_insn_type) - { - /* These insns produce their results in pipeline stage five. */ - case TYPE_ILD: - case TYPE_ICMOV: - case TYPE_IMUL: - case TYPE_MVI: - return cost + 1; - - /* Other integer insns produce results in pipeline stage four. */ - default: - return cost + 2; - } - } - break; - - case PROCESSOR_EV6: - /* There is additional latency to move the result of (most) FP - operations anywhere but the FP register file. */ + /* Everything else handled in DFA bypasses now. */ - if ((insn_type == TYPE_FST || insn_type == TYPE_FTOI) - && (dep_insn_type == TYPE_FADD || - dep_insn_type == TYPE_FMUL || - dep_insn_type == TYPE_FCMOV)) - return cost + 2; - - break; - } - - /* Otherwise, return the default cost. */ return cost; } -/* Function to initialize the issue rate used by the scheduler. */ +/* The number of instructions that can be issued per cycle. */ + static int alpha_issue_rate () { @@ -4964,57 +5321,50 @@ alpha_issue_rate () } static int -alpha_variable_issue (dump, verbose, insn, cim) - FILE *dump ATTRIBUTE_UNUSED; - int verbose ATTRIBUTE_UNUSED; - rtx insn; - int cim; +alpha_use_dfa_pipeline_interface () { - if (recog_memoized (insn) < 0 || get_attr_type (insn) == TYPE_MULTI) - return 0; - - return cim - 1; + return true; } - -/* Register global variables and machine-specific functions with the - garbage collector. */ +/* How many alternative schedules to try. This should be as wide as the + scheduling freedom in the DFA, but no wider. Making this value too + large results extra work for the scheduler. -#if TARGET_ABI_UNICOSMK -static void -alpha_init_machine_status (p) - struct function *p; -{ - p->machine = - (struct machine_function *) xcalloc (1, sizeof (struct machine_function)); + For EV4, loads can be issued to either IB0 or IB1, thus we have 2 + alternative schedules. For EV5, we can choose between E0/E1 and + FA/FM. For EV6, an arithmatic insn can be issued to U0/U1/L0/L1. */ - p->machine->first_ciw = NULL_RTX; - p->machine->last_ciw = NULL_RTX; - p->machine->ciw_count = 0; - p->machine->addr_list = NULL_RTX; +static int +alpha_multipass_dfa_lookahead () +{ + return (alpha_cpu == PROCESSOR_EV6 ? 4 : 2); } + +/* Machine-specific function data. */ -static void -alpha_mark_machine_status (p) - struct function *p; +struct machine_function GTY(()) { - struct machine_function *machine = p->machine; + /* For unicosmk. */ + /* List of call information words for calls from this function. */ + struct rtx_def *first_ciw; + struct rtx_def *last_ciw; + int ciw_count; - if (machine) - { - ggc_mark_rtx (machine->first_ciw); - ggc_mark_rtx (machine->addr_list); - } -} + /* List of deferred case vectors. */ + struct rtx_def *addr_list; -static void -alpha_free_machine_status (p) - struct function *p; + /* For OSF. */ + const char *some_ld_name; +}; + +/* How to allocate a 'struct machine_function'. */ + +static struct machine_function * +alpha_init_machine_status () { - free (p->machine); - p->machine = NULL; + return ((struct machine_function *) + ggc_alloc_cleared (sizeof (struct machine_function))); } -#endif /* TARGET_ABI_UNICOSMK */ /* Functions to save and restore alpha_return_addr_rtx. */ @@ -5039,7 +5389,7 @@ alpha_gp_save_rtx () { rtx r = get_hard_reg_initial_val (DImode, 29); if (GET_CODE (r) != MEM) - r = gen_mem_addressof (r, NULL_TREE); + r = gen_mem_addressof (r, NULL_TREE, /*rescan=*/true); return r; } @@ -5158,6 +5508,45 @@ get_round_mode_suffix () abort (); } +/* Locate some local-dynamic symbol still in use by this function + so that we can print its name in some movdi_er_tlsldm pattern. */ + +static const char * +get_some_local_dynamic_name () +{ + rtx insn; + + if (cfun->machine->some_ld_name) + return cfun->machine->some_ld_name; + + for (insn = get_insns (); insn ; insn = NEXT_INSN (insn)) + if (INSN_P (insn) + && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0)) + return cfun->machine->some_ld_name; + + abort (); +} + +static int +get_some_local_dynamic_name_1 (px, data) + rtx *px; + void *data ATTRIBUTE_UNUSED; +{ + rtx x = *px; + + if (GET_CODE (x) == SYMBOL_REF) + { + const char *str = XSTR (x, 0); + if (str[0] == '@' && str[1] == 'D') + { + cfun->machine->some_ld_name = str; + return 1; + } + } + + return 0; +} + /* Print an operand. Recognize special options, documented below. */ void @@ -5175,6 +5564,10 @@ print_operand (file, x, code) assemble_name (file, alpha_fnname); break; + case '&': + assemble_name (file, get_some_local_dynamic_name ()); + break; + case '/': { const char *trap = get_trap_mode_suffix (); @@ -5216,13 +5609,30 @@ print_operand (file, x, code) break; case 'J': - if (GET_CODE (x) == CONST_INT) - { - if (INTVAL (x) != 0) - fprintf (file, "\t\t!lituse_jsr!%d", (int) INTVAL (x)); - } - else - output_operand_lossage ("invalid %%J value"); + { + const char *lituse; + + if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSGD_CALL) + { + x = XVECEXP (x, 0, 0); + lituse = "lituse_tlsgd"; + } + else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSLDM_CALL) + { + x = XVECEXP (x, 0, 0); + lituse = "lituse_tlsldm"; + } + else if (GET_CODE (x) == CONST_INT) + lituse = "lituse_jsr"; + else + { + output_operand_lossage ("invalid %%J value"); + break; + } + + if (x != const0_rtx) + fprintf (file, "\t\t!%s!%d", lituse, (int) INTVAL (x)); + } break; case 'r': @@ -5330,31 +5740,40 @@ print_operand (file, x, code) case 'U': /* Similar, except do it from the mask. */ - if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xff) - fprintf (file, "b"); - else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffff) - fprintf (file, "w"); - else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffff) - fprintf (file, "l"); -#if HOST_BITS_PER_WIDE_INT == 32 - else if (GET_CODE (x) == CONST_DOUBLE - && CONST_DOUBLE_HIGH (x) == 0 - && CONST_DOUBLE_LOW (x) == -1) - fprintf (file, "l"); - else if (GET_CODE (x) == CONST_DOUBLE - && CONST_DOUBLE_HIGH (x) == -1 - && CONST_DOUBLE_LOW (x) == -1) - fprintf (file, "q"); -#else - else if (GET_CODE (x) == CONST_INT && INTVAL (x) == -1) - fprintf (file, "q"); - else if (GET_CODE (x) == CONST_DOUBLE - && CONST_DOUBLE_HIGH (x) == 0 - && CONST_DOUBLE_LOW (x) == -1) - fprintf (file, "q"); -#endif - else - output_operand_lossage ("invalid %%U value"); + if (GET_CODE (x) == CONST_INT) + { + HOST_WIDE_INT value = INTVAL (x); + + if (value == 0xff) + { + fputc ('b', file); + break; + } + if (value == 0xffff) + { + fputc ('w', file); + break; + } + if (value == 0xffffffff) + { + fputc ('l', file); + break; + } + if (value == -1) + { + fputc ('q', file); + break; + } + } + else if (HOST_BITS_PER_WIDE_INT == 32 + && GET_CODE (x) == CONST_DOUBLE + && CONST_DOUBLE_LOW (x) == 0xffffffff + && CONST_DOUBLE_HIGH (x) == 0) + { + fputc ('l', file); + break; + } + output_operand_lossage ("invalid %%U value"); break; case 's': @@ -5456,6 +5875,19 @@ print_operand (file, x, code) fprintf (file, "%s", reg_names[REGNO (x)]); else if (GET_CODE (x) == MEM) output_address (XEXP (x, 0)); + else if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == UNSPEC) + { + switch (XINT (XEXP (x, 0), 1)) + { + case UNSPEC_DTPREL: + case UNSPEC_TPREL: + output_addr_const (file, XVECEXP (XEXP (x, 0), 0, 0)); + break; + default: + output_operand_lossage ("unknown relocation unspec"); + break; + } + } else output_addr_const (file, x); break; @@ -5485,7 +5917,36 @@ print_operand_address (file, addr) if (GET_CODE (addr) == LO_SUM) { - output_addr_const (file, XEXP (addr, 1)); + const char *reloc16, *reloclo; + rtx op1 = XEXP (addr, 1); + + if (GET_CODE (op1) == CONST && GET_CODE (XEXP (op1, 0)) == UNSPEC) + { + op1 = XEXP (op1, 0); + switch (XINT (op1, 1)) + { + case UNSPEC_DTPREL: + reloc16 = NULL; + reloclo = (alpha_tls_size == 16 ? "dtprel" : "dtprello"); + break; + case UNSPEC_TPREL: + reloc16 = NULL; + reloclo = (alpha_tls_size == 16 ? "tprel" : "tprello"); + break; + default: + output_operand_lossage ("unknown relocation unspec"); + return; + } + + output_addr_const (file, XVECEXP (op1, 0, 0)); + } + else + { + reloc16 = "gprel"; + reloclo = "gprellow"; + output_addr_const (file, op1); + } + if (offset) { fputc ('+', file); @@ -5502,7 +5963,7 @@ print_operand_address (file, addr) abort (); fprintf (file, "($%d)\t\t!%s", basereg, - (basereg == 29 ? "gprel" : "gprellow")); + (basereg == 29 ? reloc16 : reloclo)); return; } @@ -5513,6 +5974,24 @@ print_operand_address (file, addr) basereg = subreg_regno (addr); else if (GET_CODE (addr) == CONST_INT) offset = INTVAL (addr); + +#if TARGET_ABI_OPEN_VMS + else if (GET_CODE (addr) == SYMBOL_REF) + { + fprintf (file, "%s", XSTR (addr, 0)); + return; + } + else if (GET_CODE (addr) == CONST + && GET_CODE (XEXP (addr, 0)) == PLUS + && GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF) + { + fprintf (file, "%s+%d", + XSTR (XEXP (XEXP (addr, 0), 0), 0), + INTVAL (XEXP (XEXP (addr, 0), 1))); + return; + } +#endif + else abort (); @@ -5577,7 +6056,7 @@ alpha_initialize_trampoline (tramp, fnaddr, cxt, fnofs, cxtofs, jmpofs) #ifdef TRANSFER_FROM_TRAMPOLINE emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__enable_execute_stack"), - 0, VOIDmode, 1, addr, Pmode); + 0, VOIDmode, 1, tramp, Pmode); #endif if (jmpofs >= 0) @@ -5723,7 +6202,7 @@ alpha_build_va_list () if (TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK) return ptr_type_node; - record = make_lang_type (RECORD_TYPE); + record = (*lang_hooks.types.make_type) (RECORD_TYPE); type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record); TREE_CHAIN (record) = type_decl; TYPE_NAME (record) = type_decl; @@ -5746,8 +6225,7 @@ alpha_build_va_list () } void -alpha_va_start (stdarg_p, valist, nextarg) - int stdarg_p; +alpha_va_start (valist, nextarg) tree valist; rtx nextarg ATTRIBUTE_UNUSED; { @@ -5758,7 +6236,7 @@ alpha_va_start (stdarg_p, valist, nextarg) return; if (TARGET_ABI_UNICOSMK) - std_expand_builtin_va_start (stdarg_p, valist, nextarg); + std_expand_builtin_va_start (valist, nextarg); /* For Unix, SETUP_INCOMING_VARARGS moves the starting address base up by 48, storing fp arg registers in the first 48 bytes, and the @@ -5767,12 +6245,15 @@ alpha_va_start (stdarg_p, valist, nextarg) If no integer registers need be stored, then we must subtract 48 in order to account for the integer arg registers which are counted - in argsize above, but which are not actually stored on the stack. */ + in argsize above, but which are not actually stored on the stack. + Must further be careful here about structures straddling the last + integer argument register; that futzes with pretend_args_size, + which changes the meaning of AP. */ - if (NUM_ARGS <= 5 + stdarg_p) + if (NUM_ARGS <= 6) offset = TARGET_ABI_OPEN_VMS ? UNITS_PER_WORD : 6 * UNITS_PER_WORD; else - offset = -6 * UNITS_PER_WORD; + offset = -6 * UNITS_PER_WORD + current_function_pretend_args_size; if (TARGET_ABI_OPEN_VMS) { @@ -5897,6 +6378,310 @@ alpha_va_arg (valist, type) return addr; } +/* Builtins. */ + +enum alpha_builtin +{ + ALPHA_BUILTIN_CMPBGE, + ALPHA_BUILTIN_EXTBL, + ALPHA_BUILTIN_EXTWL, + ALPHA_BUILTIN_EXTLL, + ALPHA_BUILTIN_EXTQL, + ALPHA_BUILTIN_EXTWH, + ALPHA_BUILTIN_EXTLH, + ALPHA_BUILTIN_EXTQH, + ALPHA_BUILTIN_INSBL, + ALPHA_BUILTIN_INSWL, + ALPHA_BUILTIN_INSLL, + ALPHA_BUILTIN_INSQL, + ALPHA_BUILTIN_INSWH, + ALPHA_BUILTIN_INSLH, + ALPHA_BUILTIN_INSQH, + ALPHA_BUILTIN_MSKBL, + ALPHA_BUILTIN_MSKWL, + ALPHA_BUILTIN_MSKLL, + ALPHA_BUILTIN_MSKQL, + ALPHA_BUILTIN_MSKWH, + ALPHA_BUILTIN_MSKLH, + ALPHA_BUILTIN_MSKQH, + ALPHA_BUILTIN_UMULH, + ALPHA_BUILTIN_ZAP, + ALPHA_BUILTIN_ZAPNOT, + ALPHA_BUILTIN_AMASK, + ALPHA_BUILTIN_IMPLVER, + ALPHA_BUILTIN_RPCC, + ALPHA_BUILTIN_THREAD_POINTER, + ALPHA_BUILTIN_SET_THREAD_POINTER, + + /* TARGET_MAX */ + ALPHA_BUILTIN_MINUB8, + ALPHA_BUILTIN_MINSB8, + ALPHA_BUILTIN_MINUW4, + ALPHA_BUILTIN_MINSW4, + ALPHA_BUILTIN_MAXUB8, + ALPHA_BUILTIN_MAXSB8, + ALPHA_BUILTIN_MAXUW4, + ALPHA_BUILTIN_MAXSW4, + ALPHA_BUILTIN_PERR, + ALPHA_BUILTIN_PKLB, + ALPHA_BUILTIN_PKWB, + ALPHA_BUILTIN_UNPKBL, + ALPHA_BUILTIN_UNPKBW, + + /* TARGET_CIX */ + ALPHA_BUILTIN_CTTZ, + ALPHA_BUILTIN_CTLZ, + ALPHA_BUILTIN_CTPOP, + + ALPHA_BUILTIN_max +}; + +static unsigned int const code_for_builtin[ALPHA_BUILTIN_max] = { + CODE_FOR_builtin_cmpbge, + CODE_FOR_builtin_extbl, + CODE_FOR_builtin_extwl, + CODE_FOR_builtin_extll, + CODE_FOR_builtin_extql, + CODE_FOR_builtin_extwh, + CODE_FOR_builtin_extlh, + CODE_FOR_builtin_extqh, + CODE_FOR_builtin_insbl, + CODE_FOR_builtin_inswl, + CODE_FOR_builtin_insll, + CODE_FOR_builtin_insql, + CODE_FOR_builtin_inswh, + CODE_FOR_builtin_inslh, + CODE_FOR_builtin_insqh, + CODE_FOR_builtin_mskbl, + CODE_FOR_builtin_mskwl, + CODE_FOR_builtin_mskll, + CODE_FOR_builtin_mskql, + CODE_FOR_builtin_mskwh, + CODE_FOR_builtin_msklh, + CODE_FOR_builtin_mskqh, + CODE_FOR_umuldi3_highpart, + CODE_FOR_builtin_zap, + CODE_FOR_builtin_zapnot, + CODE_FOR_builtin_amask, + CODE_FOR_builtin_implver, + CODE_FOR_builtin_rpcc, + CODE_FOR_load_tp, + CODE_FOR_set_tp, + + /* TARGET_MAX */ + CODE_FOR_builtin_minub8, + CODE_FOR_builtin_minsb8, + CODE_FOR_builtin_minuw4, + CODE_FOR_builtin_minsw4, + CODE_FOR_builtin_maxub8, + CODE_FOR_builtin_maxsb8, + CODE_FOR_builtin_maxuw4, + CODE_FOR_builtin_maxsw4, + CODE_FOR_builtin_perr, + CODE_FOR_builtin_pklb, + CODE_FOR_builtin_pkwb, + CODE_FOR_builtin_unpkbl, + CODE_FOR_builtin_unpkbw, + + /* TARGET_CIX */ + CODE_FOR_builtin_cttz, + CODE_FOR_builtin_ctlz, + CODE_FOR_builtin_ctpop +}; + +struct alpha_builtin_def +{ + const char *name; + enum alpha_builtin code; + unsigned int target_mask; +}; + +static struct alpha_builtin_def const zero_arg_builtins[] = { + { "__builtin_alpha_implver", ALPHA_BUILTIN_IMPLVER, 0 }, + { "__builtin_alpha_rpcc", ALPHA_BUILTIN_RPCC, 0 } +}; + +static struct alpha_builtin_def const one_arg_builtins[] = { + { "__builtin_alpha_amask", ALPHA_BUILTIN_AMASK, 0 }, + { "__builtin_alpha_pklb", ALPHA_BUILTIN_PKLB, MASK_MAX }, + { "__builtin_alpha_pkwb", ALPHA_BUILTIN_PKWB, MASK_MAX }, + { "__builtin_alpha_unpkbl", ALPHA_BUILTIN_UNPKBL, MASK_MAX }, + { "__builtin_alpha_unpkbw", ALPHA_BUILTIN_UNPKBW, MASK_MAX }, + { "__builtin_alpha_cttz", ALPHA_BUILTIN_CTTZ, MASK_CIX }, + { "__builtin_alpha_ctlz", ALPHA_BUILTIN_CTLZ, MASK_CIX }, + { "__builtin_alpha_ctpop", ALPHA_BUILTIN_CTPOP, MASK_CIX } +}; + +static struct alpha_builtin_def const two_arg_builtins[] = { + { "__builtin_alpha_cmpbge", ALPHA_BUILTIN_CMPBGE, 0 }, + { "__builtin_alpha_extbl", ALPHA_BUILTIN_EXTBL, 0 }, + { "__builtin_alpha_extwl", ALPHA_BUILTIN_EXTWL, 0 }, + { "__builtin_alpha_extll", ALPHA_BUILTIN_EXTLL, 0 }, + { "__builtin_alpha_extql", ALPHA_BUILTIN_EXTQL, 0 }, + { "__builtin_alpha_extwh", ALPHA_BUILTIN_EXTWH, 0 }, + { "__builtin_alpha_extlh", ALPHA_BUILTIN_EXTLH, 0 }, + { "__builtin_alpha_extqh", ALPHA_BUILTIN_EXTQH, 0 }, + { "__builtin_alpha_insbl", ALPHA_BUILTIN_INSBL, 0 }, + { "__builtin_alpha_inswl", ALPHA_BUILTIN_INSWL, 0 }, + { "__builtin_alpha_insll", ALPHA_BUILTIN_INSLL, 0 }, + { "__builtin_alpha_insql", ALPHA_BUILTIN_INSQL, 0 }, + { "__builtin_alpha_inswh", ALPHA_BUILTIN_INSWH, 0 }, + { "__builtin_alpha_inslh", ALPHA_BUILTIN_INSLH, 0 }, + { "__builtin_alpha_insqh", ALPHA_BUILTIN_INSQH, 0 }, + { "__builtin_alpha_mskbl", ALPHA_BUILTIN_MSKBL, 0 }, + { "__builtin_alpha_mskwl", ALPHA_BUILTIN_MSKWL, 0 }, + { "__builtin_alpha_mskll", ALPHA_BUILTIN_MSKLL, 0 }, + { "__builtin_alpha_mskql", ALPHA_BUILTIN_MSKQL, 0 }, + { "__builtin_alpha_mskwh", ALPHA_BUILTIN_MSKWH, 0 }, + { "__builtin_alpha_msklh", ALPHA_BUILTIN_MSKLH, 0 }, + { "__builtin_alpha_mskqh", ALPHA_BUILTIN_MSKQH, 0 }, + { "__builtin_alpha_umulh", ALPHA_BUILTIN_UMULH, 0 }, + { "__builtin_alpha_zap", ALPHA_BUILTIN_ZAP, 0 }, + { "__builtin_alpha_zapnot", ALPHA_BUILTIN_ZAPNOT, 0 }, + { "__builtin_alpha_minub8", ALPHA_BUILTIN_MINUB8, MASK_MAX }, + { "__builtin_alpha_minsb8", ALPHA_BUILTIN_MINSB8, MASK_MAX }, + { "__builtin_alpha_minuw4", ALPHA_BUILTIN_MINUW4, MASK_MAX }, + { "__builtin_alpha_minsw4", ALPHA_BUILTIN_MINSW4, MASK_MAX }, + { "__builtin_alpha_maxub8", ALPHA_BUILTIN_MAXUB8, MASK_MAX }, + { "__builtin_alpha_maxsb8", ALPHA_BUILTIN_MAXSB8, MASK_MAX }, + { "__builtin_alpha_maxuw4", ALPHA_BUILTIN_MAXUW4, MASK_MAX }, + { "__builtin_alpha_maxsw4", ALPHA_BUILTIN_MAXSW4, MASK_MAX }, + { "__builtin_alpha_perr", ALPHA_BUILTIN_PERR, MASK_MAX } +}; + +static void +alpha_init_builtins () +{ + const struct alpha_builtin_def *p; + tree ftype; + size_t i; + + ftype = build_function_type (long_integer_type_node, void_list_node); + + p = zero_arg_builtins; + for (i = 0; i < ARRAY_SIZE (zero_arg_builtins); ++i, ++p) + if ((target_flags & p->target_mask) == p->target_mask) + builtin_function (p->name, ftype, p->code, BUILT_IN_MD, + NULL, NULL_TREE); + + ftype = build_function_type_list (long_integer_type_node, + long_integer_type_node, NULL_TREE); + + p = one_arg_builtins; + for (i = 0; i < ARRAY_SIZE (one_arg_builtins); ++i, ++p) + if ((target_flags & p->target_mask) == p->target_mask) + builtin_function (p->name, ftype, p->code, BUILT_IN_MD, + NULL, NULL_TREE); + + ftype = build_function_type_list (long_integer_type_node, + long_integer_type_node, + long_integer_type_node, NULL_TREE); + + p = two_arg_builtins; + for (i = 0; i < ARRAY_SIZE (two_arg_builtins); ++i, ++p) + if ((target_flags & p->target_mask) == p->target_mask) + builtin_function (p->name, ftype, p->code, BUILT_IN_MD, + NULL, NULL_TREE); + + ftype = build_function_type (ptr_type_node, void_list_node); + builtin_function ("__builtin_thread_pointer", ftype, + ALPHA_BUILTIN_THREAD_POINTER, BUILT_IN_MD, + NULL, NULL_TREE); + + ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); + builtin_function ("__builtin_set_thread_pointer", ftype, + ALPHA_BUILTIN_SET_THREAD_POINTER, BUILT_IN_MD, + NULL, NULL_TREE); +} + +/* Expand an expression EXP that calls a built-in function, + with result going to TARGET if that's convenient + (and in mode MODE if that's convenient). + SUBTARGET may be used as the target for computing one of EXP's operands. + IGNORE is nonzero if the value is to be ignored. */ + +static rtx +alpha_expand_builtin (exp, target, subtarget, mode, ignore) + tree exp; + rtx target; + rtx subtarget ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; + int ignore ATTRIBUTE_UNUSED; +{ +#define MAX_ARGS 2 + + tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); + unsigned int fcode = DECL_FUNCTION_CODE (fndecl); + tree arglist = TREE_OPERAND (exp, 1); + enum insn_code icode; + rtx op[MAX_ARGS], pat; + int arity; + bool nonvoid; + + if (fcode >= ALPHA_BUILTIN_max) + internal_error ("bad builtin fcode"); + icode = code_for_builtin[fcode]; + if (icode == 0) + internal_error ("bad builtin fcode"); + + nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node; + + for (arglist = TREE_OPERAND (exp, 1), arity = 0; + arglist; + arglist = TREE_CHAIN (arglist), arity++) + { + const struct insn_operand_data *insn_op; + + tree arg = TREE_VALUE (arglist); + if (arg == error_mark_node) + return NULL_RTX; + if (arity > MAX_ARGS) + return NULL_RTX; + + insn_op = &insn_data[icode].operand[arity + nonvoid]; + + op[arity] = expand_expr (arg, NULL_RTX, insn_op->mode, 0); + + if (!(*insn_op->predicate) (op[arity], insn_op->mode)) + op[arity] = copy_to_mode_reg (insn_op->mode, op[arity]); + } + + if (nonvoid) + { + enum machine_mode tmode = insn_data[icode].operand[0].mode; + if (!target + || GET_MODE (target) != tmode + || !(*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + } + + switch (arity) + { + case 0: + pat = GEN_FCN (icode) (target); + break; + case 1: + if (nonvoid) + pat = GEN_FCN (icode) (target, op[0]); + else + pat = GEN_FCN (icode) (op[0]); + break; + case 2: + pat = GEN_FCN (icode) (target, op[0], op[1]); + break; + default: + abort (); + } + if (!pat) + return NULL_RTX; + emit_insn (pat); + + if (nonvoid) + return target; + else + return const0_rtx; +} + /* This page contains routines that are used to determine what the function prologue and epilogue code will do and write them out. */ @@ -5934,10 +6719,11 @@ alpha_sa_mask (imaskP, fmaskP) unsigned int i; /* Irritatingly, there are two kinds of thunks -- those created with - ASM_OUTPUT_MI_THUNK and those with DECL_THUNK_P that go through - the regular part of the compiler. In the ASM_OUTPUT_MI_THUNK case - we don't have valid register life info, but assemble_start_function - wants to output .frame and .mask directives. */ + TARGET_ASM_OUTPUT_MI_THUNK and those with DECL_THUNK_P that go + through the regular part of the compiler. In the + TARGET_ASM_OUTPUT_MI_THUNK case we don't have valid register life + info, but assemble_start_function wants to output .frame and + .mask directives. */ if (current_function_is_thunk && !no_new_pseudos) { *imaskP = 0; @@ -6012,7 +6798,7 @@ alpha_sa_size () alpha_procedure_type = (sa_size || get_frame_size() != 0 - || current_function_outgoing_args_size || current_function_varargs + || current_function_outgoing_args_size || current_function_stdarg || current_function_calls_alloca || frame_pointer_needed) ? PT_STACK : PT_REGISTER; @@ -6111,11 +6897,18 @@ const struct attribute_spec vms_attribute_table[] = #endif static int -find_lo_sum (px, data) +find_lo_sum_using_gp (px, data) rtx *px; void *data ATTRIBUTE_UNUSED; { - return GET_CODE (*px) == LO_SUM; + return GET_CODE (*px) == LO_SUM && XEXP (*px, 0) == pic_offset_table_rtx; +} + +int +alpha_find_lo_sum_using_gp (insn) + rtx insn; +{ + return for_each_rtx (&PATTERN (insn), find_lo_sum_using_gp, NULL) > 0; } static int @@ -6144,15 +6937,9 @@ alpha_does_function_need_gp () for (; insn; insn = NEXT_INSN (insn)) if (INSN_P (insn) && GET_CODE (PATTERN (insn)) != USE - && GET_CODE (PATTERN (insn)) != CLOBBER) - { - enum attr_type type = get_attr_type (insn); - if (type == TYPE_LDSYM || type == TYPE_JSR) - return 1; - if (TARGET_EXPLICIT_RELOCS - && for_each_rtx (&PATTERN (insn), find_lo_sum, NULL) > 0) - return 1; - } + && GET_CODE (PATTERN (insn)) != CLOBBER + && get_attr_usegp (insn)) + return 1; return 0; } @@ -6179,22 +6966,30 @@ alpha_write_verstamp (file) static rtx set_frame_related_p () { - rtx seq = gen_sequence (); + rtx seq = get_insns (); + rtx insn; + end_sequence (); - if (GET_CODE (seq) == SEQUENCE) + if (!seq) + return NULL_RTX; + + if (INSN_P (seq)) { - int i = XVECLEN (seq, 0); - while (--i >= 0) - RTX_FRAME_RELATED_P (XVECEXP (seq, 0, i)) = 1; - return emit_insn (seq); + insn = seq; + while (insn != NULL_RTX) + { + RTX_FRAME_RELATED_P (insn) = 1; + insn = NEXT_INSN (insn); + } + seq = emit_insn (seq); } else { seq = emit_insn (seq); RTX_FRAME_RELATED_P (seq) = 1; - return seq; } + return seq; } #define FRP(exp) (start_sequence (), exp, set_frame_related_p ()) @@ -6698,26 +7493,13 @@ alpha_start_function (file, fnname, decl) } #if TARGET_ABI_OPEN_VMS - /* Ifdef'ed cause readonly_section and link_section are only - available then. */ - readonly_section (); + /* Ifdef'ed cause link_section are only available then. */ + readonly_data_section (); fprintf (file, "\t.align 3\n"); assemble_name (file, fnname); fputs ("..na:\n", file); fputs ("\t.ascii \"", file); assemble_name (file, fnname); fputs ("\\0\"\n", file); - - link_section (); - fprintf (file, "\t.align 3\n"); - fputs ("\t.name ", file); - assemble_name (file, fnname); - fputs ("..na\n", file); - ASM_OUTPUT_LABEL (file, fnname); - fprintf (file, "\t.pdesc "); - assemble_name (file, fnname); - fprintf (file, "..en,%s\n", - alpha_procedure_type == PT_STACK ? "stack" - : alpha_procedure_type == PT_REGISTER ? "reg" : "null"); alpha_need_linkage (fnname, 1); text_section (); #endif @@ -7003,6 +7785,39 @@ alpha_expand_epilogue () } } } + +#if TARGET_ABI_OPEN_VMS +#include <splay-tree.h> + +/* Structure to collect function names for final output + in link section. */ + +enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN}; +enum reloc_kind {KIND_LINKAGE, KIND_CODEADDR}; + +struct alpha_funcs +{ + int num; + splay_tree links; +}; + +struct alpha_links +{ + int num; + rtx linkage; + enum links_kind lkind; + enum reloc_kind rkind; +}; + +static splay_tree alpha_funcs_tree; +static splay_tree alpha_links_tree; + +static int mark_alpha_links_node PARAMS ((splay_tree_node, void *)); +static void mark_alpha_links PARAMS ((void *)); +static int alpha_write_one_linkage PARAMS ((splay_tree_node, void *)); + +static int alpha_funcs_num; +#endif /* Output the rest of the textual info surrounding the epilogue. */ @@ -7010,7 +7825,7 @@ void alpha_end_function (file, fnname, decl) FILE *file; const char *fnname; - tree decl ATTRIBUTE_UNUSED; + tree decl; { /* End the function. */ if (!TARGET_ABI_UNICOSMK && !flag_inhibit_size_directive) @@ -7021,20 +7836,20 @@ alpha_end_function (file, fnname, decl) } inside_function = FALSE; - /* Show that we know this function if it is called again. +#if TARGET_ABI_OPEN_VMS + alpha_write_linkage (file, fnname, decl); +#endif + + /* Show that we know this function if it is called again. - Don't do this for global functions in object files destined for a - shared library because the function may be overridden by the application - or other libraries. Similarly, don't do this for weak functions. + Do this only for functions whose symbols bind locally. Don't do this for functions not defined in the .text section, as otherwise it's not unlikely that the destination is out of range for a direct branch. */ - if (!DECL_WEAK (current_function_decl) - && (!flag_pic || !TREE_PUBLIC (current_function_decl)) - && decl_in_text_section (current_function_decl)) - SYMBOL_REF_FLAG (XEXP (DECL_RTL (current_function_decl), 0)) = 1; + if ((*targetm.binds_local_p) (decl) && decl_in_text_section (decl)) + SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1; /* Output jump tables and the static subroutine information block. */ if (TARGET_ABI_UNICOSMK) @@ -7044,7 +7859,8 @@ alpha_end_function (file, fnname, decl) } } -/* Emit a tail call to FUNCTION after adjusting THIS by DELTA. +#if TARGET_ABI_OSF +/* Emit a tail call to FUNCTION after adjusting THIS by DELTA. In order to avoid the hordes of differences between generated code with and without TARGET_EXPLICIT_RELOCS, and to avoid duplicating @@ -7053,11 +7869,12 @@ alpha_end_function (file, fnname, decl) Not sure why this idea hasn't been explored before... */ -void -alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, function) +static void +alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, vcall_offset, function) FILE *file; tree thunk_fndecl ATTRIBUTE_UNUSED; HOST_WIDE_INT delta; + HOST_WIDE_INT vcall_offset; tree function; { HOST_WIDE_INT hi, lo; @@ -7092,6 +7909,37 @@ alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, function) emit_insn (gen_adddi3 (this, this, tmp)); } + /* Add a delta stored in the vtable at VCALL_OFFSET. */ + if (vcall_offset) + { + rtx tmp, tmp2; + + tmp = gen_rtx_REG (Pmode, 0); + emit_move_insn (tmp, gen_rtx_MEM (Pmode, this)); + + lo = ((vcall_offset & 0xffff) ^ 0x8000) - 0x8000; + hi = (((vcall_offset - lo) & 0xffffffff) ^ 0x80000000) - 0x80000000; + if (hi + lo == vcall_offset) + { + if (hi) + emit_insn (gen_adddi3 (tmp, tmp, GEN_INT (hi))); + } + else + { + tmp2 = alpha_emit_set_long_const (gen_rtx_REG (Pmode, 1), + vcall_offset, -(vcall_offset < 0)); + emit_insn (gen_adddi3 (tmp, tmp, tmp2)); + lo = 0; + } + if (lo) + tmp2 = gen_rtx_PLUS (Pmode, tmp, GEN_INT (lo)); + else + tmp2 = tmp; + emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp2)); + + emit_insn (gen_adddi3 (this, this, tmp)); + } + /* Generate a tail call to the target function. */ if (! TREE_USED (function)) { @@ -7113,6 +7961,7 @@ alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, function) final (insn, file, 1, 0); final_end_function (); } +#endif /* TARGET_ABI_OSF */ /* Debugging support. */ @@ -7575,6 +8424,7 @@ alphaev4_insn_pipe (insn) case TYPE_MISC: case TYPE_IBR: case TYPE_JSR: + case TYPE_CALLPAL: case TYPE_FCPYS: case TYPE_FCMOV: case TYPE_FADD: @@ -7617,6 +8467,7 @@ alphaev5_insn_pipe (insn) case TYPE_IBR: case TYPE_JSR: + case TYPE_CALLPAL: return EV5_E1; case TYPE_FCPYS: @@ -8077,82 +8928,25 @@ alpha_reorg (insns) } } -/* Check a floating-point value for validity for a particular machine mode. */ - -static const char * const float_strings[] = -{ - /* These are for FLOAT_VAX. */ - "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */ - "-1.70141173319264430e+38", - "2.93873587705571877e-39", /* 2^-128 */ - "-2.93873587705571877e-39", - /* These are for the default broken IEEE mode, which traps - on infinity or denormal numbers. */ - "3.402823466385288598117e+38", /* 2^128 (1 - 2^-24) */ - "-3.402823466385288598117e+38", - "1.1754943508222875079687e-38", /* 2^-126 */ - "-1.1754943508222875079687e-38", -}; +#ifdef OBJECT_FORMAT_ELF -static REAL_VALUE_TYPE float_values[8]; -static int inited_float_values = 0; +/* Switch to the section to which we should output X. The only thing + special we do here is to honor small data. */ -int -check_float_value (mode, d, overflow) +static void +alpha_elf_select_rtx_section (mode, x, align) enum machine_mode mode; - REAL_VALUE_TYPE *d; - int overflow ATTRIBUTE_UNUSED; + rtx x; + unsigned HOST_WIDE_INT align; { - - if (TARGET_IEEE || TARGET_IEEE_CONFORMANT || TARGET_IEEE_WITH_INEXACT) - return 0; - - if (inited_float_values == 0) - { - int i; - for (i = 0; i < 8; i++) - float_values[i] = REAL_VALUE_ATOF (float_strings[i], DFmode); - - inited_float_values = 1; - } - - if (mode == SFmode) - { - REAL_VALUE_TYPE r; - REAL_VALUE_TYPE *fvptr; - - if (TARGET_FLOAT_VAX) - fvptr = &float_values[0]; - else - fvptr = &float_values[4]; - - memcpy (&r, d, sizeof (REAL_VALUE_TYPE)); - if (REAL_VALUES_LESS (fvptr[0], r)) - { - memcpy (d, &fvptr[0], sizeof (REAL_VALUE_TYPE)); - return 1; - } - else if (REAL_VALUES_LESS (r, fvptr[1])) - { - memcpy (d, &fvptr[1], sizeof (REAL_VALUE_TYPE)); - return 1; - } - else if (REAL_VALUES_LESS (dconst0, r) - && REAL_VALUES_LESS (r, fvptr[2])) - { - memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE)); - return 1; - } - else if (REAL_VALUES_LESS (r, dconst0) - && REAL_VALUES_LESS (fvptr[3], r)) - { - memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE)); - return 1; - } - } - - return 0; + if (TARGET_SMALL_DATA && GET_MODE_SIZE (mode) <= g_switch_value) + /* ??? Consider using mergable sdata sections. */ + sdata_section (); + else + default_elf_select_rtx_section (mode, x, align); } + +#endif /* OBJECT_FORMAT_ELF */ #if TARGET_ABI_OPEN_VMS @@ -8189,25 +8983,6 @@ alpha_arg_info_reg_val (cum) return GEN_INT (regval); } -#include <splay-tree.h> - -/* Structure to collect function names for final output - in link section. */ - -enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN}; - -struct alpha_links -{ - rtx linkage; - enum links_kind kind; -}; - -static splay_tree alpha_links; - -static int mark_alpha_links_node PARAMS ((splay_tree_node, void *)); -static void mark_alpha_links PARAMS ((void *)); -static int alpha_write_one_linkage PARAMS ((splay_tree_node, void *)); - /* Protect alpha_links from garbage collection. */ static int @@ -8241,46 +9016,67 @@ alpha_need_linkage (name, is_local) { splay_tree_node node; struct alpha_links *al; + struct alpha_funcs *cfaf; if (name[0] == '*') name++; - if (alpha_links) + if (is_local) + { + alpha_funcs_tree = splay_tree_new + ((splay_tree_compare_fn) splay_tree_compare_pointers, + (splay_tree_delete_key_fn) free, + (splay_tree_delete_key_fn) free); + + cfaf = (struct alpha_funcs *) xmalloc (sizeof (struct alpha_funcs)); + + cfaf->links = 0; + cfaf->num = ++alpha_funcs_num; + + splay_tree_insert (alpha_funcs_tree, + (splay_tree_key) current_function_decl, + (splay_tree_value) cfaf); + + } + + if (alpha_links_tree) { /* Is this name already defined? */ - node = splay_tree_lookup (alpha_links, (splay_tree_key) name); + node = splay_tree_lookup (alpha_links_tree, (splay_tree_key) name); if (node) { al = (struct alpha_links *) node->value; if (is_local) { /* Defined here but external assumed. */ - if (al->kind == KIND_EXTERN) - al->kind = KIND_LOCAL; + if (al->lkind == KIND_EXTERN) + al->lkind = KIND_LOCAL; } else { /* Used here but unused assumed. */ - if (al->kind == KIND_UNUSED) - al->kind = KIND_LOCAL; + if (al->lkind == KIND_UNUSED) + al->lkind = KIND_LOCAL; } return al->linkage; } } else { - alpha_links = splay_tree_new ((splay_tree_compare_fn) strcmp, - (splay_tree_delete_key_fn) free, - (splay_tree_delete_key_fn) free); - ggc_add_root (&alpha_links, 1, 1, mark_alpha_links); + alpha_links_tree = splay_tree_new + ((splay_tree_compare_fn) strcmp, + (splay_tree_delete_key_fn) free, + (splay_tree_delete_key_fn) free); + + ggc_add_root (&alpha_links_tree, 1, 1, mark_alpha_links); } al = (struct alpha_links *) xmalloc (sizeof (struct alpha_links)); name = xstrdup (name); /* Assume external if no definition. */ - al->kind = (is_local ? KIND_UNUSED : KIND_EXTERN); + al->lkind = (is_local ? KIND_UNUSED : KIND_EXTERN); /* Ensure we have an IDENTIFIER so assemble_name can mark it used. */ get_identifier (name); @@ -8296,50 +9092,165 @@ alpha_need_linkage (name, is_local) ggc_alloc_string (linksym, name_len + 5)); } - splay_tree_insert (alpha_links, (splay_tree_key) name, + splay_tree_insert (alpha_links_tree, (splay_tree_key) name, (splay_tree_value) al); return al->linkage; } +rtx +alpha_use_linkage (linkage, cfundecl, lflag, rflag) + rtx linkage; + tree cfundecl; + int lflag; + int rflag; +{ + splay_tree_node cfunnode; + struct alpha_funcs *cfaf; + struct alpha_links *al; + const char *name = XSTR (linkage, 0); + + cfaf = (struct alpha_funcs *) 0; + al = (struct alpha_links *) 0; + + cfunnode = splay_tree_lookup (alpha_funcs_tree, (splay_tree_key) cfundecl); + cfaf = (struct alpha_funcs *) cfunnode->value; + + if (cfaf->links) + { + splay_tree_node lnode; + + /* Is this name already defined? */ + + lnode = splay_tree_lookup (cfaf->links, (splay_tree_key) name); + if (lnode) + al = (struct alpha_links *) lnode->value; + } + else + { + cfaf->links = splay_tree_new + ((splay_tree_compare_fn) strcmp, + (splay_tree_delete_key_fn) free, + (splay_tree_delete_key_fn) free); + ggc_add_root (&cfaf->links, 1, 1, mark_alpha_links); + } + + if (!al) + { + size_t name_len; + size_t buflen; + char buf [512]; + char *linksym; + splay_tree_node node = 0; + struct alpha_links *anl; + + if (name[0] == '*') + name++; + + name_len = strlen (name); + + al = (struct alpha_links *) xmalloc (sizeof (struct alpha_links)); + al->num = cfaf->num; + + node = splay_tree_lookup (alpha_links_tree, (splay_tree_key) name); + if (node) + { + anl = (struct alpha_links *) node->value; + al->lkind = anl->lkind; + } + + sprintf (buf, "$%d..%s..lk", cfaf->num, name); + buflen = strlen (buf); + linksym = alloca (buflen + 1); + memcpy (linksym, buf, buflen + 1); + + al->linkage = gen_rtx_SYMBOL_REF + (Pmode, ggc_alloc_string (linksym, buflen + 1)); + + splay_tree_insert (cfaf->links, (splay_tree_key) name, + (splay_tree_value) al); + } + + if (rflag) + al->rkind = KIND_CODEADDR; + else + al->rkind = KIND_LINKAGE; + + if (lflag) + return gen_rtx_MEM (Pmode, plus_constant (al->linkage, 8)); + else + return al->linkage; +} + static int alpha_write_one_linkage (node, data) splay_tree_node node; void *data; { const char *const name = (const char *) node->key; - struct alpha_links *links = (struct alpha_links *) node->value; + struct alpha_links *link = (struct alpha_links *) node->value; FILE *stream = (FILE *) data; - if (links->kind == KIND_UNUSED - || ! TREE_SYMBOL_REFERENCED (get_identifier (name))) - return 0; - - fprintf (stream, "$%s..lk:\n", name); - if (links->kind == KIND_LOCAL) + fprintf (stream, "$%d..%s..lk:\n", link->num, name); + if (link->rkind == KIND_CODEADDR) { - /* Local and used, build linkage pair. */ - fprintf (stream, "\t.quad %s..en\n", name); - fprintf (stream, "\t.quad %s\n", name); + if (link->lkind == KIND_LOCAL) + { + /* Local and used */ + fprintf (stream, "\t.quad %s..en\n", name); + } + else + { + /* External and used, request code address. */ + fprintf (stream, "\t.code_address %s\n", name); + } } else { - /* External and used, request linkage pair. */ - fprintf (stream, "\t.linkage %s\n", name); + if (link->lkind == KIND_LOCAL) + { + /* Local and used, build linkage pair. */ + fprintf (stream, "\t.quad %s..en\n", name); + fprintf (stream, "\t.quad %s\n", name); + } + else + { + /* External and used, request linkage pair. */ + fprintf (stream, "\t.linkage %s\n", name); + } } return 0; } -void -alpha_write_linkage (stream) - FILE *stream; +static void +alpha_write_linkage (stream, funname, fundecl) + FILE *stream; + const char *funname; + tree fundecl; { - if (alpha_links) + splay_tree_node node; + struct alpha_funcs *func; + + link_section (); + fprintf (stream, "\t.align 3\n"); + node = splay_tree_lookup (alpha_funcs_tree, (splay_tree_key) fundecl); + func = (struct alpha_funcs *) node->value; + + fputs ("\t.name ", stream); + assemble_name (stream, funname); + fputs ("..na\n", stream); + ASM_OUTPUT_LABEL (stream, funname); + fprintf (stream, "\t.pdesc "); + assemble_name (stream, funname); + fprintf (stream, "..en,%s\n", + alpha_procedure_type == PT_STACK ? "stack" + : alpha_procedure_type == PT_REGISTER ? "reg" : "null"); + + if (func->links) { - readonly_section (); - fprintf (stream, "\t.align 3\n"); - splay_tree_foreach (alpha_links, alpha_write_one_linkage, stream); + splay_tree_foreach (func->links, alpha_write_one_linkage, stream); + /* splay_tree_delete (func->links); */ } } @@ -8432,6 +9343,16 @@ alpha_need_linkage (name, is_local) return NULL_RTX; } +rtx +alpha_use_linkage (linkage, cfundecl, lflag, rflag) + rtx linkage ATTRIBUTE_UNUSED; + tree cfundecl ATTRIBUTE_UNUSED; + int lflag ATTRIBUTE_UNUSED; + int rflag ATTRIBUTE_UNUSED; +{ + return NULL_RTX; +} + #endif /* TARGET_ABI_OPEN_VMS */ #if TARGET_ABI_UNICOSMK @@ -8495,9 +9416,8 @@ unicosmk_output_module_name (file) prefix the module name with a '$' if necessary. */ if (!ISALPHA (*name)) - fprintf (file, "$%s", name); - else - fputs (name, file); + putc ('$', file); + output_clean_symbol_name (file, name); } /* Output text that to appear at the beginning of an assembler file. */ @@ -8636,7 +9556,7 @@ unicosmk_section_type_flags (decl, name, reloc) /* Generate a section name for decl and associate it with the declaration. */ -void +static void unicosmk_unique_section (decl, reloc) tree decl; int reloc ATTRIBUTE_UNUSED; @@ -8648,7 +9568,7 @@ unicosmk_unique_section (decl, reloc) abort (); name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); - STRIP_NAME_ENCODING (name, name); + name = alpha_strip_name_encoding (name); len = strlen (name); if (TREE_CODE (decl) == FUNCTION_DECL) @@ -8716,7 +9636,7 @@ unicosmk_insert_attributes (decl, attr_ptr) { if (DECL_P (decl) && (TREE_PUBLIC (decl) || TREE_CODE (decl) == FUNCTION_DECL)) - UNIQUE_SECTION (decl, 0); + unicosmk_unique_section (decl, 0); } /* Output an alignment directive. We have to use the macro 'gcc@code@align' @@ -8879,8 +9799,7 @@ unicosmk_ssib_name () x = XEXP (x, 0); if (GET_CODE (x) != SYMBOL_REF) abort (); - fnname = XSTR (x, 0); - STRIP_NAME_ENCODING (fnname, fnname); + fnname = alpha_strip_name_encoding (XSTR (x, 0)); len = strlen (fnname); if (len + SSIB_PREFIX_LEN > 255) @@ -9055,7 +9974,7 @@ unicosmk_output_externs (file) /* We have to strip the encoding and possibly remove user_label_prefix from the identifier in order to handle -fleading-underscore and explicit asm names correctly (cf. gcc.dg/asm-names-1.c). */ - STRIP_NAME_ENCODING (real_name, p->name); + real_name = alpha_strip_name_encoding (p->name); if (len && p->name[0] == '*' && !memcmp (real_name, user_label_prefix, len)) real_name += len; @@ -9080,7 +9999,7 @@ unicosmk_add_extern (name) struct unicosmk_extern_list *p; p = (struct unicosmk_extern_list *) - permalloc (sizeof (struct unicosmk_extern_list)); + xmalloc (sizeof (struct unicosmk_extern_list)); p->next = unicosmk_extern_head; p->name = name; unicosmk_extern_head = p; @@ -9162,7 +10081,7 @@ unicosmk_need_dex (x) --i; } - dex = (struct unicosmk_dex *) permalloc (sizeof (struct unicosmk_dex)); + dex = (struct unicosmk_dex *) xmalloc (sizeof (struct unicosmk_dex)); dex->name = name; dex->next = unicosmk_dex_list; unicosmk_dex_list = dex; @@ -9230,3 +10149,6 @@ unicosmk_need_dex (x) } #endif /* TARGET_ABI_UNICOSMK */ + +#include "gt-alpha.h" + diff --git a/contrib/gcc/config/i386/i386.md b/contrib/gcc/config/i386/i386.md index 36a0497..1fa2998 100644 --- a/contrib/gcc/config/i386/i386.md +++ b/contrib/gcc/config/i386/i386.md @@ -1,5 +1,6 @@ ;; GCC machine description for IA-32 and x86-64. -;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +;; 2001, 2002, 2003 ;; Free Software Foundation, Inc. ;; Mostly by William Schelter. ;; x86_64 support added by Jan Hubicka @@ -49,55 +50,77 @@ ;; 'k' Likewise, print the SImode name of the register. ;; 'h' Print the QImode name for a "high" register, either ah, bh, ch or dh. ;; 'y' Print "st(0)" instead of "st" as a register. -;; + ;; UNSPEC usage: -;; 0 This is a `scas' operation. The mode of the UNSPEC is always SImode. -;; operand 0 is the memory address to scan. -;; operand 1 is a register containing the value to scan for. The mode -;; of the scas opcode will be the same as the mode of this operand. -;; operand 2 is the known alignment of operand 0. -;; 1 This is a `sin' operation. The mode of the UNSPEC is MODE_FLOAT. -;; operand 0 is the argument for `sin'. -;; 2 This is a `cos' operation. The mode of the UNSPEC is MODE_FLOAT. -;; operand 0 is the argument for `cos'. -;; 3 This is part of a `stack probe' operation. The mode of the UNSPEC is -;; always SImode. operand 0 is the size of the stack allocation. -;; 4 This is the source of a fake SET of the frame pointer which is used to -;; prevent insns referencing it being scheduled across the initial -;; decrement of the stack pointer. -;; 5 This is a `bsf' operation. -;; 6 This is the @GOT offset of a PIC address. -;; 7 This is the @GOTOFF offset of a PIC address. -;; 8 This is a reference to a symbol's @PLT address. -;; 9 This is an `fnstsw' operation. -;; 10 This is a `sahf' operation. -;; 11 This is a `fstcw' operation -;; 12 This is behaviour of add when setting carry flag. -;; 13 This is a `eh_return' placeholder. - -;; For SSE/MMX support: -;; 30 This is `fix', guaranteed to be truncating. -;; 31 This is a `emms' operation. -;; 32 This is a `maskmov' operation. -;; 33 This is a `movmsk' operation. -;; 34 This is a `non-temporal' move. -;; 36 This is used to distinguish COMISS from UCOMISS. -;; 37 This is a `ldmxcsr' operation. -;; 38 This is a forced `movaps' instruction (rather than whatever movti does) -;; 39 This is a forced `movups' instruction (rather than whatever movti does) -;; 40 This is a `stmxcsr' operation. -;; 41 This is a `shuffle' operation. -;; 42 This is a `rcp' operation. -;; 43 This is a `rsqsrt' operation. -;; 44 This is a `sfence' operation. -;; 45 This is a noop to prevent excessive combiner cleverness. -;; 46 This is a `femms' operation. -;; 49 This is a 'pavgusb' operation. -;; 50 This is a `pfrcp' operation. -;; 51 This is a `pfrcpit1' operation. -;; 52 This is a `pfrcpit2' operation. -;; 53 This is a `pfrsqrt' operation. -;; 54 This is a `pfrsqrit1' operation. + +(define_constants + [; Relocation specifiers + (UNSPEC_GOT 0) + (UNSPEC_GOTOFF 1) + (UNSPEC_GOTPCREL 2) + (UNSPEC_GOTTPOFF 3) + (UNSPEC_TPOFF 4) + (UNSPEC_NTPOFF 5) + (UNSPEC_DTPOFF 6) + (UNSPEC_GOTNTPOFF 7) + (UNSPEC_INDNTPOFF 8) + + ; Prologue support + (UNSPEC_STACK_PROBE 10) + (UNSPEC_STACK_ALLOC 11) + (UNSPEC_SET_GOT 12) + (UNSPEC_SSE_PROLOGUE_SAVE 13) + + ; TLS support + (UNSPEC_TP 15) + (UNSPEC_TLS_GD 16) + (UNSPEC_TLS_LD_BASE 17) + + ; Other random patterns + (UNSPEC_SCAS 20) + (UNSPEC_SIN 21) + (UNSPEC_COS 22) + (UNSPEC_BSF 23) + (UNSPEC_FNSTSW 24) + (UNSPEC_SAHF 25) + (UNSPEC_FSTCW 26) + (UNSPEC_ADD_CARRY 27) + (UNSPEC_FLDCW 28) + + ; 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) + ]) + +(define_constants + [(UNSPECV_BLOCKAGE 0) + (UNSPECV_EH_RETURN 13) + (UNSPECV_EMMS 31) + (UNSPECV_LDMXCSR 37) + (UNSPECV_STMXCSR 40) + (UNSPECV_FEMMS 46) + (UNSPECV_CLFLUSH 57) + ]) ;; Insns whose names begin with "x86_" are emitted by gen_FOO calls ;; from i386.c. @@ -116,26 +139,44 @@ ;; A basic instruction type. Refinements due to arguments to be ;; provided in other attributes. (define_attr "type" - "other,multi,alu1,negnot,alu,icmp,test,imov,imovx,lea,incdec,ishift,imul,idiv,ibr,setcc,push,pop,call,callv,icmov,fmov,fop,fop1,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,str,cld,sse,mmx,fistp" + "other,multi, + alu,alu1,negnot,imov,imovx,lea, + incdec,ishift,ishift1,rotate,rotate1,imul,idiv, + icmp,test,ibr,setcc,icmov, + push,pop,call,callv, + str,cld, + fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp, + sselog,sseiadd,sseishft,sseimul, + sse,ssemov,sseadd,ssemul,ssecmp,ssecvt,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,unknownfp,SF,DF,XF,TI" +(define_attr "mode" + "unknown,none,QI,HI,SI,DI,unknownfp,SF,DF,XF,TI,V4SF,V2DF,V2SF" (const_string "unknown")) -;; Set for i387 operations. -(define_attr "i387" "" - (if_then_else (eq_attr "type" "fmov,fop,fop1,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp") - (const_int 1) - (const_int 0))) +;; 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") + (const_string "i387") + (eq_attr "type" "sselog,sseiadd,sseishft,sseimul, + sse,ssemov,sseadd,ssemul,ssecmp,ssecvt,ssediv") + (const_string "sse") + (eq_attr "type" "mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft") + (const_string "mmx") + (eq_attr "type" "other") + (const_string "unknown")] + (const_string "integer"))) ;; The (bounding maximum) length of an instruction immediate. (define_attr "length_immediate" "" - (cond [(eq_attr "type" "incdec,setcc,icmov,ibr,str,cld,lea,other,multi,idiv,sse,mmx") + (cond [(eq_attr "type" "incdec,setcc,icmov,str,cld,lea,other,multi,idiv") (const_int 0) - (eq_attr "i387" "1") + (eq_attr "unit" "i387,sse,mmx") (const_int 0) - (eq_attr "type" "alu1,negnot,alu,icmp,imovx,ishift,imul,push,pop") + (eq_attr "type" "alu,alu1,negnot,imovx,ishift,rotate,ishift1,rotate1, + imul,icmp,push,pop") (symbol_ref "ix86_attr_length_immediate_default(insn,1)") (eq_attr "type" "imov,test") (symbol_ref "ix86_attr_length_immediate_default(insn,0)") @@ -147,22 +188,20 @@ (if_then_else (match_operand 1 "constant_call_address_operand" "") (const_int 4) (const_int 0)) + ;; We don't know the size before shorten_branches. Expect + ;; the instruction to fit for better scheduling. (eq_attr "type" "ibr") - (if_then_else (and (ge (minus (match_dup 0) (pc)) - (const_int -128)) - (lt (minus (match_dup 0) (pc)) - (const_int 124))) - (const_int 1) - (const_int 4)) + (const_int 1) ] - (symbol_ref "/* Update immediate_length and other attributes! */ abort(),1"))) + (symbol_ref "/* Update immediate_length and other attributes! */ + abort(),1"))) ;; The (bounding maximum) length of an instruction address. (define_attr "length_address" "" (cond [(eq_attr "type" "str,cld,other,multi,fxch") (const_int 0) (and (eq_attr "type" "call") - (match_operand 1 "constant_call_address_operand" "")) + (match_operand 0 "constant_call_address_operand" "")) (const_int 0) (and (eq_attr "type" "callv") (match_operand 1 "constant_call_address_operand" "")) @@ -172,16 +211,25 @@ ;; Set when length prefix is used. (define_attr "prefix_data16" "" - (if_then_else (eq_attr "mode" "HI") + (if_then_else (ior (eq_attr "mode" "HI") + (and (eq_attr "unit" "sse") (eq_attr "mode" "V2DF"))) (const_int 1) (const_int 0))) ;; Set when string REP prefix is used. -(define_attr "prefix_rep" "" (const_int 0)) +(define_attr "prefix_rep" "" + (if_then_else (and (eq_attr "unit" "sse") (eq_attr "mode" "SF,DF")) + (const_int 1) + (const_int 0))) ;; Set when 0f opcode prefix is used. (define_attr "prefix_0f" "" - (if_then_else (eq_attr "type" "imovx,setcc,icmov,sse,mmx") + (if_then_else + (eq_attr "type" + "imovx,setcc,icmov, + sselog,sseiadd,sseishft,sseimul, + sse,ssemov,sseadd,ssemul,ssecmp,ssecvt,ssediv, + mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft") (const_int 1) (const_int 0))) @@ -189,7 +237,7 @@ (define_attr "modrm" "" (cond [(eq_attr "type" "str,cld") (const_int 0) - (eq_attr "i387" "1") + (eq_attr "unit" "i387") (const_int 0) (and (eq_attr "type" "incdec") (ior (match_operand:SI 1 "register_operand" "") @@ -205,6 +253,12 @@ (and (match_operand 0 "register_operand" "") (match_operand 1 "immediate_operand" ""))) (const_int 0) + (and (eq_attr "type" "call") + (match_operand 0 "constant_call_address_operand" "")) + (const_int 0) + (and (eq_attr "type" "callv") + (match_operand 1 "constant_call_address_operand" "")) + (const_int 0) ] (const_int 1))) @@ -214,11 +268,15 @@ (define_attr "length" "" (cond [(eq_attr "type" "other,multi,fistp") (const_int 16) - ] + (eq_attr "type" "fcmp") + (const_int 4) + (eq_attr "unit" "i387") + (plus (const_int 2) + (plus (attr "prefix_data16") + (attr "length_address")))] (plus (plus (attr "modrm") (plus (attr "prefix_0f") - (plus (attr "i387") - (const_int 1)))) + (const_int 1))) (plus (attr "prefix_rep") (plus (attr "prefix_data16") (plus (attr "length_immediate") @@ -243,7 +301,7 @@ (if_then_else (match_operand 0 "memory_operand" "") (const_string "both") (const_string "load")) - (eq_attr "type" "icmp,test") + (eq_attr "type" "icmp,test,ssecmp,mmxcmp,fcmp") (if_then_else (ior (match_operand 0 "memory_operand" "") (match_operand 1 "memory_operand" "")) (const_string "load") @@ -270,7 +328,12 @@ (const_string "store") (match_operand 1 "memory_operand" "") (const_string "load") - (and (eq_attr "type" "!icmp,test,alu1,negnot,fop1,fsgn,imov,imovx,fmov,fcmp,sse,mmx") + (and (eq_attr "type" + "!alu1,negnot, + imov,imovx,icmp,test, + fmov,fcmp,fsgn, + sse,ssemov,ssecmp,ssecvt, + mmx,mmxmov,mmxcmp,mmxcvt") (match_operand 2 "memory_operand" "")) (const_string "load") (and (eq_attr "type" "icmov") @@ -284,11 +347,11 @@ (define_attr "imm_disp" "false,true,unknown" (cond [(eq_attr "type" "other,multi") (const_string "unknown") - (and (eq_attr "type" "icmp,test,imov") + (and (eq_attr "type" "icmp,test,imov,alu1,ishift1,rotate1") (and (match_operand 0 "memory_displacement_operand" "") (match_operand 1 "immediate_operand" ""))) (const_string "true") - (and (eq_attr "type" "alu,ishift,imul,idiv") + (and (eq_attr "type" "alu,ishift,rotate,imul,idiv") (and (match_operand 0 "memory_displacement_operand" "") (match_operand 2 "immediate_operand" ""))) (const_string "true") @@ -305,710 +368,10 @@ [(set_attr "length" "128") (set_attr "type" "multi")]) -;; Pentium Scheduling -;; -;; The Pentium is an in-order core with two integer pipelines. - -;; True for insns that behave like prefixed insns on the Pentium. -(define_attr "pent_prefix" "false,true" - (if_then_else (ior (eq_attr "prefix_0f" "1") - (ior (eq_attr "prefix_data16" "1") - (eq_attr "prefix_rep" "1"))) - (const_string "true") - (const_string "false"))) - -;; Categorize how an instruction slots. - -;; The non-MMX Pentium slots an instruction with prefixes on U pipe only, -;; while MMX Pentium can slot it on either U or V. Model non-MMX Pentium -;; rules, because it results in noticeably better code on non-MMX Pentium -;; and doesn't hurt much on MMX. (Prefixed instructions are not very -;; common, so the scheduler usualy has a non-prefixed insn to pair). - -(define_attr "pent_pair" "uv,pu,pv,np" - (cond [(eq_attr "imm_disp" "true") - (const_string "np") - (ior (eq_attr "type" "alu1,alu,imov,icmp,test,lea,incdec") - (and (eq_attr "type" "pop,push") - (eq_attr "memory" "!both"))) - (if_then_else (eq_attr "pent_prefix" "true") - (const_string "pu") - (const_string "uv")) - (eq_attr "type" "ibr") - (const_string "pv") - (and (eq_attr "type" "ishift") - (match_operand 2 "const_int_operand" "")) - (const_string "pu") - (and (eq_attr "type" "call") - (match_operand 0 "constant_call_address_operand" "")) - (const_string "pv") - (and (eq_attr "type" "callv") - (match_operand 1 "constant_call_address_operand" "")) - (const_string "pv") - ] - (const_string "np"))) - -;; Rough readiness numbers. Fine tuning happens in i386.c. -;; -;; u describes pipe U -;; v describes pipe V -;; uv describes either pipe U or V for those that can issue to either -;; np describes not paring -;; fpu describes fpu -;; fpm describes fp insns of different types are not pipelined. -;; -;; ??? fxch isn't handled; not an issue until sched3 after reg-stack is real. - -(define_function_unit "pent_np" 1 0 - (and (eq_attr "cpu" "pentium") - (eq_attr "type" "imul")) - 11 11) - -(define_function_unit "pent_mul" 1 1 - (and (eq_attr "cpu" "pentium") - (eq_attr "type" "imul")) - 11 11) - -;; Rep movs takes minimally 12 cycles. -(define_function_unit "pent_np" 1 0 - (and (eq_attr "cpu" "pentium") - (eq_attr "type" "str")) - 12 12) - -; ??? IDIV for SI takes 46 cycles, for HI 30, for QI 22 -(define_function_unit "pent_np" 1 0 - (and (eq_attr "cpu" "pentium") - (eq_attr "type" "idiv")) - 46 46) - -; Fp reg-reg moves takes 1 cycle. Loads takes 1 cycle for SF/DF mode, -; 3 cycles for XFmode. Stores takes 2 cycles for SF/DF and 3 for XF. -; fldz and fld1 takes 2 cycles. Only reg-reg moves are pairable. -; The integer <-> fp conversion is not modeled correctly. Fild behaves -; like normal fp operation and fist takes 6 cycles. - -(define_function_unit "fpu" 1 0 - (and (eq_attr "cpu" "pentium") - (and (eq_attr "type" "fmov") - (and (eq_attr "memory" "load,store") - (eq_attr "mode" "XF")))) - 3 3) - -(define_function_unit "pent_np" 1 0 - (and (eq_attr "cpu" "pentium") - (and (eq_attr "type" "fmov") - (and (eq_attr "memory" "load,store") - (eq_attr "mode" "XF")))) - 3 3) - -(define_function_unit "fpu" 1 0 - (and (eq_attr "cpu" "pentium") - (and (eq_attr "type" "fmov") - (ior (match_operand 1 "immediate_operand" "") - (eq_attr "memory" "store")))) - 2 2) - -(define_function_unit "pent_np" 1 0 - (and (eq_attr "cpu" "pentium") - (and (eq_attr "type" "fmov") - (ior (match_operand 1 "immediate_operand" "") - (eq_attr "memory" "store")))) - 2 2) - -(define_function_unit "pent_np" 1 0 - (and (eq_attr "cpu" "pentium") - (eq_attr "type" "cld")) - 2 2) - -(define_function_unit "fpu" 1 0 - (and (eq_attr "cpu" "pentium") - (and (eq_attr "type" "fmov") - (eq_attr "memory" "none,load"))) - 1 1) - -; Read/Modify/Write instructions usually take 3 cycles. -(define_function_unit "pent_u" 1 0 - (and (eq_attr "cpu" "pentium") - (and (eq_attr "type" "alu,alu1,ishift") - (and (eq_attr "pent_pair" "pu") - (eq_attr "memory" "both")))) - 3 3) - -(define_function_unit "pent_uv" 2 0 - (and (eq_attr "cpu" "pentium") - (and (eq_attr "type" "alu,alu1,ishift") - (and (eq_attr "pent_pair" "!np") - (eq_attr "memory" "both")))) - 3 3) - -(define_function_unit "pent_np" 1 0 - (and (eq_attr "cpu" "pentium") - (and (eq_attr "type" "alu,alu1,negnot,ishift") - (and (eq_attr "pent_pair" "np") - (eq_attr "memory" "both")))) - 3 3) - -; Read/Modify or Modify/Write instructions usually take 2 cycles. -(define_function_unit "pent_u" 1 0 - (and (eq_attr "cpu" "pentium") - (and (eq_attr "type" "alu,ishift") - (and (eq_attr "pent_pair" "pu") - (eq_attr "memory" "load,store")))) - 2 2) - -(define_function_unit "pent_uv" 2 0 - (and (eq_attr "cpu" "pentium") - (and (eq_attr "type" "alu,ishift") - (and (eq_attr "pent_pair" "!np") - (eq_attr "memory" "load,store")))) - 2 2) - -(define_function_unit "pent_np" 1 0 - (and (eq_attr "cpu" "pentium") - (and (eq_attr "type" "alu,ishift") - (and (eq_attr "pent_pair" "np") - (eq_attr "memory" "load,store")))) - 2 2) - -; Insns w/o memory operands and move instructions usually take one cycle. -(define_function_unit "pent_u" 1 0 - (and (eq_attr "cpu" "pentium") - (eq_attr "pent_pair" "pu")) - 1 1) - -(define_function_unit "pent_v" 1 0 - (and (eq_attr "cpu" "pentium") - (eq_attr "pent_pair" "pv")) - 1 1) - -(define_function_unit "pent_uv" 2 0 - (and (eq_attr "cpu" "pentium") - (eq_attr "pent_pair" "!np")) - 1 1) - -(define_function_unit "pent_np" 1 0 - (and (eq_attr "cpu" "pentium") - (eq_attr "pent_pair" "np")) - 1 1) - -; Pairable insns only conflict with other non-pairable insns. -(define_function_unit "pent_np" 1 0 - (and (eq_attr "cpu" "pentium") - (and (eq_attr "type" "alu,alu1,ishift") - (and (eq_attr "pent_pair" "!np") - (eq_attr "memory" "both")))) - 3 3 - [(eq_attr "pent_pair" "np")]) - -(define_function_unit "pent_np" 1 0 - (and (eq_attr "cpu" "pentium") - (and (eq_attr "type" "alu,alu1,ishift") - (and (eq_attr "pent_pair" "!np") - (eq_attr "memory" "load,store")))) - 2 2 - [(eq_attr "pent_pair" "np")]) - -(define_function_unit "pent_np" 1 0 - (and (eq_attr "cpu" "pentium") - (eq_attr "pent_pair" "!np")) - 1 1 - [(eq_attr "pent_pair" "np")]) - -; Floating point instructions usually blocks cycle longer when combined with -; integer instructions, because of the inpaired fxch instruction. -(define_function_unit "pent_np" 1 0 - (and (eq_attr "cpu" "pentium") - (eq_attr "type" "fmov,fop,fop1,fsgn,fmul,fpspc,fcmov,fcmp,fistp")) - 2 2 - [(eq_attr "type" "!fmov,fop,fop1,fsgn,fmul,fpspc,fcmov,fcmp,fistp")]) - -(define_function_unit "fpu" 1 0 - (and (eq_attr "cpu" "pentium") - (eq_attr "type" "fcmp,fxch,fsgn")) - 1 1) - -; Addition takes 3 cycles; assume other random cruft does as well. -; ??? Trivial fp operations such as fabs or fchs takes only one cycle. -(define_function_unit "fpu" 1 0 - (and (eq_attr "cpu" "pentium") - (eq_attr "type" "fop,fop1,fistp")) - 3 1) - -; Multiplication takes 3 cycles and is only half pipelined. -(define_function_unit "fpu" 1 0 - (and (eq_attr "cpu" "pentium") - (eq_attr "type" "fmul")) - 3 1) - -(define_function_unit "pent_mul" 1 1 - (and (eq_attr "cpu" "pentium") - (eq_attr "type" "fmul")) - 2 2) - -; ??? This is correct only for fdiv and sqrt -- sin/cos take 65-100 cycles. -; They can overlap with integer insns. Only the last two cycles can overlap -; with other fp insns. Only fsin/fcos can overlap with multiplies. -; Only last two cycles of fsin/fcos can overlap with other instructions. -(define_function_unit "fpu" 1 0 - (and (eq_attr "cpu" "pentium") - (eq_attr "type" "fdiv")) - 39 37) - -(define_function_unit "pent_mul" 1 1 - (and (eq_attr "cpu" "pentium") - (eq_attr "type" "fdiv")) - 39 39) - -(define_function_unit "fpu" 1 0 - (and (eq_attr "cpu" "pentium") - (eq_attr "type" "fpspc")) - 70 68) - -(define_function_unit "pent_mul" 1 1 - (and (eq_attr "cpu" "pentium") - (eq_attr "type" "fpspc")) - 70 70) - -;; Pentium Pro/PII Scheduling -;; -;; The PPro has an out-of-order core, but the instruction decoders are -;; naturally in-order and asymmetric. We get best performance by scheduling -;; for the decoders, for in doing so we give the oo execution unit the -;; most choices. - -;; Categorize how many uops an ia32 instruction evaluates to: -;; one -- an instruction with 1 uop can be decoded by any of the -;; three decoders. -;; few -- an instruction with 1 to 4 uops can be decoded only by -;; decoder 0. -;; many -- a complex instruction may take an unspecified number of -;; cycles to decode in decoder 0. - -(define_attr "ppro_uops" "one,few,many" - (cond [(eq_attr "type" "other,multi,call,callv,fpspc,str") - (const_string "many") - (eq_attr "type" "icmov,fcmov,str,cld") - (const_string "few") - (eq_attr "type" "imov") - (if_then_else (eq_attr "memory" "store,both") - (const_string "few") - (const_string "one")) - (eq_attr "memory" "!none") - (const_string "few") - ] - (const_string "one"))) - -;; Rough readiness numbers. Fine tuning happens in i386.c. -;; -;; p0 describes port 0. -;; p01 describes ports 0 and 1 as a pair; alu insns can issue to either. -;; p2 describes port 2 for loads. -;; p34 describes ports 3 and 4 for stores. -;; fpu describes the fpu accessed via port 0. -;; ??? It is less than clear if there are separate fadd and fmul units -;; that could operate in parallel. -;; -;; ??? fxch isn't handled; not an issue until sched3 after reg-stack is real. - -(define_function_unit "ppro_p0" 1 0 - (and (eq_attr "cpu" "pentiumpro") - (eq_attr "type" "ishift,lea,ibr,cld")) - 1 1) - -(define_function_unit "ppro_p0" 1 0 - (and (eq_attr "cpu" "pentiumpro") - (eq_attr "type" "imul")) - 4 1) - -;; ??? Does the divider lock out the pipe while it works, -;; or is there a disconnected unit? -(define_function_unit "ppro_p0" 1 0 - (and (eq_attr "cpu" "pentiumpro") - (eq_attr "type" "idiv")) - 17 17) - -(define_function_unit "ppro_p0" 1 0 - (and (eq_attr "cpu" "pentiumpro") - (eq_attr "type" "fop,fop1,fsgn,fistp")) - 3 1) - -(define_function_unit "ppro_p0" 1 0 - (and (eq_attr "cpu" "pentiumpro") - (eq_attr "type" "fcmov")) - 2 1) - -(define_function_unit "ppro_p0" 1 0 - (and (eq_attr "cpu" "pentiumpro") - (eq_attr "type" "fcmp")) - 1 1) - -(define_function_unit "ppro_p0" 1 0 - (and (eq_attr "cpu" "pentiumpro") - (eq_attr "type" "fmov")) - 1 1) - -(define_function_unit "ppro_p0" 1 0 - (and (eq_attr "cpu" "pentiumpro") - (eq_attr "type" "fmul")) - 5 1) - -(define_function_unit "ppro_p0" 1 0 - (and (eq_attr "cpu" "pentiumpro") - (eq_attr "type" "fdiv,fpspc")) - 56 1) - -(define_function_unit "ppro_p01" 2 0 - (and (eq_attr "cpu" "pentiumpro") - (eq_attr "type" "!imov,fmov")) - 1 1) - -(define_function_unit "ppro_p01" 2 0 - (and (and (eq_attr "cpu" "pentiumpro") - (eq_attr "type" "imov,fmov")) - (eq_attr "memory" "none")) - 1 1) - -(define_function_unit "ppro_p2" 1 0 - (and (eq_attr "cpu" "pentiumpro") - (ior (eq_attr "type" "pop") - (eq_attr "memory" "load,both"))) - 3 1) - -(define_function_unit "ppro_p34" 1 0 - (and (eq_attr "cpu" "pentiumpro") - (ior (eq_attr "type" "push") - (eq_attr "memory" "store,both"))) - 1 1) - -(define_function_unit "fpu" 1 0 - (and (eq_attr "cpu" "pentiumpro") - (eq_attr "type" "fop,fop1,fsgn,fmov,fcmp,fcmov,fistp")) - 1 1) - -(define_function_unit "fpu" 1 0 - (and (eq_attr "cpu" "pentiumpro") - (eq_attr "type" "fmul")) - 5 2) - -(define_function_unit "fpu" 1 0 - (and (eq_attr "cpu" "pentiumpro") - (eq_attr "type" "fdiv,fpspc")) - 56 56) - -;; imul uses the fpu. ??? does it have the same throughput as fmul? -(define_function_unit "fpu" 1 0 - (and (eq_attr "cpu" "pentiumpro") - (eq_attr "type" "imul")) - 4 1) - -;; AMD K6/K6-2 Scheduling -;; -;; The K6 has similar architecture to PPro. Important difference is, that -;; there are only two decoders and they seems to be much slower than execution -;; units. So we have to pay much more attention to proper decoding for -;; schedulers. We share most of scheduler code for PPro in i386.c -;; -;; The fp unit is not pipelined and do one operation per two cycles including -;; the FXCH. -;; -;; alu describes both ALU units (ALU-X and ALU-Y). -;; alux describes X alu unit -;; fpu describes FPU unit -;; load describes load unit. -;; branch describes branch unit. -;; store decsribes store unit. This unit is not modelled completely and only -;; used to model lea operation. Otherwise it lie outside of the critical -;; path. -;; -;; ??? fxch isn't handled; not an issue until sched3 after reg-stack is real. - -;; The decoder specification is in the PPro section above! - -;; Shift instructions and certain arithmetic are issued only to X pipe. -(define_function_unit "k6_alux" 1 0 - (and (eq_attr "cpu" "k6") - (eq_attr "type" "ishift,alu1,negnot,cld")) - 1 1) - -;; The QI mode arithmetic is issued to X pipe only. -(define_function_unit "k6_alux" 1 0 - (and (eq_attr "cpu" "k6") - (and (eq_attr "type" "alu,alu1,negnot,icmp,test,imovx,incdec") - (match_operand:QI 0 "general_operand" ""))) - 1 1) - -(define_function_unit "k6_alu" 2 0 - (and (eq_attr "cpu" "k6") - (eq_attr "type" "ishift,alu1,negnot,alu,icmp,test,imovx,incdec,setcc,lea")) - 1 1) - -(define_function_unit "k6_alu" 2 0 - (and (eq_attr "cpu" "k6") - (and (eq_attr "type" "imov") - (eq_attr "memory" "none"))) - 1 1) - -(define_function_unit "k6_branch" 1 0 - (and (eq_attr "cpu" "k6") - (eq_attr "type" "call,callv,ibr")) - 1 1) - -;; Load unit have two cycle latency, but we take care for it in adjust_cost -(define_function_unit "k6_load" 1 0 - (and (eq_attr "cpu" "k6") - (ior (eq_attr "type" "pop") - (eq_attr "memory" "load,both"))) - 1 1) - -(define_function_unit "k6_load" 1 0 - (and (eq_attr "cpu" "k6") - (and (eq_attr "type" "str") - (eq_attr "memory" "load,both"))) - 10 10) - -;; Lea have two instructions, so latency is probably 2 -(define_function_unit "k6_store" 1 0 - (and (eq_attr "cpu" "k6") - (eq_attr "type" "lea")) - 2 1) - -(define_function_unit "k6_store" 1 0 - (and (eq_attr "cpu" "k6") - (eq_attr "type" "str")) - 10 10) - -(define_function_unit "k6_store" 1 0 - (and (eq_attr "cpu" "k6") - (ior (eq_attr "type" "push") - (eq_attr "memory" "store,both"))) - 1 1) - -(define_function_unit "k6_fpu" 1 1 - (and (eq_attr "cpu" "k6") - (eq_attr "type" "fop,fop1,fmov,fcmp,fistp")) - 2 2) - -(define_function_unit "k6_fpu" 1 1 - (and (eq_attr "cpu" "k6") - (eq_attr "type" "fmul")) - 2 2) - -;; ??? Guess -(define_function_unit "k6_fpu" 1 1 - (and (eq_attr "cpu" "k6") - (eq_attr "type" "fdiv,fpspc")) - 56 56) - -(define_function_unit "k6_alu" 2 0 - (and (eq_attr "cpu" "k6") - (eq_attr "type" "imul")) - 2 2) - -(define_function_unit "k6_alux" 1 0 - (and (eq_attr "cpu" "k6") - (eq_attr "type" "imul")) - 2 2) - -;; ??? Guess -(define_function_unit "k6_alu" 2 0 - (and (eq_attr "cpu" "k6") - (eq_attr "type" "idiv")) - 17 17) - -(define_function_unit "k6_alux" 1 0 - (and (eq_attr "cpu" "k6") - (eq_attr "type" "idiv")) - 17 17) - -;; AMD Athlon Scheduling -;; -;; The Athlon does contain three pipelined FP units, three integer units and -;; three address generation units. -;; -;; The predecode logic is determining boundaries of instructions in the 64 -;; byte cache line. So the cache line straddling problem of K6 might be issue -;; here as well, but it is not noted in the documentation. -;; -;; Three DirectPath instructions decoders and only one VectorPath decoder -;; is available. They can decode three DirectPath instructions or one VectorPath -;; instruction per cycle. -;; Decoded macro instructions are then passed to 72 entry instruction control -;; unit, that passes -;; it to the specialized integer (18 entry) and fp (36 entry) schedulers. -;; -;; The load/store queue unit is not attached to the schedulers but -;; communicates with all the execution units separately instead. - -(define_attr "athlon_decode" "direct,vector" - (cond [(eq_attr "type" "call,imul,idiv,other,multi,fcmov,fpspc,str,pop,cld,fcmov") - (const_string "vector") - (and (eq_attr "type" "push") - (match_operand 1 "memory_operand" "")) - (const_string "vector") - (and (eq_attr "type" "fmov") - (and (eq_attr "memory" "load,store") - (eq_attr "mode" "XF"))) - (const_string "vector")] - (const_string "direct"))) - -(define_function_unit "athlon_vectordec" 1 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "athlon_decode" "vector")) - 1 1) - -(define_function_unit "athlon_directdec" 3 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "athlon_decode" "direct")) - 1 1) - -(define_function_unit "athlon_vectordec" 1 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "athlon_decode" "direct")) - 1 1 [(eq_attr "athlon_decode" "vector")]) - -(define_function_unit "athlon_ieu" 3 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "type" "alu1,negnot,alu,icmp,test,imov,imovx,lea,incdec,ishift,ibr,call,callv,icmov,cld,pop,setcc,push,pop")) - 1 1) - -(define_function_unit "athlon_ieu" 3 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "type" "str")) - 15 15) - -(define_function_unit "athlon_ieu" 3 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "type" "imul")) - 5 0) - -(define_function_unit "athlon_ieu" 3 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "type" "idiv")) - 42 0) - -(define_function_unit "athlon_muldiv" 1 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "type" "imul")) - 5 0) - -(define_function_unit "athlon_muldiv" 1 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "type" "idiv")) - 42 42) - -(define_attr "athlon_fpunits" "none,store,mul,add,muladd,any" - (cond [(eq_attr "type" "fop,fop1,fcmp,fistp") - (const_string "add") - (eq_attr "type" "fmul,fdiv,fpspc,fsgn,fcmov") - (const_string "mul") - (and (eq_attr "type" "fmov") (eq_attr "memory" "store,both")) - (const_string "store") - (and (eq_attr "type" "fmov") (eq_attr "memory" "load")) - (const_string "any") - (and (eq_attr "type" "fmov") - (ior (match_operand:SI 1 "register_operand" "") - (match_operand 1 "immediate_operand" ""))) - (const_string "store") - (eq_attr "type" "fmov") - (const_string "muladd")] - (const_string "none"))) - -;; We use latencies 1 for definitions. This is OK to model colisions -;; in execution units. The real latencies are modeled in the "fp" pipeline. - -;; fsin, fcos: 96-192 -;; fsincos: 107-211 -;; fsqrt: 19 for SFmode, 27 for DFmode, 35 for XFmode. -(define_function_unit "athlon_fp" 3 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "type" "fpspc")) - 100 1) - -;; 16 cycles for SFmode, 20 for DFmode and 24 for XFmode. -(define_function_unit "athlon_fp" 3 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "type" "fdiv")) - 24 1) - -(define_function_unit "athlon_fp" 3 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "type" "fop,fop1,fmul,fistp")) - 4 1) - -;; XFmode loads are slow. -;; XFmode store is slow too (8 cycles), but we don't need to model it, because -;; there are no dependent instructions. - -(define_function_unit "athlon_fp" 3 0 - (and (eq_attr "cpu" "athlon") - (and (eq_attr "type" "fmov") - (and (eq_attr "memory" "load") - (eq_attr "mode" "XF")))) - 10 1) - -(define_function_unit "athlon_fp" 3 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "type" "fmov,fsgn")) - 2 1) - -;; fcmp and ftst instructions -(define_function_unit "athlon_fp" 3 0 - (and (eq_attr "cpu" "athlon") - (and (eq_attr "type" "fcmp") - (eq_attr "athlon_decode" "direct"))) - 3 1) - -;; fcmpi instructions. -(define_function_unit "athlon_fp" 3 0 - (and (eq_attr "cpu" "athlon") - (and (eq_attr "type" "fcmp") - (eq_attr "athlon_decode" "vector"))) - 3 1) - -(define_function_unit "athlon_fp" 3 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "type" "fcmov")) - 7 1) - -(define_function_unit "athlon_fp_mul" 1 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "athlon_fpunits" "mul")) - 1 1) - -(define_function_unit "athlon_fp_add" 1 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "athlon_fpunits" "add")) - 1 1) - -(define_function_unit "athlon_fp_muladd" 2 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "athlon_fpunits" "muladd,mul,add")) - 1 1) - -(define_function_unit "athlon_fp_store" 1 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "athlon_fpunits" "store")) - 1 1) - -;; We don't need to model the Address Generation Unit, since we don't model -;; the re-order buffer yet and thus we never schedule more than three operations -;; at time. Later we may want to experiment with MD_SCHED macros modeling the -;; decoders independently on the functional units. - -;(define_function_unit "athlon_agu" 3 0 -; (and (eq_attr "cpu" "athlon") -; (and (eq_attr "memory" "!none") -; (eq_attr "athlon_fpunits" "none"))) -; 1 1) - -;; Model load unit to avoid too long sequences of loads. We don't need to -;; model store queue, since it is hardly going to be bottleneck. - -(define_function_unit "athlon_load" 2 0 - (and (eq_attr "cpu" "athlon") - (eq_attr "memory" "load,both")) - 1 1) - +(include "pentium.md") +(include "ppro.md") +(include "k6.md") +(include "athlon.md") ;; Compare instructions. @@ -1382,7 +745,8 @@ [(set (match_operand:HI 0 "register_operand" "=a") (unspec:HI [(compare:CCFP (match_operand 1 "register_operand" "f") - (match_operand 2 "const0_operand" "X"))] 9))] + (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])" @@ -1413,7 +777,8 @@ (unspec:HI [(compare:CCFP (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "nonimmediate_operand" "fm"))] 9))] + (match_operand:SF 2 "nonimmediate_operand" "fm"))] + UNSPEC_FNSTSW))] "TARGET_80387" "* return output_fp_compare (insn, operands, 2, 0);" [(set_attr "type" "fcmp") @@ -1434,7 +799,8 @@ (unspec:HI [(compare:CCFP (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "nonimmediate_operand" "fm"))] 9))] + (match_operand:DF 2 "nonimmediate_operand" "fm"))] + UNSPEC_FNSTSW))] "TARGET_80387" "* return output_fp_compare (insn, operands, 2, 0);" [(set_attr "type" "multi") @@ -1465,7 +831,8 @@ (unspec:HI [(compare:CCFP (match_operand:XF 1 "register_operand" "f") - (match_operand:XF 2 "register_operand" "f"))] 9))] + (match_operand:XF 2 "register_operand" "f"))] + UNSPEC_FNSTSW))] "!TARGET_64BIT && TARGET_80387" "* return output_fp_compare (insn, operands, 2, 0);" [(set_attr "type" "multi") @@ -1476,7 +843,8 @@ (unspec:HI [(compare:CCFP (match_operand:TF 1 "register_operand" "f") - (match_operand:TF 2 "register_operand" "f"))] 9))] + (match_operand:TF 2 "register_operand" "f"))] + UNSPEC_FNSTSW))] "TARGET_80387" "* return output_fp_compare (insn, operands, 2, 0);" [(set_attr "type" "multi") @@ -1499,7 +867,8 @@ (unspec:HI [(compare:CCFPU (match_operand 1 "register_operand" "f") - (match_operand 2 "register_operand" "f"))] 9))] + (match_operand 2 "register_operand" "f"))] + UNSPEC_FNSTSW))] "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1])) && GET_MODE (operands[1]) == GET_MODE (operands[2])" @@ -1547,12 +916,12 @@ (define_insn "x86_fnstsw_1" [(set (match_operand:HI 0 "register_operand" "=a") - (unspec:HI [(reg 18)] 9))] + (unspec:HI [(reg 18)] UNSPEC_FNSTSW))] "TARGET_80387" "fnstsw\t%0" [(set_attr "length" "2") (set_attr "mode" "SI") - (set_attr "i387" "1") + (set_attr "unit" "i387") (set_attr "ppro_uops" "few")]) ;; FP compares, step 3 @@ -1560,7 +929,7 @@ (define_insn "x86_sahf_1" [(set (reg:CC 17) - (unspec:CC [(match_operand:HI 0 "register_operand" "a")] 10))] + (unspec:CC [(match_operand:HI 0 "register_operand" "a")] UNSPEC_SAHF))] "!TARGET_64BIT" "sahf" [(set_attr "length" "1") @@ -1591,7 +960,7 @@ && SSE_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,sse") + [(set_attr "type" "fcmp,ssecmp") (set_attr "mode" "unknownfp") (set_attr "athlon_decode" "vector")]) @@ -1602,7 +971,7 @@ "SSE_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" "sse") + [(set_attr "type" "ssecmp") (set_attr "mode" "unknownfp") (set_attr "athlon_decode" "vector")]) @@ -1627,7 +996,7 @@ && 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" "fcmp,sse") + [(set_attr "type" "fcmp,ssecmp") (set_attr "mode" "unknownfp") (set_attr "athlon_decode" "vector")]) @@ -1638,7 +1007,7 @@ "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" "sse") + [(set_attr "type" "ssecmp") (set_attr "mode" "unknownfp") (set_attr "athlon_decode" "vector")]) @@ -1733,25 +1102,20 @@ (set_attr "mode" "SI") (set_attr "length_immediate" "1")]) -; The first alternative is used only to compute proper length of instruction. -; Reload's algorithm does not take into account the cost of spill instructions -; needed to free register in given class, so avoid it from choosing the first -; alternative when eax is not available. - (define_insn "*movsi_1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=*?a,r,*?a,m,!*y,!rm,!*y,!*Y,!rm,!*Y") - (match_operand:SI 1 "general_operand" "im,rinm,rinm,rin,rm,*y,*y,rm,*Y,*Y"))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m,!*y,!rm,!*y,!*Y,!*Y,!rm") + (match_operand:SI 1 "general_operand" "rinm,rin,rm,*y,*y,*Y,rm,*Y"))] "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" { switch (get_attr_type (insn)) { - case TYPE_SSE: - if (get_attr_mode (insn) == TImode) + case TYPE_SSEMOV: + if (get_attr_mode (insn) == MODE_TI) return "movdqa\t{%1, %0|%0, %1}"; return "movd\t{%1, %0|%0, %1}"; - case TYPE_MMX: - if (get_attr_mode (insn) == DImode) + case TYPE_MMXMOV: + if (get_attr_mode (insn) == MODE_DI) return "movq\t{%1, %0|%0, %1}"; return "movd\t{%1, %0|%0, %1}"; @@ -1759,46 +1123,44 @@ return "lea{l}\t{%1, %0|%0, %1}"; default: - if (flag_pic && SYMBOLIC_CONST (operands[1])) + 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" "4,5,6") - (const_string "mmx") - (eq_attr "alternative" "7,8,9") - (const_string "sse") + (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 "modrm" "0,*,0,*,*,*,*,*,*,*") - (set_attr "mode" "SI,SI,SI,SI,SI,SI,DI,TI,SI,SI")]) + (set_attr "mode" "SI,SI,SI,SI,DI,TI,SI,SI")]) ;; Stores and loads of ax to arbitary constant address. ;; We fake an second form of instruction to force reload to load address ;; into register when rax is not available (define_insn "*movabssi_1_rex64" - [(set (mem:SI (match_operand:DI 0 "x86_64_movabs_operand" "i,r,r")) - (match_operand:SI 1 "nonmemory_operand" "a,er,i"))] - "TARGET_64BIT" + [(set (mem:SI (match_operand:DI 0 "x86_64_movabs_operand" "i,r")) + (match_operand:SI 1 "nonmemory_operand" "a,er"))] + "TARGET_64BIT && ix86_check_movabs (insn, 0)" "@ movabs{l}\t{%1, %P0|%P0, %1} - mov{l}\t{%1, %a0|%a0, %1} - movabs{l}\t{%1, %a0|%a0, %1}" + mov{l}\t{%1, %a0|%a0, %1}" [(set_attr "type" "imov") - (set_attr "modrm" "0,*,*") - (set_attr "length_address" "8,0,0") - (set_attr "length_immediate" "0,*,*") + (set_attr "modrm" "0,*") + (set_attr "length_address" "8,0") + (set_attr "length_immediate" "0,*") (set_attr "memory" "store") (set_attr "mode" "SI")]) (define_insn "*movabssi_2_rex64" [(set (match_operand:SI 0 "register_operand" "=a,r") (mem:SI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))] - "TARGET_64BIT" + "TARGET_64BIT && ix86_check_movabs (insn, 1)" "@ movabs{l}\t{%P1, %0|%0, %P1} mov{l}\t{%a1, %0|%0, %a1}" @@ -1848,14 +1210,9 @@ [(set_attr "type" "push") (set_attr "mode" "QI")]) -; The first alternative is used only to compute proper length of instruction. -; Reload's algorithm does not take into account the cost of spill instructions -; needed to free register in given class, so avoid it from choosing the first -; alternative when eax is not available. - (define_insn "*movhi_1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=*?a,r,r,*?a,r,m") - (match_operand:HI 1 "general_operand" "i,r,rn,rm,rm,rn"))] + [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m") + (match_operand:HI 1 "general_operand" "r,rn,rm,rn"))] "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" { switch (get_attr_type (insn)) @@ -1872,59 +1229,57 @@ } } [(set (attr "type") - (cond [(and (eq_attr "alternative" "0,1") + (cond [(and (eq_attr "alternative" "0") (ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL") (const_int 0)) (eq (symbol_ref "TARGET_HIMODE_MATH") (const_int 0)))) (const_string "imov") - (and (eq_attr "alternative" "2,3,4") + (and (eq_attr "alternative" "1,2") (match_operand:HI 1 "aligned_operand" "")) (const_string "imov") (and (ne (symbol_ref "TARGET_MOVX") (const_int 0)) - (eq_attr "alternative" "0,1,3,4")) + (eq_attr "alternative" "0,2")) (const_string "imovx") ] (const_string "imov"))) (set (attr "mode") (cond [(eq_attr "type" "imovx") (const_string "SI") - (and (eq_attr "alternative" "2,3,4") + (and (eq_attr "alternative" "1,2") (match_operand:HI 1 "aligned_operand" "")) (const_string "SI") - (and (eq_attr "alternative" "0,1") + (and (eq_attr "alternative" "0") (ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL") (const_int 0)) (eq (symbol_ref "TARGET_HIMODE_MATH") (const_int 0)))) (const_string "SI") ] - (const_string "HI"))) - (set_attr "modrm" "0,*,*,0,*,*")]) + (const_string "HI")))]) ;; Stores and loads of ax to arbitary constant address. ;; We fake an second form of instruction to force reload to load address ;; into register when rax is not available (define_insn "*movabshi_1_rex64" - [(set (mem:HI (match_operand:DI 0 "x86_64_movabs_operand" "i,r,r")) - (match_operand:HI 1 "nonmemory_operand" "a,er,i"))] - "TARGET_64BIT" + [(set (mem:HI (match_operand:DI 0 "x86_64_movabs_operand" "i,r")) + (match_operand:HI 1 "nonmemory_operand" "a,er"))] + "TARGET_64BIT && ix86_check_movabs (insn, 0)" "@ movabs{w}\t{%1, %P0|%P0, %1} - mov{w}\t{%1, %a0|%a0, %1} - movabs{w}\t{%1, %a0|%a0, %1}" + mov{w}\t{%1, %a0|%a0, %1}" [(set_attr "type" "imov") - (set_attr "modrm" "0,*,*") - (set_attr "length_address" "8,0,0") - (set_attr "length_immediate" "0,*,*") + (set_attr "modrm" "0,*") + (set_attr "length_address" "8,0") + (set_attr "length_immediate" "0,*") (set_attr "memory" "store") (set_attr "mode" "HI")]) (define_insn "*movabshi_2_rex64" [(set (match_operand:HI 0 "register_operand" "=a,r") (mem:HI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))] - "TARGET_64BIT" + "TARGET_64BIT && ix86_check_movabs (insn, 1)" "@ movabs{w}\t{%P1, %0|%0, %P1} mov{w}\t{%a1, %0|%0, %a1}" @@ -2122,7 +1477,7 @@ (define_expand "movstrictqi" [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "")) (match_operand:QI 1 "general_operand" ""))] - "! TARGET_PARTIAL_REG_STALL" + "! TARGET_PARTIAL_REG_STALL || optimize_size" { /* Don't generate memory->memory moves, go through a register. */ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) @@ -2132,7 +1487,7 @@ (define_insn "*movstrictqi_1" [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) (match_operand:QI 1 "general_operand" "*qn,m"))] - "! TARGET_PARTIAL_REG_STALL + "(! TARGET_PARTIAL_REG_STALL || optimize_size) && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "mov{b}\t{%1, %0|%0, %1}" [(set_attr "type" "imov") @@ -2226,24 +1581,23 @@ ;; We fake an second form of instruction to force reload to load address ;; into register when rax is not available (define_insn "*movabsqi_1_rex64" - [(set (mem:QI (match_operand:DI 0 "x86_64_movabs_operand" "i,r,r")) - (match_operand:QI 1 "nonmemory_operand" "a,er,i"))] - "TARGET_64BIT" + [(set (mem:QI (match_operand:DI 0 "x86_64_movabs_operand" "i,r")) + (match_operand:QI 1 "nonmemory_operand" "a,er"))] + "TARGET_64BIT && ix86_check_movabs (insn, 0)" "@ movabs{b}\t{%1, %P0|%P0, %1} - mov{b}\t{%1, %a0|%a0, %1} - movabs{b}\t{%1, %a0|%a0, %1}" + mov{b}\t{%1, %a0|%a0, %1}" [(set_attr "type" "imov") - (set_attr "modrm" "0,*,*") - (set_attr "length_address" "8,0,0") - (set_attr "length_immediate" "0,*,*") + (set_attr "modrm" "0,*") + (set_attr "length_address" "8,0") + (set_attr "length_immediate" "0,*") (set_attr "memory" "store") (set_attr "mode" "QI")]) (define_insn "*movabsqi_2_rex64" [(set (match_operand:QI 0 "register_operand" "=a,r") (mem:QI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))] - "TARGET_64BIT" + "TARGET_64BIT && ix86_check_movabs (insn, 1)" "@ movabs{b}\t{%P1, %0|%0, %P1} mov{b}\t{%a1, %0|%0, %a1}" @@ -2484,7 +1838,7 @@ movq\t{%1, %0|%0, %1} movdqa\t{%1, %0|%0, %1} movq\t{%1, %0|%0, %1}" - [(set_attr "type" "*,*,mmx,mmx,sse,sse,sse") + [(set_attr "type" "*,*,mmx,mmx,ssemov,ssemov,ssemov") (set_attr "mode" "DI,DI,DI,DI,DI,TI,DI")]) (define_split @@ -2513,19 +1867,19 @@ { switch (get_attr_type (insn)) { - case TYPE_SSE: + case TYPE_SSEMOV: if (register_operand (operands[0], DImode) && register_operand (operands[1], DImode)) return "movdqa\t{%1, %0|%0, %1}"; /* FALLTHRU */ - case TYPE_MMX: + 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 && SYMBOLIC_CONST (operands[1])) + 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}"; @@ -2537,9 +1891,9 @@ } [(set (attr "type") (cond [(eq_attr "alternative" "5,6") - (const_string "mmx") - (eq_attr "alternative" "7,8") - (const_string "sse") + (const_string "mmxmov") + (eq_attr "alternative" "7,8,9") + (const_string "ssemov") (eq_attr "alternative" "4") (const_string "multi") (and (ne (symbol_ref "flag_pic") (const_int 0)) @@ -2557,7 +1911,7 @@ (define_insn "*movabsdi_1_rex64" [(set (mem:DI (match_operand:DI 0 "x86_64_movabs_operand" "i,r")) (match_operand:DI 1 "nonmemory_operand" "a,er"))] - "TARGET_64BIT" + "TARGET_64BIT && ix86_check_movabs (insn, 0)" "@ movabs{q}\t{%1, %P0|%P0, %1} mov{q}\t{%1, %a0|%a0, %1}" @@ -2571,7 +1925,7 @@ (define_insn "*movabsdi_2_rex64" [(set (match_operand:DI 0 "register_operand" "=a,r") (mem:DI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))] - "TARGET_64BIT" + "TARGET_64BIT && ix86_check_movabs (insn, 1)" "@ movabs{q}\t{%P1, %0|%0, %P1} mov{q}\t{%a1, %0|%0, %a1}" @@ -2711,21 +2065,21 @@ ;; %%% Kill this when call knows how to work this out. (define_split [(set (match_operand:SF 0 "push_operand" "") - (match_operand:SF 1 "register_operand" ""))] - "!TARGET_64BIT && ANY_FP_REGNO_P (REGNO (operands[1]))" + (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))]) (define_split [(set (match_operand:SF 0 "push_operand" "") - (match_operand:SF 1 "register_operand" ""))] - "TARGET_64BIT && ANY_FP_REGNO_P (REGNO (operands[1]))" + (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))]) (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,H,x,xm#rf,x#rf,rm,*y,*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"))] "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) && (reload_in_progress || reload_completed || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) @@ -2763,7 +2117,7 @@ case 4: return "mov{l}\t{%1, %0|%0, %1}"; case 5: - if (TARGET_SSE2) + if (TARGET_SSE2 && !TARGET_ATHLON) return "pxor\t%0, %0"; else return "xorps\t%0, %0"; @@ -2787,7 +2141,7 @@ abort(); } } - [(set_attr "type" "fmov,fmov,fmov,imov,imov,sse,sse,sse,sse,mmx,mmx,mmx") + [(set_attr "type" "fmov,fmov,fmov,imov,imov,ssemov,ssemov,ssemov,ssemov,mmxmov,mmxmov,mmxmov") (set_attr "mode" "SF,SF,SF,SI,SI,TI,SF,SF,SF,SI,SI,DI")]) (define_insn "*swapsf" @@ -2883,16 +2237,16 @@ ;; %%% Kill this when call knows how to work this out. (define_split [(set (match_operand:DF 0 "push_operand" "") - (match_operand:DF 1 "register_operand" ""))] - "!TARGET_64BIT && reload_completed && ANY_FP_REGNO_P (REGNO (operands[1]))" + (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))] "") (define_split [(set (match_operand:DF 0 "push_operand" "") - (match_operand:DF 1 "register_operand" ""))] - "TARGET_64BIT && reload_completed && ANY_FP_REGNO_P (REGNO (operands[1]))" + (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))] "") @@ -2910,7 +2264,7 @@ (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,H,Y#f,YHm#f,Y#f"))] + (match_operand:DF 1 "general_operand" "fm#Y,f#Y,G,*roF,F*r,C,Y#f,YHm#f,Y#f"))] "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) && (optimize_size || !TARGET_INTEGER_DFMODE_MOVES) && (reload_in_progress || reload_completed @@ -2949,7 +2303,10 @@ case 4: return "#"; case 5: - return "pxor\t%0, %0"; + if (TARGET_ATHLON) + return "xorpd\t%0, %0"; + else + return "pxor\t%0, %0"; case 6: if (TARGET_PARTIAL_REG_DEPENDENCY) return "movapd\t{%1, %0|%0, %1}"; @@ -2963,12 +2320,12 @@ abort(); } } - [(set_attr "type" "fmov,fmov,fmov,multi,multi,sse,sse,sse,sse") + [(set_attr "type" "fmov,fmov,fmov,multi,multi,ssemov,ssemov,ssemov,ssemov") (set_attr "mode" "DF,DF,DF,SI,SI,TI,DF,DF,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,H,Y#rf,Ym#rf,Y#rf"))] + (match_operand:DF 1 "general_operand" "fm#Yr,f#Yr,G,roF#Yf,Fr#Yf,C,Y#rf,Ym#rf,Y#rf"))] "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) && !optimize_size && TARGET_INTEGER_DFMODE_MOVES && (reload_in_progress || reload_completed @@ -3008,7 +2365,10 @@ return "#"; case 5: - return "pxor\t%0, %0"; + if (TARGET_ATHLON) + return "xorpd\t%0, %0"; + else + return "pxor\t%0, %0"; case 6: if (TARGET_PARTIAL_REG_DEPENDENCY) return "movapd\t{%1, %0|%0, %1}"; @@ -3022,7 +2382,7 @@ abort(); } } - [(set_attr "type" "fmov,fmov,fmov,multi,multi,sse,sse,sse,sse") + [(set_attr "type" "fmov,fmov,fmov,multi,multi,ssemov,ssemov,ssemov,ssemov") (set_attr "mode" "DF,DF,DF,SI,SI,TI,DF,DF,DF")]) (define_split @@ -3196,28 +2556,28 @@ && (GET_MODE (operands[0]) == XFmode || GET_MODE (operands[0]) == TFmode || GET_MODE (operands[0]) == DFmode) - && (!REG_P (operands[1]) || !ANY_FP_REGNO_P (REGNO (operands[1])))" + && !ANY_FP_REG_P (operands[1])" [(const_int 0)] "ix86_split_long_move (operands); DONE;") (define_split [(set (match_operand:XF 0 "push_operand" "") - (match_operand:XF 1 "register_operand" ""))] - "!TARGET_64BIT && ANY_FP_REGNO_P (REGNO (operands[1]))" + (match_operand:XF 1 "any_fp_register_operand" ""))] + "!TARGET_64BIT" [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -12))) (set (mem:XF (reg:SI 7)) (match_dup 1))]) (define_split [(set (match_operand:TF 0 "push_operand" "") - (match_operand:TF 1 "register_operand" ""))] - "!TARGET_64BIT && ANY_FP_REGNO_P (REGNO (operands[1]))" + (match_operand:TF 1 "any_fp_register_operand" ""))] + "!TARGET_64BIT" [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) (set (mem:TF (reg:SI 7)) (match_dup 1))]) (define_split [(set (match_operand:TF 0 "push_operand" "") - (match_operand:TF 1 "register_operand" ""))] - "TARGET_64BIT && ANY_FP_REGNO_P (REGNO (operands[1]))" + (match_operand:TF 1 "any_fp_register_operand" ""))] + "TARGET_64BIT" [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -16))) (set (mem:TF (reg:DI 7)) (match_dup 1))]) @@ -3969,15 +3329,15 @@ (define_split [(set (match_operand:DF 0 "push_operand" "") - (float_extend:DF (match_operand:SF 1 "register_operand" "")))] - "!TARGET_64BIT && FP_REGNO_P (REGNO (operands[1]))" + (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)))]) (define_split [(set (match_operand:DF 0 "push_operand" "") - (float_extend:DF (match_operand:SF 1 "register_operand" "")))] - "TARGET_64BIT && FP_REGNO_P (REGNO (operands[1]))" + (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)))]) @@ -3989,8 +3349,8 @@ (define_split [(set (match_operand:XF 0 "push_operand" "") - (float_extend:XF (match_operand:SF 1 "register_operand" "")))] - "!TARGET_64BIT && FP_REGNO_P (REGNO (operands[1]))" + (float_extend:XF (match_operand:SF 1 "fp_register_operand" "")))] + "!TARGET_64BIT" [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -12))) (set (mem:XF (reg:SI 7)) (float_extend:XF (match_dup 1)))]) @@ -4002,15 +3362,15 @@ (define_split [(set (match_operand:TF 0 "push_operand" "") - (float_extend:TF (match_operand:SF 1 "register_operand" "")))] - "!TARGET_64BIT && FP_REGNO_P (REGNO (operands[1]))" + (float_extend:TF (match_operand:SF 1 "fp_register_operand" "")))] + "!TARGET_64BIT" [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) (set (mem:TF (reg:SI 7)) (float_extend:TF (match_dup 1)))]) (define_split [(set (match_operand:TF 0 "push_operand" "") - (float_extend:TF (match_operand:SF 1 "register_operand" "")))] - "TARGET_64BIT && FP_REGNO_P (REGNO (operands[1]))" + (float_extend:TF (match_operand:SF 1 "fp_register_operand" "")))] + "TARGET_64BIT" [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -16))) (set (mem:DF (reg:DI 7)) (float_extend:TF (match_dup 1)))]) @@ -4022,8 +3382,8 @@ (define_split [(set (match_operand:XF 0 "push_operand" "") - (float_extend:XF (match_operand:DF 1 "register_operand" "")))] - "!TARGET_64BIT && FP_REGNO_P (REGNO (operands[1]))" + (float_extend:XF (match_operand:DF 1 "fp_register_operand" "")))] + "!TARGET_64BIT" [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -12))) (set (mem:DF (reg:SI 7)) (float_extend:XF (match_dup 1)))]) @@ -4035,23 +3395,27 @@ (define_split [(set (match_operand:TF 0 "push_operand" "") - (float_extend:TF (match_operand:DF 1 "register_operand" "")))] - "!TARGET_64BIT && FP_REGNO_P (REGNO (operands[1]))" + (float_extend:TF (match_operand:DF 1 "fp_register_operand" "")))] + "!TARGET_64BIT" [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) (set (mem:TF (reg:SI 7)) (float_extend:XF (match_dup 1)))]) (define_split [(set (match_operand:TF 0 "push_operand" "") - (float_extend:TF (match_operand:DF 1 "register_operand" "")))] - "TARGET_64BIT && FP_REGNO_P (REGNO (operands[1]))" + (float_extend:TF (match_operand:DF 1 "fp_register_operand" "")))] + "TARGET_64BIT" [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -16))) (set (mem:TF (reg:DI 7)) (float_extend:TF (match_dup 1)))]) (define_expand "extendsfdf2" [(set (match_operand:DF 0 "nonimmediate_operand" "") - (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "")))] + (float_extend:DF (match_operand:SF 1 "general_operand" "")))] "TARGET_80387 || TARGET_SSE2" { + /* ??? 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 (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) operands[1] = force_reg (SFmode, operands[1]); }) @@ -4086,7 +3450,7 @@ abort (); } } - [(set_attr "type" "fmov,fmov,sse") + [(set_attr "type" "fmov,fmov,ssecvt") (set_attr "mode" "SF,XF,DF")]) (define_insn "*extendsfdf2_1_sse_only" @@ -4095,14 +3459,18 @@ "!TARGET_80387 && TARGET_SSE2 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "cvtss2sd\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") + [(set_attr "type" "ssecvt") (set_attr "mode" "DF")]) (define_expand "extendsfxf2" [(set (match_operand:XF 0 "nonimmediate_operand" "") - (float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "")))] + (float_extend:XF (match_operand:SF 1 "general_operand" "")))] "!TARGET_64BIT && TARGET_80387" { + /* ??? 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 (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) operands[1] = force_reg (SFmode, operands[1]); }) @@ -4141,9 +3509,13 @@ (define_expand "extendsftf2" [(set (match_operand:TF 0 "nonimmediate_operand" "") - (float_extend:TF (match_operand:SF 1 "nonimmediate_operand" "")))] + (float_extend:TF (match_operand:SF 1 "general_operand" "")))] "TARGET_80387" { + /* ??? 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 (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) operands[1] = force_reg (SFmode, operands[1]); }) @@ -4182,9 +3554,13 @@ (define_expand "extenddfxf2" [(set (match_operand:XF 0 "nonimmediate_operand" "") - (float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "")))] + (float_extend:XF (match_operand:DF 1 "general_operand" "")))] "!TARGET_64BIT && TARGET_80387" { + /* ??? 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 (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) operands[1] = force_reg (DFmode, operands[1]); }) @@ -4223,9 +3599,13 @@ (define_expand "extenddftf2" [(set (match_operand:TF 0 "nonimmediate_operand" "") - (float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "")))] + (float_extend:TF (match_operand:DF 1 "general_operand" "")))] "TARGET_80387" { + /* ??? 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 (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) operands[1] = force_reg (DFmode, operands[1]); }) @@ -4325,7 +3705,7 @@ abort (); } } - [(set_attr "type" "fmov,multi,multi,multi,sse") + [(set_attr "type" "fmov,multi,multi,multi,ssecvt") (set_attr "mode" "SF,SF,SF,SF,DF")]) (define_insn "*truncdfsf2_2" @@ -4348,7 +3728,7 @@ abort (); } } - [(set_attr "type" "sse,fmov") + [(set_attr "type" "ssecvt,fmov") (set_attr "mode" "DF,SF")]) (define_insn "truncdfsf2_3" @@ -4371,7 +3751,7 @@ (match_operand:DF 1 "nonimmediate_operand" "mY")))] "!TARGET_80387 && TARGET_SSE2" "cvtsd2ss\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") + [(set_attr "type" "ssecvt") (set_attr "mode" "DF")]) (define_split @@ -4396,10 +3776,9 @@ (define_split [(set (match_operand:SF 0 "register_operand" "") (float_truncate:SF - (match_operand:DF 1 "register_operand" ""))) + (match_operand:DF 1 "fp_register_operand" ""))) (clobber (match_operand:SF 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed - && FP_REG_P (operands[1])" + "TARGET_80387 && reload_completed" [(set (match_dup 2) (float_truncate:SF (match_dup 1))) (set (match_dup 0) (match_dup 2))] "") @@ -4788,14 +4167,14 @@ (fix:DI (match_operand:SF 1 "nonimmediate_operand" "xm")))] "TARGET_64BIT && TARGET_SSE" "cvttss2si{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssecvt")]) (define_insn "fix_truncdfdi_sse" [(set (match_operand:DI 0 "register_operand" "=r") (fix:DI (match_operand:DF 1 "nonimmediate_operand" "Ym")))] "TARGET_64BIT && TARGET_SSE2" "cvttsd2si{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssecvt")]) ;; Signed conversion to SImode. @@ -4896,14 +4275,14 @@ (fix:SI (match_operand:SF 1 "nonimmediate_operand" "xm")))] "TARGET_SSE" "cvttss2si\t{%1, %0|%0, %1}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssecvt")]) (define_insn "fix_truncdfsi_sse" [(set (match_operand:SI 0 "register_operand" "=r") (fix:SI (match_operand:DF 1 "nonimmediate_operand" "Ym")))] "TARGET_SSE2" "cvttsd2si\t{%1, %0|%0, %1}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssecvt")]) (define_split [(set (match_operand:SI 0 "register_operand" "") @@ -5034,22 +4413,22 @@ ;; %% Not used yet. (define_insn "x86_fnstcw_1" [(set (match_operand:HI 0 "memory_operand" "=m") - (unspec:HI [(reg:HI 18)] 11))] + (unspec:HI [(reg:HI 18)] UNSPEC_FSTCW))] "TARGET_80387" "fnstcw\t%0" [(set_attr "length" "2") (set_attr "mode" "HI") - (set_attr "i387" "1") + (set_attr "unit" "i387") (set_attr "ppro_uops" "few")]) (define_insn "x86_fldcw_1" [(set (reg:HI 18) - (unspec:HI [(match_operand:HI 0 "memory_operand" "m")] 12))] + (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 "i387" "1") + (set_attr "unit" "i387") (set_attr "athlon_decode" "vector") (set_attr "ppro_uops" "few")]) @@ -5083,7 +4462,7 @@ fild%z1\t%1 # cvtsi2ss\t{%1, %0|%0, %1}" - [(set_attr "type" "fmov,multi,sse") + [(set_attr "type" "fmov,multi,ssecvt") (set_attr "mode" "SF") (set_attr "fp_int_src" "true")]) @@ -5092,7 +4471,7 @@ (float:SF (match_operand:SI 1 "nonimmediate_operand" "mr")))] "TARGET_SSE" "cvtsi2ss\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") + [(set_attr "type" "ssecvt") (set_attr "mode" "SF") (set_attr "fp_int_src" "true")]) @@ -5121,7 +4500,7 @@ fild%z1\t%1 # cvtsi2ss{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "fmov,multi,sse") + [(set_attr "type" "fmov,multi,ssecvt") (set_attr "mode" "SF") (set_attr "fp_int_src" "true")]) @@ -5130,7 +4509,7 @@ (float:SF (match_operand:DI 1 "nonimmediate_operand" "mr")))] "TARGET_64BIT && TARGET_SSE" "cvtsi2ss{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") + [(set_attr "type" "ssecvt") (set_attr "mode" "SF") (set_attr "fp_int_src" "true")]) @@ -5159,7 +4538,7 @@ fild%z1\t%1 # cvtsi2sd\t{%1, %0|%0, %1}" - [(set_attr "type" "fmov,multi,sse") + [(set_attr "type" "fmov,multi,ssecvt") (set_attr "mode" "DF") (set_attr "fp_int_src" "true")]) @@ -5168,7 +4547,7 @@ (float:DF (match_operand:SI 1 "nonimmediate_operand" "mr")))] "TARGET_SSE2" "cvtsi2sd\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") + [(set_attr "type" "ssecvt") (set_attr "mode" "DF") (set_attr "fp_int_src" "true")]) @@ -5197,7 +4576,7 @@ fild%z1\t%1 # cvtsi2sd{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "fmov,multi,sse") + [(set_attr "type" "fmov,multi,ssecvt") (set_attr "mode" "DF") (set_attr "fp_int_src" "true")]) @@ -5206,7 +4585,7 @@ (float:DF (match_operand:DI 1 "nonimmediate_operand" "mr")))] "TARGET_SSE2" "cvtsi2sd{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") + [(set_attr "type" "ssecvt") (set_attr "mode" "DF") (set_attr "fp_int_src" "true")]) @@ -5278,10 +4657,9 @@ ;; %%% Kill these when reload knows how to do it. (define_split - [(set (match_operand 0 "register_operand" "") + [(set (match_operand 0 "fp_register_operand" "") (float (match_operand 1 "register_operand" "")))] - "reload_completed && FLOAT_MODE_P (GET_MODE (operands[0])) - && FP_REG_P (operands[0])" + "reload_completed && FLOAT_MODE_P (GET_MODE (operands[0]))" [(const_int 0)] { operands[2] = ix86_force_to_memory (GET_MODE (operands[1]), operands[1]); @@ -5320,7 +4698,8 @@ (match_operand:DI 2 "general_operand" ""))) (clobber (reg:CC 17))] "!TARGET_64BIT && reload_completed" - [(parallel [(set (reg:CC 17) (unspec:CC [(match_dup 1) (match_dup 2)] 12)) + [(parallel [(set (reg:CC 17) (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)) @@ -5345,8 +4724,10 @@ (set_attr "ppro_uops" "few")]) (define_insn "*adddi3_cc_rex64" - [(set (reg:CC 17) (unspec:CC [(match_operand:DI 1 "nonimmediate_operand" "%0,0") - (match_operand:DI 2 "x86_64_general_operand" "re,rm")] 12)) + [(set (reg:CC 17) + (unspec:CC [(match_operand:DI 1 "nonimmediate_operand" "%0,0") + (match_operand:DI 2 "x86_64_general_operand" "re,rm")] + UNSPEC_ADD_CARRY)) (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") (plus:DI (match_dup 1) (match_dup 2)))] "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)" @@ -5382,8 +4763,10 @@ (set_attr "ppro_uops" "few")]) (define_insn "*addsi3_cc" - [(set (reg:CC 17) (unspec:CC [(match_operand:SI 1 "nonimmediate_operand" "%0,0") - (match_operand:SI 2 "general_operand" "ri,rm")] 12)) + [(set (reg:CC 17) + (unspec:CC [(match_operand:SI 1 "nonimmediate_operand" "%0,0") + (match_operand:SI 2 "general_operand" "ri,rm")] + UNSPEC_ADD_CARRY)) (set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") (plus:SI (match_dup 1) (match_dup 2)))] "ix86_binary_operator_ok (PLUS, SImode, operands)" @@ -5392,8 +4775,10 @@ (set_attr "mode" "SI")]) (define_insn "addqi3_cc" - [(set (reg:CC 17) (unspec:CC [(match_operand:QI 1 "nonimmediate_operand" "%0,0") - (match_operand:QI 2 "general_operand" "qi,qm")] 12)) + [(set (reg:CC 17) + (unspec:CC [(match_operand:QI 1 "nonimmediate_operand" "%0,0") + (match_operand:QI 2 "general_operand" "qi,qm")] + UNSPEC_ADD_CARRY)) (set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") (plus:QI (match_dup 1) (match_dup 2)))] "ix86_binary_operator_ok (PLUS, QImode, operands)" @@ -5446,7 +4831,7 @@ (define_insn_and_split "*lea_general_1" [(set (match_operand 0 "register_operand" "=r") - (plus (plus (match_operand 1 "register_operand" "r") + (plus (plus (match_operand 1 "index_register_operand" "r") (match_operand 2 "register_operand" "r")) (match_operand 3 "immediate_operand" "i")))] "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode @@ -5478,7 +4863,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 "register_operand" "r") + (plus:SI (plus:SI (match_operand:SI 1 "index_register_operand" "r") (match_operand:SI 2 "register_operand" "r")) (match_operand:SI 3 "immediate_operand" "i"))))] "TARGET_64BIT" @@ -5498,7 +4883,7 @@ (define_insn_and_split "*lea_general_2" [(set (match_operand 0 "register_operand" "=r") - (plus (mult (match_operand 1 "register_operand" "r") + (plus (mult (match_operand 1 "index_register_operand" "r") (match_operand 2 "const248_operand" "i")) (match_operand 3 "nonmemory_operand" "ri")))] "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode @@ -5528,7 +4913,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 "register_operand" "r") + (plus:SI (mult:SI (match_operand:SI 1 "index_register_operand" "r") (match_operand:SI 2 "const248_operand" "n")) (match_operand:SI 3 "nonmemory_operand" "ri"))))] "TARGET_64BIT" @@ -5547,7 +4932,7 @@ (define_insn_and_split "*lea_general_3" [(set (match_operand 0 "register_operand" "=r") - (plus (plus (mult (match_operand 1 "register_operand" "r") + (plus (plus (mult (match_operand 1 "index_register_operand" "r") (match_operand 2 "const248_operand" "i")) (match_operand 3 "register_operand" "r")) (match_operand 4 "immediate_operand" "i")))] @@ -5581,7 +4966,7 @@ (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 "register_operand" "r") + (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "index_register_operand" "r") (match_operand:SI 2 "const248_operand" "n")) (match_operand:SI 3 "register_operand" "r")) (match_operand:SI 4 "immediate_operand" "i"))))] @@ -6318,9 +5703,7 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{w}\t%0"; - else if (operands[2] == constm1_rtx - || (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 65535)) + else if (operands[2] == constm1_rtx) return "dec{w}\t%0"; abort(); @@ -6359,9 +5742,7 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{w}\t%0"; - else if (operands[2] == constm1_rtx - || (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 65535)) + else if (operands[2] == constm1_rtx) return "dec{w}\t%0"; abort(); @@ -6401,9 +5782,7 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{w}\t%0"; - else if (operands[2] == constm1_rtx - || (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 65535)) + else if (operands[2] == constm1_rtx) return "dec{w}\t%0"; abort(); @@ -6440,9 +5819,7 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{w}\t%0"; - else if (operands[2] == constm1_rtx - || (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 65535)) + else if (operands[2] == constm1_rtx) return "dec{w}\t%0"; abort(); @@ -6478,9 +5855,7 @@ switch (get_attr_type (insn)) { case TYPE_INCDEC: - if (operands[2] == constm1_rtx - || (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 65535)) + if (operands[2] == constm1_rtx) return "inc{w}\t%0"; else if (operands[2] == const1_rtx) return "dec{w}\t%0"; @@ -6522,9 +5897,7 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return "inc{w}\t%0"; - else if (operands[2] == constm1_rtx - || (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 65535)) + else if (operands[2] == constm1_rtx) return "dec{w}\t%0"; abort(); @@ -6573,9 +5946,7 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return widen ? "inc{l}\t%k0" : "inc{b}\t%0"; - else if (operands[2] == constm1_rtx - || (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 255)) + else if (operands[2] == constm1_rtx) return widen ? "dec{l}\t%k0" : "dec{b}\t%0"; abort(); @@ -6621,9 +5992,7 @@ case TYPE_INCDEC: if (operands[2] == const1_rtx) return widen ? "inc{l}\t%k0" : "inc{b}\t%0"; - else if (operands[2] == constm1_rtx - || (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 255)) + else if (operands[2] == constm1_rtx) return widen ? "dec{l}\t%k0" : "dec{b}\t%0"; abort(); @@ -6653,6 +6022,40 @@ (const_string "alu"))) (set_attr "mode" "QI,QI,SI")]) +(define_insn "*addqi_1_slp" + [(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))] + "(! TARGET_PARTIAL_REG_STALL || optimize_size) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" +{ + switch (get_attr_type (insn)) + { + 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(); + + default: + /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. */ + if (GET_CODE (operands[1]) == CONST_INT + && INTVAL (operands[1]) < 0) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + return "sub{b}\t{%1, %0|%0, %1}"; + } + return "add{b}\t{%1, %0|%0, %1}"; + } +} + [(set (attr "type") + (if_then_else (match_operand:QI 2 "incdec_operand" "") + (const_string "incdec") + (const_string "alu1"))) + (set_attr "mode" "QI")]) + (define_insn "*addqi_2" [(set (reg 17) (compare @@ -7184,6 +6587,17 @@ [(set_attr "type" "alu") (set_attr "mode" "QI")]) +(define_insn "*subqi_1_slp" + [(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))] + "(! TARGET_PARTIAL_REG_STALL || optimize_size) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" + "sub{b}\t{%1, %0|%0, %1}" + [(set_attr "type" "alu1") + (set_attr "mode" "QI")]) + (define_insn "*subqi_2" [(set (reg 17) (compare @@ -7822,7 +7236,7 @@ (use (match_dup 3)) (clobber (reg:CC 17))])] { - /* Avoid use of cltd in favour of a mov+shift. */ + /* Avoid use of cltd in favor of a mov+shift. */ if (!TARGET_USE_CLTD && !optimize_size) { if (true_regnum (operands[1])) @@ -7907,7 +7321,7 @@ (use (match_dup 3)) (clobber (reg:CC 17))])] { - /* Avoid use of cltd in favour of a mov+shift. */ + /* Avoid use of cltd in favor of a mov+shift. */ if (!TARGET_USE_CLTD && !optimize_size) { if (true_regnum (operands[1])) @@ -8180,8 +7594,7 @@ (const_int 8)) (match_operand 1 "const_int_operand" "n")) (const_int 0)))] - "(unsigned HOST_WIDE_INT) INTVAL (operands[1]) <= 0xff - && ix86_match_ccmode (insn, CCNOmode)" + "ix86_match_ccmode (insn, CCNOmode)" "test{b}\t{%1, %h0|%h0, %1}" [(set_attr "type" "test") (set_attr "mode" "QI") @@ -8319,10 +7732,57 @@ mask = ((HOST_WIDE_INT)1 << (pos + len)) - 1; mask &= ~(((HOST_WIDE_INT)1 << pos) - 1); - operands[3] = gen_rtx_AND (mode, operands[0], - GEN_INT (trunc_int_for_mode (mask, mode))); + operands[3] = gen_rtx_AND (mode, operands[0], gen_int_mode (mask, mode)); }) +;; Convert HImode/SImode test instructions with immediate to QImode ones. +;; i386 does not allow to encode test with 8bit sign extended immediate, so +;; this is relatively important trick. +;; Do the converison only post-reload to avoid limiting of the register class +;; to QI regs. +(define_split + [(set (reg 17) + (compare + (and (match_operand 0 "register_operand" "") + (match_operand 1 "const_int_operand" "")) + (const_int 0)))] + "reload_completed + && QI_REG_P (operands[0]) + && ((ix86_match_ccmode (insn, CCZmode) + && !(INTVAL (operands[1]) & ~(255 << 8))) + || (ix86_match_ccmode (insn, CCNOmode) + && !(INTVAL (operands[1]) & ~(127 << 8)))) + && GET_MODE (operands[0]) != QImode" + [(set (reg:CCNO 17) + (compare:CCNO + (and:SI (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8)) + (match_dup 1)) + (const_int 0)))] + "operands[0] = gen_lowpart (SImode, operands[0]); + operands[1] = gen_int_mode (INTVAL (operands[1]) >> 8, SImode);") + +(define_split + [(set (reg 17) + (compare + (and (match_operand 0 "nonimmediate_operand" "") + (match_operand 1 "const_int_operand" "")) + (const_int 0)))] + "reload_completed + && (!REG_P (operands[0]) || ANY_QI_REG_P (operands[0])) + && ((ix86_match_ccmode (insn, CCZmode) + && !(INTVAL (operands[1]) & ~255)) + || (ix86_match_ccmode (insn, CCNOmode) + && !(INTVAL (operands[1]) & ~127))) + && GET_MODE (operands[0]) != QImode" + [(set (reg:CCNO 17) + (compare:CCNO + (and:QI (match_dup 0) + (match_dup 1)) + (const_int 0)))] + "operands[0] = gen_lowpart (QImode, operands[0]); + operands[1] = gen_lowpart (QImode, operands[1]);") + + ;; %%% This used to optimize known byte-wide and operations to memory, ;; and sometimes to QImode registers. If this is considered useful, ;; it should be done with splitters. @@ -8445,7 +7905,7 @@ (and (match_dup 0) (const_int -65536))) (clobber (reg:CC 17))] - "optimize_size" + "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]);") @@ -8591,7 +8051,8 @@ (and:QI (match_dup 0) (match_operand:QI 1 "general_operand" "qi,qmi"))) (clobber (reg:CC 17))] - "" + "(! TARGET_PARTIAL_REG_STALL || optimize_size) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "and{b}\t{%1, %0|%0, %1}" [(set_attr "type" "alu1") (set_attr "mode" "QI")]) @@ -8627,7 +8088,9 @@ (const_int 0))) (set (strict_low_part (match_dup 0)) (and:QI (match_dup 0) (match_dup 1)))] - "ix86_match_ccmode (insn, CCNOmode)" + "(! TARGET_PARTIAL_REG_STALL || optimize_size) + && ix86_match_ccmode (insn, CCNOmode) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "and{b}\t{%1, %0|%0, %1}" [(set_attr "type" "alu1") (set_attr "mode" "QI")]) @@ -8647,7 +8110,7 @@ (const_int 8)) (match_operand 2 "const_int_operand" "n"))) (clobber (reg:CC 17))] - "(unsigned HOST_WIDE_INT)INTVAL (operands[2]) <= 0xff" + "" "and{b}\t{%2, %h0|%h0, %2}" [(set_attr "type" "alu") (set_attr "length_immediate" "1") @@ -8675,8 +8138,7 @@ (const_int 8) (const_int 8)) (match_dup 2)))] - "ix86_match_ccmode (insn, CCNOmode) - && (unsigned HOST_WIDE_INT)INTVAL (operands[2]) <= 0xff" + "ix86_match_ccmode (insn, CCNOmode)" "and{b}\t{%2, %h0|%h0, %2}" [(set_attr "type" "alu") (set_attr "length_immediate" "1") @@ -8737,6 +8199,51 @@ [(set_attr "type" "alu") (set_attr "length_immediate" "0") (set_attr "mode" "QI")]) + +;; Convert wide AND instructions with immediate operand to shorter QImode +;; equivalents when possible. +;; Don't do the splitting with memory operands, since it intoduces risc +;; of memory mismatch stalls. We may want to do the splitting for optimizing +;; for size, but that can (should?) be handled by generic code instead. +(define_split + [(set (match_operand 0 "register_operand" "") + (and (match_operand 1 "register_operand" "") + (match_operand 2 "const_int_operand" ""))) + (clobber (reg:CC 17))] + "reload_completed + && QI_REG_P (operands[0]) + && (!TARGET_PARTIAL_REG_STALL || optimize_size) + && !(~INTVAL (operands[2]) & ~(255 << 8)) + && GET_MODE (operands[0]) != QImode" + [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8)) + (and:SI (zero_extract:SI (match_dup 1) + (const_int 8) (const_int 8)) + (match_dup 2))) + (clobber (reg:CC 17))])] + "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);") + +;; Since AND can be encoded with sign extended immediate, this is only +;; profitable when 7th bit is not set. +(define_split + [(set (match_operand 0 "register_operand" "") + (and (match_operand 1 "general_operand" "") + (match_operand 2 "const_int_operand" ""))) + (clobber (reg:CC 17))] + "reload_completed + && ANY_QI_REG_P (operands[0]) + && (!TARGET_PARTIAL_REG_STALL || optimize_size) + && !(~INTVAL (operands[2]) & ~255) + && !(INTVAL (operands[2]) & 128) + && GET_MODE (operands[0]) != QImode" + [(parallel [(set (strict_low_part (match_dup 0)) + (and:QI (match_dup 1) + (match_dup 2))) + (clobber (reg:CC 17))])] + "operands[0] = gen_lowpart (QImode, operands[0]); + operands[1] = gen_lowpart (QImode, operands[1]); + operands[2] = gen_lowpart (QImode, operands[2]);") ;; Logical inclusive OR instructions @@ -8953,7 +8460,8 @@ (ior:QI (match_dup 0) (match_operand:QI 1 "general_operand" "qmi,qi"))) (clobber (reg:CC 17))] - "" + "(! TARGET_PARTIAL_REG_STALL || optimize_size) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "or{b}\t{%1, %0|%0, %1}" [(set_attr "type" "alu1") (set_attr "mode" "QI")]) @@ -8978,7 +8486,9 @@ (const_int 0))) (set (strict_low_part (match_dup 0)) (ior:QI (match_dup 0) (match_dup 1)))] - "ix86_match_ccmode (insn, CCNOmode)" + "(! TARGET_PARTIAL_REG_STALL || optimize_size) + && ix86_match_ccmode (insn, CCNOmode) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "or{b}\t{%1, %0|%0, %1}" [(set_attr "type" "alu1") (set_attr "mode" "QI")]) @@ -8995,6 +8505,118 @@ [(set_attr "type" "alu") (set_attr "mode" "QI")]) +(define_insn "iorqi_ext_0" + [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") + (const_int 8) + (const_int 8)) + (ior:SI + (zero_extract:SI + (match_operand 1 "ext_register_operand" "0") + (const_int 8) + (const_int 8)) + (match_operand 2 "const_int_operand" "n"))) + (clobber (reg:CC 17))] + "(!TARGET_PARTIAL_REG_STALL || optimize_size)" + "or{b}\t{%2, %h0|%h0, %2}" + [(set_attr "type" "alu") + (set_attr "length_immediate" "1") + (set_attr "mode" "QI")]) + +(define_insn "*iorqi_ext_1" + [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") + (const_int 8) + (const_int 8)) + (ior:SI + (zero_extract:SI + (match_operand 1 "ext_register_operand" "0") + (const_int 8) + (const_int 8)) + (zero_extend:SI + (match_operand:QI 2 "general_operand" "Qm")))) + (clobber (reg:CC 17))] + "!TARGET_64BIT + && (!TARGET_PARTIAL_REG_STALL || optimize_size)" + "or{b}\t{%2, %h0|%h0, %2}" + [(set_attr "type" "alu") + (set_attr "length_immediate" "0") + (set_attr "mode" "QI")]) + +(define_insn "*iorqi_ext_1_rex64" + [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") + (const_int 8) + (const_int 8)) + (ior:SI + (zero_extract:SI + (match_operand 1 "ext_register_operand" "0") + (const_int 8) + (const_int 8)) + (zero_extend:SI + (match_operand 2 "ext_register_operand" "Q")))) + (clobber (reg:CC 17))] + "TARGET_64BIT + && (!TARGET_PARTIAL_REG_STALL || optimize_size)" + "or{b}\t{%2, %h0|%h0, %2}" + [(set_attr "type" "alu") + (set_attr "length_immediate" "0") + (set_attr "mode" "QI")]) + +(define_insn "*iorqi_ext_2" + [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") + (const_int 8) + (const_int 8)) + (ior:SI + (zero_extract:SI (match_operand 1 "ext_register_operand" "0") + (const_int 8) + (const_int 8)) + (zero_extract:SI (match_operand 2 "ext_register_operand" "Q") + (const_int 8) + (const_int 8)))) + (clobber (reg:CC 17))] + "(!TARGET_PARTIAL_REG_STALL || optimize_size)" + "ior{b}\t{%h2, %h0|%h0, %h2}" + [(set_attr "type" "alu") + (set_attr "length_immediate" "0") + (set_attr "mode" "QI")]) + +(define_split + [(set (match_operand 0 "register_operand" "") + (ior (match_operand 1 "register_operand" "") + (match_operand 2 "const_int_operand" ""))) + (clobber (reg:CC 17))] + "reload_completed + && QI_REG_P (operands[0]) + && (!TARGET_PARTIAL_REG_STALL || optimize_size) + && !(INTVAL (operands[2]) & ~(255 << 8)) + && GET_MODE (operands[0]) != QImode" + [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8)) + (ior:SI (zero_extract:SI (match_dup 1) + (const_int 8) (const_int 8)) + (match_dup 2))) + (clobber (reg:CC 17))])] + "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);") + +;; Since OR can be encoded with sign extended immediate, this is only +;; profitable when 7th bit is set. +(define_split + [(set (match_operand 0 "register_operand" "") + (ior (match_operand 1 "general_operand" "") + (match_operand 2 "const_int_operand" ""))) + (clobber (reg:CC 17))] + "reload_completed + && ANY_QI_REG_P (operands[0]) + && (!TARGET_PARTIAL_REG_STALL || optimize_size) + && !(INTVAL (operands[2]) & ~255) + && (INTVAL (operands[2]) & 128) + && GET_MODE (operands[0]) != QImode" + [(parallel [(set (strict_low_part (match_dup 0)) + (ior:QI (match_dup 1) + (match_dup 2))) + (clobber (reg:CC 17))])] + "operands[0] = gen_lowpart (QImode, operands[0]); + operands[1] = gen_lowpart (QImode, operands[1]); + operands[2] = gen_lowpart (QImode, operands[2]);") ;; Logical XOR instructions @@ -9210,11 +8832,77 @@ [(set_attr "type" "alu") (set_attr "mode" "QI,QI,SI")]) +(define_insn "*xorqi_1_slp" + [(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))] + "(! TARGET_PARTIAL_REG_STALL || optimize_size) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" + "xor{b}\t{%1, %0|%0, %1}" + [(set_attr "type" "alu1") + (set_attr "mode" "QI")]) + +(define_insn "xorqi_ext_0" + [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") + (const_int 8) + (const_int 8)) + (xor:SI + (zero_extract:SI + (match_operand 1 "ext_register_operand" "0") + (const_int 8) + (const_int 8)) + (match_operand 2 "const_int_operand" "n"))) + (clobber (reg:CC 17))] + "(!TARGET_PARTIAL_REG_STALL || optimize_size)" + "xor{b}\t{%2, %h0|%h0, %2}" + [(set_attr "type" "alu") + (set_attr "length_immediate" "1") + (set_attr "mode" "QI")]) + (define_insn "*xorqi_ext_1" [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") (const_int 8) (const_int 8)) (xor:SI + (zero_extract:SI + (match_operand 1 "ext_register_operand" "0") + (const_int 8) + (const_int 8)) + (zero_extend:SI + (match_operand:QI 2 "general_operand" "Qm")))) + (clobber (reg:CC 17))] + "!TARGET_64BIT + && (!TARGET_PARTIAL_REG_STALL || optimize_size)" + "xor{b}\t{%2, %h0|%h0, %2}" + [(set_attr "type" "alu") + (set_attr "length_immediate" "0") + (set_attr "mode" "QI")]) + +(define_insn "*xorqi_ext_1_rex64" + [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") + (const_int 8) + (const_int 8)) + (xor:SI + (zero_extract:SI + (match_operand 1 "ext_register_operand" "0") + (const_int 8) + (const_int 8)) + (zero_extend:SI + (match_operand 2 "ext_register_operand" "Q")))) + (clobber (reg:CC 17))] + "TARGET_64BIT + && (!TARGET_PARTIAL_REG_STALL || optimize_size)" + "xor{b}\t{%2, %h0|%h0, %2}" + [(set_attr "type" "alu") + (set_attr "length_immediate" "0") + (set_attr "mode" "QI")]) + +(define_insn "*xorqi_ext_2" + [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") + (const_int 8) + (const_int 8)) + (xor:SI (zero_extract:SI (match_operand 1 "ext_register_operand" "0") (const_int 8) (const_int 8)) @@ -9222,7 +8910,7 @@ (const_int 8) (const_int 8)))) (clobber (reg:CC 17))] - "" + "(!TARGET_PARTIAL_REG_STALL || optimize_size)" "xor{b}\t{%h2, %h0|%h0, %h2}" [(set_attr "type" "alu") (set_attr "length_immediate" "0") @@ -9242,6 +8930,20 @@ [(set_attr "type" "alu") (set_attr "mode" "QI")]) +(define_insn "*xorqi_2_slp" + [(set (reg 17) + (compare (xor:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm") + (match_operand:QI 1 "general_operand" "qim,qi")) + (const_int 0))) + (set (strict_low_part (match_dup 0)) + (xor:QI (match_dup 0) (match_dup 1)))] + "(! TARGET_PARTIAL_REG_STALL || optimize_size) + && ix86_match_ccmode (insn, CCNOmode) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" + "xor{b}\t{%1, %0|%0, %1}" + [(set_attr "type" "alu1") + (set_attr "mode" "QI")]) + (define_insn "*xorqi_cc_2" [(set (reg 17) (compare @@ -9316,6 +9018,46 @@ (match_dup 2)))])] "" "") + +(define_split + [(set (match_operand 0 "register_operand" "") + (xor (match_operand 1 "register_operand" "") + (match_operand 2 "const_int_operand" ""))) + (clobber (reg:CC 17))] + "reload_completed + && QI_REG_P (operands[0]) + && (!TARGET_PARTIAL_REG_STALL || optimize_size) + && !(INTVAL (operands[2]) & ~(255 << 8)) + && GET_MODE (operands[0]) != QImode" + [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8)) + (xor:SI (zero_extract:SI (match_dup 1) + (const_int 8) (const_int 8)) + (match_dup 2))) + (clobber (reg:CC 17))])] + "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);") + +;; Since XOR can be encoded with sign extended immediate, this is only +;; profitable when 7th bit is set. +(define_split + [(set (match_operand 0 "register_operand" "") + (xor (match_operand 1 "general_operand" "") + (match_operand 2 "const_int_operand" ""))) + (clobber (reg:CC 17))] + "reload_completed + && ANY_QI_REG_P (operands[0]) + && (!TARGET_PARTIAL_REG_STALL || optimize_size) + && !(INTVAL (operands[2]) & ~255) + && (INTVAL (operands[2]) & 128) + && GET_MODE (operands[0]) != QImode" + [(parallel [(set (strict_low_part (match_dup 0)) + (xor:QI (match_dup 1) + (match_dup 2))) + (clobber (reg:CC 17))])] + "operands[0] = gen_lowpart (QImode, operands[0]); + operands[1] = gen_lowpart (QImode, operands[1]); + operands[2] = gen_lowpart (QImode, operands[2]);") ;; Negation instructions @@ -9519,8 +9261,7 @@ operands[0] = force_reg (SFmode, operands[0]); emit_move_insn (reg, gen_lowpart (SFmode, - GEN_INT (trunc_int_for_mode (0x80000000, - SImode)))); + gen_int_mode (0x80000000, SImode))); emit_insn (gen_negsf2_ifs (operands[0], operands[1], reg)); if (dest != operands[0]) emit_move_insn (dest, operands[0]); @@ -9599,22 +9340,22 @@ "#") (define_split - [(set (match_operand:SF 0 "register_operand" "") + [(set (match_operand:SF 0 "fp_register_operand" "") (neg:SF (match_operand:SF 1 "register_operand" ""))) (clobber (reg:CC 17))] - "TARGET_80387 && FP_REGNO_P (REGNO (operands[0])) && reload_completed" + "TARGET_80387 && reload_completed" [(set (match_dup 0) (neg:SF (match_dup 1)))] "") (define_split - [(set (match_operand:SF 0 "register_operand" "") + [(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 && !FP_REGNO_P (REGNO (operands[0]))" + "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 (trunc_int_for_mode (0x80000000, SImode)); + "operands[1] = gen_int_mode (0x80000000, SImode); operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));") (define_split @@ -9631,7 +9372,7 @@ if (size >= 12) size = 10; operands[0] = adjust_address (operands[0], QImode, size - 1); - operands[1] = GEN_INT (trunc_int_for_mode (0x80, QImode)); + operands[1] = gen_int_mode (0x80, QImode); }) (define_expand "negdf2" @@ -9651,8 +9392,7 @@ in register. */ rtx reg = gen_reg_rtx (DFmode); #if HOST_BITS_PER_WIDE_INT >= 64 - rtx imm = GEN_INT (trunc_int_for_mode(((HOST_WIDE_INT)1) << 63, - DImode)); + rtx imm = gen_int_mode (((HOST_WIDE_INT)1) << 63, DImode); #else rtx imm = immed_double_const (0, 0x80000000, DImode); #endif @@ -9688,9 +9428,9 @@ "#") (define_insn "*negdf2_ifs_rex64" - [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#fr,Y#fr,fm#Yr,r#Yf") - (neg:DF (match_operand:DF 1 "nonimmediate_operand" "0,Y#fr,0,0"))) - (use (match_operand:DF 2 "general_operand" "Y,0,*g#Yr,*rm")) + [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#f,Y#f,fm#Y") + (neg:DF (match_operand:DF 1 "nonimmediate_operand" "0,Y#f,0"))) + (use (match_operand:DF 2 "general_operand" "Y,0,*g#Y*r")) (clobber (reg:CC 17))] "TARGET_64BIT && TARGET_SSE2 && (reload_in_progress || reload_completed @@ -9775,23 +9515,22 @@ "#") (define_split - [(set (match_operand:DF 0 "register_operand" "") + [(set (match_operand:DF 0 "fp_register_operand" "") (neg:DF (match_operand:DF 1 "register_operand" ""))) (clobber (reg:CC 17))] - "TARGET_80387 && FP_REGNO_P (REGNO (operands[0])) && reload_completed" + "TARGET_80387 && reload_completed" [(set (match_dup 0) (neg:DF (match_dup 1)))] "") (define_split - [(set (match_operand:DF 0 "register_operand" "") + [(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 - && !FP_REGNO_P (REGNO (operands[0]))" + "!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 (trunc_int_for_mode (0x80000000, SImode)); + "operands[4] = gen_int_mode (0x80000000, SImode); split_di (operands+0, 1, operands+2, operands+3);") (define_expand "negxf2" @@ -9820,19 +9559,19 @@ "#") (define_split - [(set (match_operand:XF 0 "register_operand" "") + [(set (match_operand:XF 0 "fp_register_operand" "") (neg:XF (match_operand:XF 1 "register_operand" ""))) (clobber (reg:CC 17))] - "TARGET_80387 && FP_REGNO_P (REGNO (operands[0])) && reload_completed" + "TARGET_80387 && reload_completed" [(set (match_dup 0) (neg:XF (match_dup 1)))] "") (define_split - [(set (match_operand:XF 0 "register_operand" "") + [(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 && !FP_REGNO_P (REGNO (operands[0]))" + "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); @@ -9850,19 +9589,19 @@ "#") (define_split - [(set (match_operand:TF 0 "register_operand" "") + [(set (match_operand:TF 0 "fp_register_operand" "") (neg:TF (match_operand:TF 1 "register_operand" ""))) (clobber (reg:CC 17))] - "TARGET_80387 && FP_REGNO_P (REGNO (operands[0])) && reload_completed" + "TARGET_80387 && reload_completed" [(set (match_dup 0) (neg:TF (match_dup 1)))] "") (define_split - [(set (match_operand:TF 0 "register_operand" "") + [(set (match_operand:TF 0 "register_and_not_fp_reg_operand" "") (neg:TF (match_operand:TF 1 "register_operand" ""))) (clobber (reg:CC 17))] - "TARGET_80387 && reload_completed && !FP_REGNO_P (REGNO (operands[0]))" + "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); @@ -9982,8 +9721,7 @@ operands[0] = force_reg (SFmode, operands[0]); emit_move_insn (reg, gen_lowpart (SFmode, - GEN_INT (trunc_int_for_mode (0x80000000, - SImode)))); + gen_int_mode (0x80000000, SImode))); emit_insn (gen_abssf2_ifs (operands[0], operands[1], reg)); if (dest != operands[0]) emit_move_insn (dest, operands[0]); @@ -10051,22 +9789,22 @@ "#") (define_split - [(set (match_operand:SF 0 "register_operand" "") + [(set (match_operand:SF 0 "fp_register_operand" "") (abs:SF (match_operand:SF 1 "register_operand" ""))) (clobber (reg:CC 17))] - "TARGET_80387 && FP_REGNO_P (REGNO (operands[0]))" + "TARGET_80387" [(set (match_dup 0) (abs:SF (match_dup 1)))] "") (define_split - [(set (match_operand:SF 0 "register_operand" "") + [(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 && !FP_REGNO_P (REGNO (operands[0]))" + "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 (trunc_int_for_mode (~0x80000000, SImode)); + "operands[1] = gen_int_mode (~0x80000000, SImode); operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));") (define_split @@ -10083,7 +9821,7 @@ if (size >= 12) size = 10; operands[0] = adjust_address (operands[0], QImode, size - 1); - operands[1] = GEN_INT (trunc_int_for_mode (~0x80, QImode)); + operands[1] = gen_int_mode (~0x80, QImode); }) (define_expand "absdf2" @@ -10103,8 +9841,7 @@ in register. */ rtx reg = gen_reg_rtx (DFmode); #if HOST_BITS_PER_WIDE_INT >= 64 - rtx imm = GEN_INT (trunc_int_for_mode(((HOST_WIDE_INT)1) << 63, - DImode)); + rtx imm = gen_int_mode (((HOST_WIDE_INT)1) << 63, DImode); #else rtx imm = immed_double_const (0, 0x80000000, DImode); #endif @@ -10205,23 +9942,22 @@ "#") (define_split - [(set (match_operand:DF 0 "register_operand" "") + [(set (match_operand:DF 0 "fp_register_operand" "") (abs:DF (match_operand:DF 1 "register_operand" ""))) (clobber (reg:CC 17))] - "TARGET_80387 && FP_REGNO_P (REGNO (operands[0])) && reload_completed" + "TARGET_80387 && reload_completed" [(set (match_dup 0) (abs:DF (match_dup 1)))] "") (define_split - [(set (match_operand:DF 0 "register_operand" "") + [(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 && - !FP_REGNO_P (REGNO (operands[0]))" + "!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 (trunc_int_for_mode (~0x80000000, SImode)); + "operands[4] = gen_int_mode (~0x80000000, SImode); split_di (operands+0, 1, operands+2, operands+3);") (define_expand "absxf2" @@ -10250,19 +9986,19 @@ "#") (define_split - [(set (match_operand:XF 0 "register_operand" "") + [(set (match_operand:XF 0 "fp_register_operand" "") (abs:XF (match_operand:XF 1 "register_operand" ""))) (clobber (reg:CC 17))] - "TARGET_80387 && FP_REGNO_P (REGNO (operands[0])) && reload_completed" + "TARGET_80387 && reload_completed" [(set (match_dup 0) (abs:XF (match_dup 1)))] "") (define_split - [(set (match_operand:XF 0 "register_operand" "") + [(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 && !FP_REGNO_P (REGNO (operands[0]))" + "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); @@ -10277,19 +10013,19 @@ "#") (define_split - [(set (match_operand:TF 0 "register_operand" "") + [(set (match_operand:TF 0 "fp_register_operand" "") (abs:TF (match_operand:TF 1 "register_operand" ""))) (clobber (reg:CC 17))] - "TARGET_80387 && FP_REGNO_P (REGNO (operands[0])) && reload_completed" + "TARGET_80387 && reload_completed" [(set (match_dup 0) (abs:TF (match_dup 1)))] "") (define_split - [(set (match_operand:TF 0 "register_operand" "") + [(set (match_operand:TF 0 "register_and_not_any_fp_reg_operand" "") (abs:TF (match_operand:TF 1 "register_operand" ""))) (clobber (reg:CC 17))] - "TARGET_80387 && reload_completed && !FP_REGNO_P (REGNO (operands[0]))" + "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); @@ -10643,7 +10379,7 @@ return "sal{q}\t{%b2, %0|%0, %b2}"; else if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 1 - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)) + && (TARGET_SHIFT1 || optimize_size)) return "sal{q}\t%0"; else return "sal{q}\t{%2, %0|%0, %2}"; @@ -10672,8 +10408,7 @@ [(set (match_dup 0) (mult:DI (match_dup 1) (match_dup 2)))] - "operands[2] = GEN_INT (trunc_int_for_mode (1 << INTVAL (operands[2]), - DImode));") + "operands[2] = gen_int_mode (1 << INTVAL (operands[2]), DImode);") ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant @@ -10701,7 +10436,7 @@ return "sal{q}\t{%b2, %0|%0, %b2}"; else if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 1 - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)) + && (TARGET_SHIFT1 || optimize_size)) return "sal{q}\t%0"; else return "sal{q}\t{%2, %0|%0, %2}"; @@ -10849,7 +10584,7 @@ return "sal{l}\t{%b2, %0|%0, %b2}"; else if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 1 - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)) + && (TARGET_SHIFT1 || optimize_size)) return "sal{l}\t%0"; else return "sal{l}\t{%2, %0|%0, %2}"; @@ -10870,7 +10605,7 @@ ;; Convert lea to the lea pattern to avoid flags dependency. (define_split [(set (match_operand 0 "register_operand" "") - (ashift (match_operand 1 "register_operand" "") + (ashift (match_operand 1 "index_register_operand" "") (match_operand:QI 2 "const_int_operand" ""))) (clobber (reg:CC 17))] "reload_completed @@ -10880,8 +10615,7 @@ rtx pat; operands[0] = gen_lowpart (SImode, operands[0]); operands[1] = gen_lowpart (Pmode, operands[1]); - operands[2] = GEN_INT (trunc_int_for_mode (1 << INTVAL (operands[2]), - Pmode)); + 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); @@ -10889,6 +10623,26 @@ DONE; }) +;; Rare case of shifting RSP is handled by generating move and shift +(define_split + [(set (match_operand 0 "register_operand" "") + (ashift (match_operand 1 "register_operand" "") + (match_operand:QI 2 "const_int_operand" ""))) + (clobber (reg:CC 17))] + "reload_completed + && true_regnum (operands[0]) != true_regnum (operands[1])" + [(const_int 0)] +{ + rtx pat, clob; + emit_move_insn (operands[1], operands[0]); + pat = gen_rtx_SET (VOIDmode, operands[0], + gen_rtx_ASHIFT (GET_MODE (operands[0]), + operands[0], operands[2])); + clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG)); + emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, pat, clob))); + DONE; +}) + (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") @@ -10911,7 +10665,7 @@ return "sal{l}\t{%b2, %k0|%k0, %b2}"; else if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 1 - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)) + && (TARGET_SHIFT1 || optimize_size)) return "sal{l}\t%k0"; else return "sal{l}\t{%2, %k0|%k0, %2}"; @@ -10939,8 +10693,7 @@ [(set (match_dup 0) (zero_extend:DI (subreg:SI (mult:SI (match_dup 1) (match_dup 2)) 0)))] { operands[1] = gen_lowpart (Pmode, operands[1]); - operands[2] = GEN_INT (trunc_int_for_mode (1 << INTVAL (operands[2]), - Pmode)); + operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode); }) ;; This pattern can't accept a variable shift count, since shifts by @@ -10969,7 +10722,7 @@ return "sal{l}\t{%b2, %0|%0, %b2}"; else if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 1 - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)) + && (TARGET_SHIFT1 || optimize_size)) return "sal{l}\t%0"; else return "sal{l}\t{%2, %0|%0, %2}"; @@ -11008,7 +10761,7 @@ return "sal{l}\t{%b2, %k0|%k0, %b2}"; else if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 1 - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)) + && (TARGET_SHIFT1 || optimize_size)) return "sal{l}\t%k0"; else return "sal{l}\t{%2, %k0|%k0, %2}"; @@ -11053,7 +10806,7 @@ return "sal{w}\t{%b2, %0|%0, %b2}"; else if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 1 - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)) + && (TARGET_SHIFT1 || optimize_size)) return "sal{w}\t%0"; else return "sal{w}\t{%2, %0|%0, %2}"; @@ -11091,7 +10844,7 @@ return "sal{w}\t{%b2, %0|%0, %b2}"; else if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 1 - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)) + && (TARGET_SHIFT1 || optimize_size)) return "sal{w}\t%0"; else return "sal{w}\t{%2, %0|%0, %2}"; @@ -11133,7 +10886,7 @@ return "sal{w}\t{%b2, %0|%0, %b2}"; else if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 1 - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)) + && (TARGET_SHIFT1 || optimize_size)) return "sal{w}\t%0"; else return "sal{w}\t{%2, %0|%0, %2}"; @@ -11189,7 +10942,7 @@ } else if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 1 - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)) + && (TARGET_SHIFT1 || optimize_size)) { if (get_attr_mode (insn) == MODE_SI) return "sal{l}\t%0"; @@ -11245,7 +10998,7 @@ } else if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 1 - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)) + && (TARGET_SHIFT1 || optimize_size)) { if (get_attr_mode (insn) == MODE_SI) return "sal{l}\t%0"; @@ -11297,7 +11050,7 @@ return "sal{b}\t{%b2, %0|%0, %b2}"; else if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 1 - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)) + && (TARGET_SHIFT1 || optimize_size)) return "sal{b}\t%0"; else return "sal{b}\t{%2, %0|%0, %2}"; @@ -11353,7 +11106,7 @@ (match_operand:QI 2 "const_int_1_operand" ""))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, DImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "sar{q}\t%0" [(set_attr "type" "ishift") (set (attr "length") @@ -11385,7 +11138,7 @@ (set (match_operand:DI 0 "nonimmediate_operand" "=rm") (ashiftrt:DI (match_dup 1) (match_dup 2)))] "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO) + && (TARGET_SHIFT1 || optimize_size) && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)" "sar{q}\t%0" [(set_attr "type" "ishift") @@ -11542,7 +11295,7 @@ (match_operand:QI 2 "const_int_1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ASHIFTRT, SImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "sar{l}\t%0" [(set_attr "type" "ishift") (set (attr "length") @@ -11556,7 +11309,7 @@ (match_operand:QI 2 "const_int_1_operand" "")))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "sar{l}\t%k0" [(set_attr "type" "ishift") (set_attr "length" "2")]) @@ -11597,7 +11350,7 @@ (set (match_operand:SI 0 "nonimmediate_operand" "=rm") (ashiftrt:SI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO) + && (TARGET_SHIFT1 || optimize_size) && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" "sar{l}\t%0" [(set_attr "type" "ishift") @@ -11615,7 +11368,7 @@ (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, CCmode) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO) + && (TARGET_SHIFT1 || optimize_size) && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" "sar{l}\t%k0" [(set_attr "type" "ishift") @@ -11666,7 +11419,7 @@ (match_operand:QI 2 "const_int_1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ASHIFTRT, HImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "sar{w}\t%0" [(set_attr "type" "ishift") (set (attr "length") @@ -11698,7 +11451,7 @@ (set (match_operand:HI 0 "nonimmediate_operand" "=rm") (ashiftrt:HI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO) + && (TARGET_SHIFT1 || optimize_size) && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)" "sar{w}\t%0" [(set_attr "type" "ishift") @@ -11738,7 +11491,7 @@ (match_operand:QI 2 "const_int_1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ASHIFTRT, QImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "sar{b}\t%0" [(set_attr "type" "ishift") (set (attr "length") @@ -11746,6 +11499,21 @@ (const_string "2") (const_string "*")))]) +(define_insn "*ashrqi3_1_one_bit_slp" + [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) + (ashiftrt:QI (match_dup 0) + (match_operand:QI 1 "const_int_1_operand" ""))) + (clobber (reg:CC 17))] + "ix86_binary_operator_ok (ASHIFTRT, QImode, operands) + && (! TARGET_PARTIAL_REG_STALL || optimize_size) + && (TARGET_SHIFT1 || optimize_size)" + "sar{b}\t%0" + [(set_attr "type" "ishift1") + (set (attr "length") + (if_then_else (match_operand 0 "register_operand" "") + (const_string "2") + (const_string "*")))]) + (define_insn "*ashrqi3_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm") (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") @@ -11758,6 +11526,19 @@ [(set_attr "type" "ishift") (set_attr "mode" "QI")]) +(define_insn "*ashrqi3_1_slp" + [(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))] + "(! TARGET_PARTIAL_REG_STALL || optimize_size) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" + "@ + sar{b}\t{%1, %0|%0, %1} + sar{b}\t{%b1, %0|%0, %b1}" + [(set_attr "type" "ishift1") + (set_attr "mode" "QI")]) + ;; 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. @@ -11770,7 +11551,7 @@ (set (match_operand:QI 0 "nonimmediate_operand" "=qm") (ashiftrt:QI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO) + && (TARGET_SHIFT1 || optimize_size) && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)" "sar{b}\t%0" [(set_attr "type" "ishift") @@ -11822,7 +11603,7 @@ (match_operand:QI 2 "const_int_1_operand" ""))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "shr{q}\t%0" [(set_attr "type" "ishift") (set (attr "length") @@ -11854,7 +11635,7 @@ (set (match_operand:DI 0 "nonimmediate_operand" "=rm") (lshiftrt:DI (match_dup 1) (match_dup 2)))] "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO) + && (TARGET_SHIFT1 || optimize_size) && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "shr{q}\t%0" [(set_attr "type" "ishift") @@ -11932,7 +11713,7 @@ (match_operand:QI 2 "const_int_1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (LSHIFTRT, HImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "shr{l}\t%0" [(set_attr "type" "ishift") (set (attr "length") @@ -11946,7 +11727,7 @@ (match_operand:QI 2 "const_int_1_operand" ""))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "shr{l}\t%k0" [(set_attr "type" "ishift") (set_attr "length" "2")]) @@ -11988,7 +11769,7 @@ (set (match_operand:SI 0 "nonimmediate_operand" "=rm") (lshiftrt:SI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO) + && (TARGET_SHIFT1 || optimize_size) && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "shr{l}\t%0" [(set_attr "type" "ishift") @@ -12006,7 +11787,7 @@ (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) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO) + && (TARGET_SHIFT1 || optimize_size) && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "shr{l}\t%k0" [(set_attr "type" "ishift") @@ -12057,7 +11838,7 @@ (match_operand:QI 2 "const_int_1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (LSHIFTRT, HImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "shr{w}\t%0" [(set_attr "type" "ishift") (set (attr "length") @@ -12089,7 +11870,7 @@ (set (match_operand:HI 0 "nonimmediate_operand" "=rm") (lshiftrt:HI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO) + && (TARGET_SHIFT1 || optimize_size) && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" "shr{w}\t%0" [(set_attr "type" "ishift") @@ -12129,7 +11910,7 @@ (match_operand:QI 2 "const_int_1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (LSHIFTRT, QImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "shr{b}\t%0" [(set_attr "type" "ishift") (set (attr "length") @@ -12137,6 +11918,20 @@ (const_string "2") (const_string "*")))]) +(define_insn "*lshrqi3_1_one_bit_slp" + [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) + (lshiftrt:QI (match_dup 0) + (match_operand:QI 1 "const_int_1_operand" ""))) + (clobber (reg:CC 17))] + "(! TARGET_PARTIAL_REG_STALL || optimize_size) + && (TARGET_SHIFT1 || optimize_size)" + "shr{b}\t%0" + [(set_attr "type" "ishift1") + (set (attr "length") + (if_then_else (match_operand 0 "register_operand" "") + (const_string "2") + (const_string "*")))]) + (define_insn "*lshrqi3_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm") (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") @@ -12149,6 +11944,19 @@ [(set_attr "type" "ishift") (set_attr "mode" "QI")]) +(define_insn "*lshrqi3_1_slp" + [(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))] + "(! TARGET_PARTIAL_REG_STALL || optimize_size) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" + "@ + shr{b}\t{%1, %0|%0, %1} + shr{b}\t{%b1, %0|%0, %b1}" + [(set_attr "type" "ishift1") + (set_attr "mode" "QI")]) + ;; 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. @@ -12161,7 +11969,7 @@ (set (match_operand:QI 0 "nonimmediate_operand" "=qm") (lshiftrt:QI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO) + && (TARGET_SHIFT1 || optimize_size) && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)" "shr{b}\t%0" [(set_attr "type" "ishift") @@ -12203,9 +12011,9 @@ (match_operand:QI 2 "const_int_1_operand" ""))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, DImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "rol{q}\t%0" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") (set (attr "length") (if_then_else (match_operand:DI 0 "register_operand" "") (const_string "2") @@ -12220,7 +12028,7 @@ "@ rol{q}\t{%2, %0|%0, %2} rol{q}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") (set_attr "mode" "DI")]) (define_expand "rotlsi3" @@ -12237,9 +12045,9 @@ (match_operand:QI 2 "const_int_1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ROTATE, SImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "rol{l}\t%0" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") (set (attr "length") (if_then_else (match_operand:SI 0 "register_operand" "") (const_string "2") @@ -12252,9 +12060,9 @@ (match_operand:QI 2 "const_int_1_operand" "")))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, SImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "rol{l}\t%k0" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") (set_attr "length" "2")]) (define_insn "*rotlsi3_1" @@ -12266,7 +12074,7 @@ "@ rol{l}\t{%2, %0|%0, %2} rol{l}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") (set_attr "mode" "SI")]) (define_insn "*rotlsi3_1_zext" @@ -12279,7 +12087,7 @@ "@ rol{l}\t{%2, %k0|%k0, %2} rol{l}\t{%b2, %k0|%k0, %b2}" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") (set_attr "mode" "SI")]) (define_expand "rotlhi3" @@ -12296,9 +12104,9 @@ (match_operand:QI 2 "const_int_1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ROTATE, HImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "rol{w}\t%0" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") (set (attr "length") (if_then_else (match_operand 0 "register_operand" "") (const_string "2") @@ -12313,7 +12121,7 @@ "@ rol{w}\t{%2, %0|%0, %2} rol{w}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") (set_attr "mode" "HI")]) (define_expand "rotlqi3" @@ -12324,20 +12132,47 @@ "TARGET_QIMODE_MATH" "ix86_expand_binary_operator (ROTATE, QImode, operands); DONE;") +(define_insn "*rotlqi3_1_one_bit_slp" + [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) + (rotate:QI (match_dup 0) + (match_operand:QI 1 "const_int_1_operand" ""))) + (clobber (reg:CC 17))] + "(! TARGET_PARTIAL_REG_STALL || optimize_size) + && (TARGET_SHIFT1 || optimize_size)" + "rol{b}\t%0" + [(set_attr "type" "rotate1") + (set (attr "length") + (if_then_else (match_operand 0 "register_operand" "") + (const_string "2") + (const_string "*")))]) + (define_insn "*rotlqi3_1_one_bit" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") (rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "const_int_1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ROTATE, QImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "rol{b}\t%0" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") (set (attr "length") (if_then_else (match_operand 0 "register_operand" "") (const_string "2") (const_string "*")))]) +(define_insn "*rotlqi3_1_slp" + [(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))] + "(! TARGET_PARTIAL_REG_STALL || optimize_size) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" + "@ + rol{b}\t{%1, %0|%0, %1} + rol{b}\t{%b1, %0|%0, %b1}" + [(set_attr "type" "rotate1") + (set_attr "mode" "QI")]) + (define_insn "*rotlqi3_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm") (rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") @@ -12347,7 +12182,7 @@ "@ rol{b}\t{%2, %0|%0, %2} rol{b}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") (set_attr "mode" "QI")]) (define_expand "rotrdi3" @@ -12364,9 +12199,9 @@ (match_operand:QI 2 "const_int_1_operand" ""))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, DImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "ror{q}\t%0" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") (set (attr "length") (if_then_else (match_operand:DI 0 "register_operand" "") (const_string "2") @@ -12381,7 +12216,7 @@ "@ ror{q}\t{%2, %0|%0, %2} ror{q}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") (set_attr "mode" "DI")]) (define_expand "rotrsi3" @@ -12398,9 +12233,9 @@ (match_operand:QI 2 "const_int_1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ROTATERT, SImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "ror{l}\t%0" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") (set (attr "length") (if_then_else (match_operand:SI 0 "register_operand" "") (const_string "2") @@ -12413,9 +12248,9 @@ (match_operand:QI 2 "const_int_1_operand" "")))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, SImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "ror{l}\t%k0" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") (set (attr "length") (if_then_else (match_operand:SI 0 "register_operand" "") (const_string "2") @@ -12430,7 +12265,7 @@ "@ ror{l}\t{%2, %0|%0, %2} ror{l}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") (set_attr "mode" "SI")]) (define_insn "*rotrsi3_1_zext" @@ -12443,7 +12278,7 @@ "@ ror{l}\t{%2, %k0|%k0, %2} ror{l}\t{%b2, %k0|%k0, %b2}" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") (set_attr "mode" "SI")]) (define_expand "rotrhi3" @@ -12460,9 +12295,9 @@ (match_operand:QI 2 "const_int_1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ROTATERT, HImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "ror{w}\t%0" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") (set (attr "length") (if_then_else (match_operand 0 "register_operand" "") (const_string "2") @@ -12477,7 +12312,7 @@ "@ ror{w}\t{%2, %0|%0, %2} ror{w}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") (set_attr "mode" "HI")]) (define_expand "rotrqi3" @@ -12494,9 +12329,23 @@ (match_operand:QI 2 "const_int_1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ROTATERT, QImode, operands) - && (TARGET_PENTIUM || TARGET_PENTIUMPRO)" + && (TARGET_SHIFT1 || optimize_size)" "ror{b}\t%0" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") + (set (attr "length") + (if_then_else (match_operand 0 "register_operand" "") + (const_string "2") + (const_string "*")))]) + +(define_insn "*rotrqi3_1_one_bit_slp" + [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) + (rotatert:QI (match_dup 0) + (match_operand:QI 1 "const_int_1_operand" ""))) + (clobber (reg:CC 17))] + "(! TARGET_PARTIAL_REG_STALL || optimize_size) + && (TARGET_SHIFT1 || optimize_size)" + "ror{b}\t%0" + [(set_attr "type" "rotate1") (set (attr "length") (if_then_else (match_operand 0 "register_operand" "") (const_string "2") @@ -12511,7 +12360,20 @@ "@ ror{b}\t{%2, %0|%0, %2} ror{b}\t{%b2, %0|%0, %b2}" - [(set_attr "type" "ishift") + [(set_attr "type" "rotate") + (set_attr "mode" "QI")]) + +(define_insn "*rotrqi3_1_slp" + [(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))] + "(! TARGET_PARTIAL_REG_STALL || optimize_size) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" + "@ + ror{b}\t{%1, %0|%0, %1} + ror{b}\t{%b1, %0|%0, %b1}" + [(set_attr "type" "rotate1") (set_attr "mode" "QI")]) ;; Bit set / bit test instructions @@ -12789,7 +12651,7 @@ (match_operand:SF 3 "nonimmediate_operand" "xm")]))] "TARGET_SSE && reload_completed" "cmp%D1ss\t{%3, %0|%0, %3}" - [(set_attr "type" "sse") + [(set_attr "type" "ssecmp") (set_attr "mode" "SF")]) (define_insn "*sse_setccdf" @@ -12799,7 +12661,7 @@ (match_operand:DF 3 "nonimmediate_operand" "Ym")]))] "TARGET_SSE2 && reload_completed" "cmp%D1sd\t{%3, %0|%0, %3}" - [(set_attr "type" "sse") + [(set_attr "type" "ssecmp") (set_attr "mode" "DF")]) ;; Basic conditional jump instructions. @@ -12961,13 +12823,14 @@ "" "%+j%C1\t%l0" [(set_attr "type" "ibr") - (set (attr "prefix_0f") + (set_attr "modrm" "0") + (set (attr "length") (if_then_else (and (ge (minus (match_dup 0) (pc)) - (const_int -128)) + (const_int -126)) (lt (minus (match_dup 0) (pc)) - (const_int 124))) - (const_int 0) - (const_int 1)))]) + (const_int 128))) + (const_int 2) + (const_int 6)))]) (define_insn "*jcc_2" [(set (pc) @@ -12978,13 +12841,14 @@ "" "%+j%c1\t%l0" [(set_attr "type" "ibr") - (set (attr "prefix_0f") + (set_attr "modrm" "0") + (set (attr "length") (if_then_else (and (ge (minus (match_dup 0) (pc)) - (const_int -128)) + (const_int -126)) (lt (minus (match_dup 0) (pc)) - (const_int 124))) - (const_int 0) - (const_int 1)))]) + (const_int 128))) + (const_int 2) + (const_int 6)))]) ;; In general it is not safe to assume too much about CCmode registers, ;; so simplify-rtx stops when it sees a second one. Under certain @@ -13244,7 +13108,15 @@ (label_ref (match_operand 0 "" "")))] "" "jmp\t%l0" - [(set_attr "type" "ibr")]) + [(set_attr "type" "ibr") + (set (attr "length") + (if_then_else (and (ge (minus (match_dup 0) (pc)) + (const_int -126)) + (lt (minus (match_dup 0) (pc)) + (const_int 128))) + (const_int 2) + (const_int 5))) + (set_attr "modrm" "0")]) (define_expand "indirect_jump" [(set (pc) (match_operand 0 "nonimmediate_operand" "rm"))] @@ -13270,29 +13142,34 @@ (use (label_ref (match_operand 1 "" "")))])] "" { - /* In PIC mode, the table entries are stored GOT-relative. Convert - the relative address to an absolute address. */ + /* In PIC mode, the table entries are stored GOT (32-bit) or PC (64-bit) + relative. Convert the relative address to an absolute address. */ if (flag_pic) { + rtx op0, op1; + enum rtx_code code; + if (TARGET_64BIT) - operands[0] = expand_simple_binop (Pmode, PLUS, operands[0], - gen_rtx_LABEL_REF (Pmode, operands[1]), - NULL_RTX, 0, - OPTAB_DIRECT); - else if (HAVE_AS_GOTOFF_IN_DATA) { - operands[0] = expand_simple_binop (Pmode, PLUS, operands[0], - pic_offset_table_rtx, NULL_RTX, - 1, OPTAB_DIRECT); - current_function_uses_pic_offset_table = 1; + code = PLUS; + op0 = operands[0]; + op1 = gen_rtx_LABEL_REF (Pmode, operands[1]); + } + else if (TARGET_MACHO || HAVE_AS_GOTOFF_IN_DATA) + { + code = PLUS; + op0 = operands[0]; + op1 = pic_offset_table_rtx; } else { - operands[0] = expand_simple_binop (Pmode, MINUS, pic_offset_table_rtx, - operands[0], NULL_RTX, 1, - OPTAB_DIRECT); - current_function_uses_pic_offset_table = 1; + code = MINUS; + op0 = pic_offset_table_rtx; + op1 = operands[0]; } + + operands[0] = expand_simple_binop (Pmode, code, op0, op1, NULL_RTX, 0, + OPTAB_DIRECT); } }) @@ -13357,14 +13234,17 @@ return "dec{l}\t%1\;%+jne\t%l0"; } [(set_attr "ppro_uops" "many") - (set (attr "type") + (set (attr "length") (if_then_else (and (eq_attr "alternative" "0") (and (ge (minus (match_dup 0) (pc)) - (const_int -128)) + (const_int -126)) (lt (minus (match_dup 0) (pc)) - (const_int 124)))) - (const_string "ibr") - (const_string "multi")))]) + (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) @@ -13474,21 +13354,8 @@ (match_operand:SI 3 "" "")))])] "!TARGET_64BIT" { - if (operands[3] == const0_rtx) - { - emit_insn (gen_call (operands[0], operands[1], constm1_rtx)); - DONE; - } - /* Static functions and indirect calls don't need - current_function_uses_pic_offset_table. */ - if (flag_pic - && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF - && ! SYMBOL_REF_FLAG (XEXP (operands[0], 0))) - current_function_uses_pic_offset_table = 1; - if (! call_insn_operand (XEXP (operands[0], 0), Pmode)) - XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); - if (TARGET_64BIT) - abort(); + ix86_expand_call (NULL, operands[0], operands[1], operands[2], operands[3]); + DONE; }) (define_insn "*call_pop_0" @@ -13530,37 +13397,12 @@ [(call (match_operand:QI 0 "" "") (match_operand 1 "" "")) (use (match_operand 2 "" ""))] - ;; Operand 1 not used on the i386. "" { - rtx insn; - /* Static functions and indirect calls don't need - current_function_uses_pic_offset_table. */ - if (flag_pic - && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF - && ! SYMBOL_REF_FLAG (XEXP (operands[0], 0))) - current_function_uses_pic_offset_table = 1; - - if (! call_insn_operand (XEXP (operands[0], 0), Pmode)) - XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); - if (TARGET_64BIT && INTVAL (operands[2]) >= 0) - { - rtx reg = gen_rtx_REG (QImode, 0); - emit_move_insn (reg, operands[2]); - insn = emit_call_insn (gen_call_exp (operands[0], operands[1])); - use_reg (&CALL_INSN_FUNCTION_USAGE (insn), reg); - DONE; - } - insn = emit_call_insn (gen_call_exp (operands[0], operands[1])); - DONE; + ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL); + DONE; }) -(define_expand "call_exp" - [(call (match_operand:QI 0 "" "") - (match_operand 1 "" ""))] - "" - "") - (define_insn "*call_0" [(call (mem:QI (match_operand 0 "constant_call_address_operand" "")) (match_operand 1 "" ""))] @@ -13612,7 +13454,6 @@ [(set_attr "type" "call")]) ;; Call subroutine, returning value in operand 0 -;; (which must be a hard register). (define_expand "call_value_pop" [(parallel [(set (match_operand 0 "" "") @@ -13623,20 +13464,9 @@ (match_operand:SI 4 "" "")))])] "!TARGET_64BIT" { - if (operands[4] == const0_rtx) - { - emit_insn (gen_call_value (operands[0], operands[1], operands[2], - constm1_rtx)); - DONE; - } - /* Static functions and indirect calls don't need - current_function_uses_pic_offset_table. */ - if (flag_pic - && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF - && ! SYMBOL_REF_FLAG (XEXP (operands[1], 0))) - current_function_uses_pic_offset_table = 1; - if (! call_insn_operand (XEXP (operands[1], 0), Pmode)) - XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); + ix86_expand_call (operands[0], operands[1], operands[2], + operands[3], operands[4]); + DONE; }) (define_expand "call_value" @@ -13647,36 +13477,10 @@ ;; Operand 2 not used on the i386. "" { - rtx insn; - /* Static functions and indirect calls don't need - current_function_uses_pic_offset_table. */ - if (flag_pic - && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF - && ! SYMBOL_REF_FLAG (XEXP (operands[1], 0))) - current_function_uses_pic_offset_table = 1; - if (! call_insn_operand (XEXP (operands[1], 0), Pmode)) - XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); - if (TARGET_64BIT && INTVAL (operands[3]) >= 0) - { - rtx reg = gen_rtx_REG (QImode, 0); - emit_move_insn (reg, operands[3]); - insn = emit_call_insn (gen_call_value_exp (operands[0], operands[1], - operands[2])); - use_reg (&CALL_INSN_FUNCTION_USAGE (insn), reg); - DONE; - } - insn = emit_call_insn (gen_call_value_exp (operands[0], operands[1], - operands[2])); + ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL); DONE; }) -(define_expand "call_value_exp" - [(set (match_operand 0 "" "") - (call (match_operand:QI 1 "" "") - (match_operand:SI 2 "" "")))] - "" - "") - ;; Call subroutine returning any type. (define_expand "untyped_call" @@ -13693,12 +13497,10 @@ simply pretend the untyped call returns a complex long double value. */ - emit_call_insn (TARGET_FLOAT_RETURNS_IN_80387 - ? gen_call_value (gen_rtx_REG (XCmode, FIRST_FLOAT_REG), - operands[0], const0_rtx, - GEN_INT (SSE_REGPARM_MAX - 1)) - : gen_call (operands[0], const0_rtx, - GEN_INT (SSE_REGPARM_MAX - 1))); + ix86_expand_call ((TARGET_FLOAT_RETURNS_IN_80387 + ? gen_rtx_REG (XCmode, FIRST_FLOAT_REG) : NULL), + operands[0], const0_rtx, GEN_INT (SSE_REGPARM_MAX - 1), + NULL); for (i = 0; i < XVECLEN (operands[2], 0); i++) { @@ -13710,7 +13512,7 @@ registers we stored in the result block. We avoid problems by claiming that all hard registers are used and clobbered at this point. */ - emit_insn (gen_blockage ()); + emit_insn (gen_blockage (const0_rtx)); DONE; }) @@ -13721,7 +13523,7 @@ ;; all of memory. This blocks insns from being moved across this point. (define_insn "blockage" - [(unspec_volatile [(const_int 0)] 0)] + [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_BLOCKAGE)] "" "" [(set_attr "length" "0")]) @@ -13781,45 +13583,14 @@ "" "ix86_expand_prologue (); DONE;") -(define_insn "prologue_set_got" +(define_insn "set_got" [(set (match_operand:SI 0 "register_operand" "=r") - (unspec_volatile:SI - [(plus:SI (match_dup 0) - (plus:SI (match_operand:SI 1 "symbolic_operand" "") - (minus:SI (pc) (match_operand 2 "" ""))))] 1)) + (unspec:SI [(const_int 0)] UNSPEC_SET_GOT)) (clobber (reg:CC 17))] "!TARGET_64BIT" -{ - if (GET_CODE (operands[2]) == LABEL_REF) - operands[2] = XEXP (operands[2], 0); - if (TARGET_DEEP_BRANCH_PREDICTION) - return "add{l}\t{%1, %0|%0, %1}"; - else - return "add{l}\t{%1+[.-%X2], %0|%0, %a1+(.-%X2)}"; -} - [(set_attr "type" "alu") - ; Since this insn may have two constant operands, we must set the - ; length manually. - (set_attr "length_immediate" "4") - (set_attr "mode" "SI")]) - -(define_insn "prologue_get_pc" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec_volatile:SI [(plus:SI (pc) (match_operand 1 "" ""))] 2))] - "!TARGET_64BIT" -{ - if (GET_CODE (operands[1]) == LABEL_REF) - operands[1] = XEXP (operands[1], 0); - output_asm_insn ("call\t%X1", operands); - if (! TARGET_DEEP_BRANCH_PREDICTION) - { - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", - CODE_LABEL_NUMBER (operands[1])); - return "pop{l}\t%0"; - } - RET; -} - [(set_attr "type" "multi")]) + { return output_set_got (operands[0]); } + [(set_attr "type" "multi") + (set_attr "length" "12")]) (define_expand "epilogue" [(const_int 1)] @@ -13832,11 +13603,10 @@ "ix86_expand_epilogue (0); DONE;") (define_expand "eh_return" - [(use (match_operand 0 "register_operand" "")) - (use (match_operand 1 "register_operand" ""))] + [(use (match_operand 0 "register_operand" ""))] "" { - rtx tmp, sa = operands[0], ra = operands[1]; + rtx tmp, sa = EH_RETURN_STACKADJ_RTX, ra = operands[0]; /* Tricky bit: we write the address of the handler to which we will be returning into someone else's stack frame, one word below the @@ -13855,7 +13625,8 @@ }) (define_insn_and_split "eh_return_si" - [(unspec_volatile [(match_operand:SI 0 "register_operand" "c")] 13)] + [(unspec_volatile [(match_operand:SI 0 "register_operand" "c")] + UNSPECV_EH_RETURN)] "!TARGET_64BIT" "#" "reload_completed" @@ -13863,7 +13634,8 @@ "ix86_expand_epilogue (2); DONE;") (define_insn_and_split "eh_return_di" - [(unspec_volatile [(match_operand:DI 0 "register_operand" "c")] 13)] + [(unspec_volatile [(match_operand:DI 0 "register_operand" "c")] + UNSPECV_EH_RETURN)] "TARGET_64BIT" "#" "reload_completed" @@ -13879,7 +13651,6 @@ [(set_attr "length_immediate" "0") (set_attr "length" "1") (set_attr "modrm" "0") - (set_attr "modrm" "0") (set_attr "athlon_decode" "vector") (set_attr "ppro_uops" "few")]) @@ -13892,13 +13663,12 @@ [(set_attr "length_immediate" "0") (set_attr "length" "1") (set_attr "modrm" "0") - (set_attr "modrm" "0") (set_attr "athlon_decode" "vector") (set_attr "ppro_uops" "few")]) (define_expand "ffssi2" [(set (match_operand:SI 0 "nonimmediate_operand" "") - (ffs:SI (match_operand:SI 1 "general_operand" "")))] + (ffs:SI (match_operand:SI 1 "nonimmediate_operand" "")))] "" { rtx out = gen_reg_rtx (SImode), tmp = gen_reg_rtx (SImode); @@ -13987,7 +13757,7 @@ (compare:CCZ (match_operand:SI 1 "nonimmediate_operand" "rm") (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(match_dup 1)] 5))] + (unspec:SI [(match_dup 1)] UNSPEC_BSF))] "" "bsf{l}\t{%1, %0|%0, %1}" [(set_attr "prefix_0f" "1") @@ -13996,6 +13766,173 @@ ;; ffshi2 is not useful -- 4 word prefix ops are needed, which is larger ;; and slower than the two-byte movzx insn needed to do the work in SImode. +;; Thread-local storage patterns for ELF. +;; +;; Note that these code sequences must appear exactly as shown +;; in order to allow linker relaxation. + +(define_insn "*tls_global_dynamic_32_gnu" + [(set (match_operand:SI 0 "register_operand" "=a") + (unspec:SI [(match_operand:SI 1 "register_operand" "b") + (match_operand:SI 2 "tls_symbolic_operand" "") + (match_operand:SI 3 "call_insn_operand" "")] + UNSPEC_TLS_GD)) + (clobber (match_scratch:SI 4 "=d")) + (clobber (match_scratch:SI 5 "=c")) + (clobber (reg:CC 17))] + "!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") + (set_attr "length" "12")]) + +(define_insn "*tls_global_dynamic_32_sun" + [(set (match_operand:SI 0 "register_operand" "=a") + (unspec:SI [(match_operand:SI 1 "register_operand" "b") + (match_operand:SI 2 "tls_symbolic_operand" "") + (match_operand:SI 3 "call_insn_operand" "")] + UNSPEC_TLS_GD)) + (clobber (match_scratch:SI 4 "=d")) + (clobber (match_scratch:SI 5 "=c")) + (clobber (reg:CC 17))] + "!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" + [(set_attr "type" "multi") + (set_attr "length" "14")]) + +(define_expand "tls_global_dynamic_32" + [(parallel [(set (match_operand:SI 0 "register_operand" "") + (unspec:SI + [(match_dup 2) + (match_operand:SI 1 "tls_symbolic_operand" "") + (match_dup 3)] + UNSPEC_TLS_GD)) + (clobber (match_scratch:SI 4 "")) + (clobber (match_scratch:SI 5 "")) + (clobber (reg:CC 17))])] + "" +{ + if (flag_pic) + operands[2] = pic_offset_table_rtx; + else + { + operands[2] = gen_reg_rtx (Pmode); + emit_insn (gen_set_got (operands[2])); + } + 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 "" ""))) + (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] + UNSPEC_TLS_GD)] + "TARGET_64BIT" + ".byte\t0x66\;lea{q}\t{%a1@TLSGD(%%rip), %%rdi|%%rdi, %a1@TLSGD[%%rip]}\;.word\t0x6666\;rex64\;call\t%P2" + [(set_attr "type" "multi") + (set_attr "length" "16")]) + +(define_expand "tls_global_dynamic_64" + [(parallel [(set (match_operand:DI 0 "register_operand" "") + (call (mem:QI (match_dup 2)) (const_int 0))) + (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] + UNSPEC_TLS_GD)])] + "" +{ + operands[2] = ix86_tls_get_addr (); +}) + +(define_insn "*tls_local_dynamic_base_32_gnu" + [(set (match_operand:SI 0 "register_operand" "=a") + (unspec:SI [(match_operand:SI 1 "register_operand" "b") + (match_operand:SI 2 "call_insn_operand" "")] + UNSPEC_TLS_LD_BASE)) + (clobber (match_scratch:SI 3 "=d")) + (clobber (match_scratch:SI 4 "=c")) + (clobber (reg:CC 17))] + "!TARGET_64BIT && TARGET_GNU_TLS" + "lea{l}\t{%&@TLSLDM(%1), %0|%0, %&@TLSLDM[%1]}\;call\t%P2" + [(set_attr "type" "multi") + (set_attr "length" "11")]) + +(define_insn "*tls_local_dynamic_base_32_sun" + [(set (match_operand:SI 0 "register_operand" "=a") + (unspec:SI [(match_operand:SI 1 "register_operand" "b") + (match_operand:SI 2 "call_insn_operand" "")] + UNSPEC_TLS_LD_BASE)) + (clobber (match_scratch:SI 3 "=d")) + (clobber (match_scratch:SI 4 "=c")) + (clobber (reg:CC 17))] + "!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" + [(set_attr "type" "multi") + (set_attr "length" "13")]) + +(define_expand "tls_local_dynamic_base_32" + [(parallel [(set (match_operand:SI 0 "register_operand" "") + (unspec:SI [(match_dup 1) (match_dup 2)] + UNSPEC_TLS_LD_BASE)) + (clobber (match_scratch:SI 3 "")) + (clobber (match_scratch:SI 4 "")) + (clobber (reg:CC 17))])] + "" +{ + if (flag_pic) + operands[1] = pic_offset_table_rtx; + else + { + operands[1] = gen_reg_rtx (Pmode); + emit_insn (gen_set_got (operands[1])); + } + 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 "" ""))) + (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)] + "TARGET_64BIT" + "lea{q}\t{%&@TLSLD(%%rip), %%rdi|%%rdi, %&@TLSLD[%%rip]}\;call\t%P1" + [(set_attr "type" "multi") + (set_attr "length" "12")]) + +(define_expand "tls_local_dynamic_base_64" + [(parallel [(set (match_operand:DI 0 "register_operand" "") + (call (mem:QI (match_dup 1)) (const_int 0))) + (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])] + "" +{ + operands[1] = ix86_tls_get_addr (); +}) + +;; Local dynamic of a single variable is a lose. Show combine how +;; to convert that back to global dynamic. + +(define_insn_and_split "*tls_local_dynamic_32_once" + [(set (match_operand:SI 0 "register_operand" "=a") + (plus:SI (unspec:SI [(match_operand:SI 1 "register_operand" "b") + (match_operand:SI 2 "call_insn_operand" "")] + UNSPEC_TLS_LD_BASE) + (const:SI (unspec:SI + [(match_operand:SI 3 "tls_symbolic_operand" "")] + UNSPEC_DTPOFF)))) + (clobber (match_scratch:SI 4 "=d")) + (clobber (match_scratch:SI 5 "=c")) + (clobber (reg:CC 17))] + "" + "#" + "" + [(parallel [(set (match_dup 0) + (unspec:SI [(match_dup 1) (match_dup 3) (match_dup 2)] + UNSPEC_TLS_GD)) + (clobber (match_dup 4)) + (clobber (match_dup 5)) + (clobber (reg:CC 17))])] + "") + ;; These patterns match the binary 387 instructions for addM3, subM3, ;; mulM3 and divM3. There are three patterns for each of DFmode and ;; SFmode. The first is the normal insn, the second the same insn but @@ -14032,7 +13969,9 @@ "* return output_387_binary_op (insn, operands);" [(set (attr "type") (if_then_else (eq_attr "alternative" "1") - (const_string "sse") + (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")))) @@ -14046,7 +13985,10 @@ "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" "sse") + [(set (attr "type") + (if_then_else (match_operand:SF 3 "mult_operator" "") + (const_string "ssemul") + (const_string "sseadd"))) (set_attr "mode" "SF")]) (define_insn "*fop_df_comm_nosse" @@ -14075,7 +14017,9 @@ "* return output_387_binary_op (insn, operands);" [(set (attr "type") (if_then_else (eq_attr "alternative" "1") - (const_string "sse") + (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")))) @@ -14090,7 +14034,10 @@ && 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" "sse") + [(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" @@ -14148,8 +14095,14 @@ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "* return output_387_binary_op (insn, operands);" [(set (attr "type") - (cond [(eq_attr "alternative" "2") - (const_string "sse") + (cond [(and (eq_attr "alternative" "2") + (match_operand:SF 3 "mult_operator" "")) + (const_string "ssemul") + (and (eq_attr "alternative" "2") + (match_operand:SF 3 "div_operator" "")) + (const_string "ssediv") + (eq_attr "alternative" "2") + (const_string "sseadd") (match_operand:SF 3 "mult_operator" "") (const_string "fmul") (match_operand:SF 3 "div_operator" "") @@ -14166,7 +14119,13 @@ "TARGET_SSE_MATH && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'" "* return output_387_binary_op (insn, operands);" - [(set_attr "type" "sse") + [(set (attr "type") + (cond [(match_operand:SF 3 "mult_operator" "") + (const_string "ssemul") + (match_operand:SF 3 "div_operator" "") + (const_string "ssediv") + ] + (const_string "sseadd"))) (set_attr "mode" "SF")]) ;; ??? Add SSE splitters for these! @@ -14218,7 +14177,7 @@ [(set (attr "type") (cond [(match_operand:DF 3 "mult_operator" "") (const_string "fmul") - (match_operand:DF 3 "div_operator" "") + (match_operand:DF 3 "div_operator" "") (const_string "fdiv") ] (const_string "fop"))) @@ -14235,8 +14194,14 @@ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "* return output_387_binary_op (insn, operands);" [(set (attr "type") - (cond [(eq_attr "alternative" "2") - (const_string "sse") + (cond [(and (eq_attr "alternative" "2") + (match_operand:SF 3 "mult_operator" "")) + (const_string "ssemul") + (and (eq_attr "alternative" "2") + (match_operand:SF 3 "div_operator" "")) + (const_string "ssediv") + (eq_attr "alternative" "2") + (const_string "sseadd") (match_operand:DF 3 "mult_operator" "") (const_string "fmul") (match_operand:DF 3 "div_operator" "") @@ -14253,7 +14218,14 @@ "TARGET_SSE2 && TARGET_SSE_MATH && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'" "* return output_387_binary_op (insn, operands);" - [(set_attr "type" "sse")]) + [(set_attr "mode" "DF") + (set (attr "type") + (cond [(match_operand:SF 3 "mult_operator" "") + (const_string "ssemul") + (match_operand:SF 3 "div_operator" "") + (const_string "ssediv") + ] + (const_string "sseadd")))]) ;; ??? Add SSE splitters for these! (define_insn "*fop_df_2" @@ -14760,7 +14732,7 @@ (define_insn "sindf2" [(set (match_operand:DF 0 "register_operand" "=f") - (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))] + (unspec:DF [(match_operand:DF 1 "register_operand" "0")] UNSPEC_SIN))] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" "fsin" @@ -14769,7 +14741,7 @@ (define_insn "sinsf2" [(set (match_operand:SF 0 "register_operand" "=f") - (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))] + (unspec:SF [(match_operand:SF 1 "register_operand" "0")] UNSPEC_SIN))] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" "fsin" @@ -14779,7 +14751,8 @@ (define_insn "*sinextendsfdf2" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(float_extend:DF - (match_operand:SF 1 "register_operand" "0"))] 1))] + (match_operand:SF 1 "register_operand" "0"))] + UNSPEC_SIN))] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" "fsin" @@ -14788,7 +14761,7 @@ (define_insn "sinxf2" [(set (match_operand:XF 0 "register_operand" "=f") - (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 1))] + (unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_SIN))] "!TARGET_64BIT && TARGET_80387 && !TARGET_NO_FANCY_MATH_387 && flag_unsafe_math_optimizations" "fsin" @@ -14797,7 +14770,7 @@ (define_insn "sintf2" [(set (match_operand:TF 0 "register_operand" "=f") - (unspec:TF [(match_operand:TF 1 "register_operand" "0")] 1))] + (unspec:TF [(match_operand:TF 1 "register_operand" "0")] UNSPEC_SIN))] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" "fsin" @@ -14806,7 +14779,7 @@ (define_insn "cosdf2" [(set (match_operand:DF 0 "register_operand" "=f") - (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))] + (unspec:DF [(match_operand:DF 1 "register_operand" "0")] UNSPEC_COS))] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" "fcos" @@ -14815,7 +14788,7 @@ (define_insn "cossf2" [(set (match_operand:SF 0 "register_operand" "=f") - (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))] + (unspec:SF [(match_operand:SF 1 "register_operand" "0")] UNSPEC_COS))] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" "fcos" @@ -14825,7 +14798,8 @@ (define_insn "*cosextendsfdf2" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(float_extend:DF - (match_operand:SF 1 "register_operand" "0"))] 2))] + (match_operand:SF 1 "register_operand" "0"))] + UNSPEC_COS))] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" "fcos" @@ -14834,8 +14808,8 @@ (define_insn "cosxf2" [(set (match_operand:XF 0 "register_operand" "=f") - (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 2))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + (unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_COS))] + "!TARGET_64BIT && ! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" "fcos" [(set_attr "type" "fpspc") @@ -14843,7 +14817,7 @@ (define_insn "costf2" [(set (match_operand:TF 0 "register_operand" "=f") - (unspec:TF [(match_operand:TF 1 "register_operand" "0")] 2))] + (unspec:TF [(match_operand:TF 1 "register_operand" "0")] UNSPEC_COS))] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" "fcos" @@ -15737,7 +15711,7 @@ [(set (match_operand:SI 0 "register_operand" "") (unspec:SI [(match_operand:BLK 1 "general_operand" "") (match_operand:QI 2 "immediate_operand" "") - (match_operand 3 "immediate_operand" "")] 0))] + (match_operand 3 "immediate_operand" "")] UNSPEC_SCAS))] "" { if (ix86_expand_strlen (operands[0], operands[1], operands[2], operands[3])) @@ -15750,7 +15724,7 @@ [(set (match_operand:DI 0 "register_operand" "") (unspec:DI [(match_operand:BLK 1 "general_operand" "") (match_operand:QI 2 "immediate_operand" "") - (match_operand 3 "immediate_operand" "")] 0))] + (match_operand 3 "immediate_operand" "")] UNSPEC_SCAS))] "" { if (ix86_expand_strlen (operands[0], operands[1], operands[2], operands[3])) @@ -15764,7 +15738,7 @@ (unspec:SI [(mem:BLK (match_operand:SI 5 "register_operand" "1")) (match_operand:QI 2 "register_operand" "a") (match_operand:SI 3 "immediate_operand" "i") - (match_operand:SI 4 "register_operand" "0")] 0)) + (match_operand:SI 4 "register_operand" "0")] UNSPEC_SCAS)) (use (reg:SI 19)) (clobber (match_operand:SI 1 "register_operand" "=D")) (clobber (reg:CC 17))] @@ -15779,7 +15753,7 @@ (unspec:DI [(mem:BLK (match_operand:DI 5 "register_operand" "1")) (match_operand:QI 2 "register_operand" "a") (match_operand:DI 3 "immediate_operand" "i") - (match_operand:DI 4 "register_operand" "0")] 0)) + (match_operand:DI 4 "register_operand" "0")] UNSPEC_SCAS)) (use (reg:SI 19)) (clobber (match_operand:DI 1 "register_operand" "=D")) (clobber (reg:CC 17))] @@ -15895,6 +15869,7 @@ ; Since we don't have the proper number of operands for an alu insn, ; fill in all the blanks. [(set_attr "type" "alu") + (set_attr "pent_pair" "pu") (set_attr "memory" "none") (set_attr "imm_disp" "false") (set_attr "mode" "DI") @@ -15937,6 +15912,7 @@ ; Since we don't have the proper number of operands for an alu insn, ; fill in all the blanks. [(set_attr "type" "alu") + (set_attr "pent_pair" "pu") (set_attr "memory" "none") (set_attr "imm_disp" "false") (set_attr "mode" "SI") @@ -16043,12 +16019,12 @@ (set_attr "mode" "DF")]) (define_split - [(set (match_operand:DF 0 "register_operand" "") + [(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 "" "") (const_int 0)]) (match_operand:DF 2 "nonimmediate_operand" "") (match_operand:DF 3 "nonimmediate_operand" "")))] - "!TARGET_64BIT && !ANY_FP_REG_P (operands[0]) && reload_completed" + "!TARGET_64BIT && reload_completed" [(set (match_dup 2) (if_then_else:SI (match_op_dup 1 [(match_dup 4) (const_int 0)]) (match_dup 5) @@ -16156,13 +16132,13 @@ ;; We can't represent the LT test directly. Do this by swapping the operands. (define_split - [(set (match_operand:SF 0 "register_operand" "") + [(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))] - "FP_REG_P (operands[0]) && reload_completed + "reload_completed && ((operands_match_p (operands[1], operands[3]) && operands_match_p (operands[2], operands[4])) || (operands_match_p (operands[1], operands[4]) @@ -16238,13 +16214,13 @@ ;; We can't represent the LT test directly. Do this by swapping the operands. (define_split - [(set (match_operand:DF 0 "register_operand" "") + [(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))] - "FP_REG_P (operands[0]) && reload_completed + "reload_completed && ((operands_match_p (operands[1], operands[3]) && operands_match_p (operands[2], operands[4])) || (operands_match_p (operands[1], operands[4]) @@ -16319,13 +16295,13 @@ (match_dup 2)))]) (define_split - [(set (match_operand:SF 0 "register_operand" "") + [(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))] - "FP_REG_P (operands[0]) && reload_completed + "reload_completed && ((operands_match_p (operands[1], operands[3]) && operands_match_p (operands[2], operands[4])) || (operands_match_p (operands[1], operands[4]) @@ -16400,13 +16376,13 @@ (match_dup 2)))]) (define_split - [(set (match_operand:DF 0 "register_operand" "") + [(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))] - "FP_REG_P (operands[0]) && reload_completed + "reload_completed && ((operands_match_p (operands[1], operands[3]) && operands_match_p (operands[2], operands[4])) || (operands_match_p (operands[1], operands[4]) @@ -16628,7 +16604,7 @@ ;; 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 non-zero one into the result. +;; or op2, op0 - get the nonzero one into the result. (define_split [(set (match_operand 0 "register_operand" "") (if_then_else (match_operator 1 "sse_comparison_operator" @@ -16744,7 +16720,7 @@ (define_split [(set (match_operand 0 "register_operand" "") (if_then_else (match_operator 1 "comparison_operator" - [(match_operand 4 "register_operand" "") + [(match_operand 4 "nonimmediate_operand" "") (match_operand 5 "nonimmediate_operand" "")]) (match_operand 2 "nonmemory_operand" "") (match_operand 3 "nonmemory_operand" "")))] @@ -16756,13 +16732,16 @@ (subreg:TI (match_dup 7) 0)))] { PUT_MODE (operands[1], GET_MODE (operands[0])); - if (!sse_comparison_operator (operands[1], VOIDmode)) + 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 (); if (const0_operand (operands[2], GET_MODE (operands[0]))) { operands[7] = operands[3]; @@ -16788,7 +16767,7 @@ }) (define_insn "allocate_stack_worker_1" - [(unspec:SI [(match_operand:SI 0 "register_operand" "a")] 3) + [(unspec:SI [(match_operand:SI 0 "register_operand" "a")] UNSPEC_STACK_PROBE) (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 0))) (clobber (match_dup 0)) (clobber (reg:CC 17))] @@ -16798,7 +16777,7 @@ (set_attr "length" "5")]) (define_insn "allocate_stack_worker_rex64" - [(unspec:DI [(match_operand:DI 0 "register_operand" "a")] 3) + [(unspec:DI [(match_operand:DI 0 "register_operand" "a")] UNSPEC_STACK_PROBE) (set (reg:DI 7) (minus:DI (reg:DI 7) (match_dup 0))) (clobber (match_dup 0)) (clobber (reg:CC 17))] @@ -16835,7 +16814,7 @@ [(label_ref (match_operand 0 "" ""))] "!TARGET_64BIT && flag_pic" { - load_pic_register (); + emit_insn (gen_set_got (pic_offset_table_rtx)); DONE; }) @@ -16849,7 +16828,8 @@ (clobber (reg:CC 17))] "! TARGET_PARTIAL_REG_STALL && reload_completed && ((GET_MODE (operands[0]) == HImode - && (!optimize_size || GET_CODE (operands[2]) != CONST_INT + && ((!optimize_size && !TARGET_FAST_PREFIX) + || GET_CODE (operands[2]) != CONST_INT || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))) || (GET_MODE (operands[0]) == QImode && (TARGET_PROMOTE_QImode || optimize_size)))" @@ -16862,6 +16842,10 @@ operands[2] = gen_lowpart (SImode, operands[2]); PUT_MODE (operands[3], SImode);") +; Promote the QImode tests, as i386 has encoding of the AND +; instruction with 32-bit sign-extended immediate and thus the +; instruction size is unchanged, except in the %eax case for +; which it is increased by one byte, hence the ! optimize_size. (define_split [(set (reg 17) (compare (and (match_operand 1 "aligned_operand" "") @@ -16870,39 +16854,44 @@ (set (match_operand 0 "register_operand" "") (and (match_dup 1) (match_dup 2)))] "! TARGET_PARTIAL_REG_STALL && reload_completed - && ix86_match_ccmode (insn, CCNOmode) - && (GET_MODE (operands[0]) == HImode - || (GET_MODE (operands[0]) == QImode - && (TARGET_PROMOTE_QImode || optimize_size)))" + /* Ensure that the operand will remain sign-extended immediate. */ + && ix86_match_ccmode (insn, INTVAL (operands[2]) >= 0 ? CCNOmode : CCZmode) + && ! optimize_size + && ((GET_MODE (operands[0]) == HImode && ! TARGET_FAST_PREFIX) + || (GET_MODE (operands[0]) == QImode && TARGET_PROMOTE_QImode))" [(parallel [(set (reg:CCNO 17) (compare:CCNO (and:SI (match_dup 1) (match_dup 2)) (const_int 0))) (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])] "operands[2] - = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]) - & GET_MODE_MASK (GET_MODE (operands[0])), - SImode)); + = gen_int_mode (INTVAL (operands[2]) + & GET_MODE_MASK (GET_MODE (operands[0])), + SImode); operands[0] = gen_lowpart (SImode, operands[0]); operands[1] = gen_lowpart (SImode, operands[1]);") +; Don't promote the QImode tests, as i386 doesn't have encoding of +; the TEST instruction with 32-bit sign-extended immediate and thus +; the instruction size would at least double, which is not what we +; want even with ! optimize_size. (define_split [(set (reg 17) - (compare (and (match_operand 0 "aligned_operand" "") - (match_operand 1 "const_int_operand" "")) + (compare (and (match_operand:HI 0 "aligned_operand" "") + (match_operand:HI 1 "const_int_operand" "")) (const_int 0)))] "! TARGET_PARTIAL_REG_STALL && reload_completed - && ix86_match_ccmode (insn, CCNOmode) - && (GET_MODE (operands[0]) == HImode - || (GET_MODE (operands[0]) == QImode - && (TARGET_PROMOTE_QImode || optimize_size)))" + /* Ensure that the operand will remain sign-extended immediate. */ + && ix86_match_ccmode (insn, INTVAL (operands[1]) >= 0 ? CCNOmode : CCZmode) + && ! TARGET_FAST_PREFIX + && ! optimize_size" [(set (reg:CCNO 17) (compare:CCNO (and:SI (match_dup 0) (match_dup 1)) (const_int 0)))] "operands[1] - = GEN_INT (trunc_int_for_mode (INTVAL (operands[1]) - & GET_MODE_MASK (GET_MODE (operands[0])), - SImode)); + = gen_int_mode (INTVAL (operands[1]) + & GET_MODE_MASK (GET_MODE (operands[0])), + SImode); operands[0] = gen_lowpart (SImode, operands[0]);") (define_split @@ -17152,7 +17141,8 @@ (const_int 0)))] "ix86_match_ccmode (insn, CCNOmode) && (true_regnum (operands[0]) != 0 - || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'K')) + || (GET_CODE (operands[1]) == CONST_INT + && CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'K'))) && find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))" [(parallel [(set (reg:CCNO 17) @@ -17375,7 +17365,7 @@ [(set (match_operand:SI 0 "register_operand" "") (subreg:SI (mult:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "const_int_operand" "")) 0))] - "exact_log2 (INTVAL (operands[1])) >= 0 + "exact_log2 (INTVAL (operands[2])) >= 0 && 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))) @@ -17853,52 +17843,92 @@ ;; Moves for SSE/MMX regs. (define_insn "movv4sf_internal" - [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m") - (match_operand:V4SF 1 "nonimmediate_operand" "xm,x"))] + [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,m") + (match_operand:V4SF 1 "vector_move_operand" "C,xm,x"))] "TARGET_SSE" ;; @@@ let's try to use movaps here. - "movaps\t{%1, %0|%0, %1}" - [(set_attr "type" "sse")]) + "@ + 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_insn "movv4si_internal" - [(set (match_operand:V4SI 0 "nonimmediate_operand" "=x,m") - (match_operand:V4SI 1 "nonimmediate_operand" "xm,x"))] + [(set (match_operand:V4SI 0 "nonimmediate_operand" "=x,x,m") + (match_operand:V4SI 1 "vector_move_operand" "C,xm,x"))] "TARGET_SSE" ;; @@@ let's try to use movaps here. - "movaps\t{%1, %0|%0, %1}" - [(set_attr "type" "sse")]) + "@ + 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_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" + ;; @@@ let's try to use movaps here. + "@ + pxor\t%0, %0 + movdqa\t{%1, %0|%0, %1} + movdqa\t{%1, %0|%0, %1}" + [(set_attr "type" "ssemov") + (set_attr "mode" "V4SF")]) (define_insn "movv8qi_internal" - [(set (match_operand:V8QI 0 "nonimmediate_operand" "=y,m") - (match_operand:V8QI 1 "nonimmediate_operand" "ym,y"))] - "TARGET_MMX" - "movq\t{%1, %0|%0, %1}" - [(set_attr "type" "mmx")]) + [(set (match_operand:V8QI 0 "nonimmediate_operand" "=y,y,m") + (match_operand:V8QI 1 "vector_move_operand" "C,ym,y"))] + "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}" + [(set_attr "type" "mmxmov") + (set_attr "mode" "DI")]) (define_insn "movv4hi_internal" - [(set (match_operand:V4HI 0 "nonimmediate_operand" "=y,m") - (match_operand:V4HI 1 "nonimmediate_operand" "ym,y"))] - "TARGET_MMX" - "movq\t{%1, %0|%0, %1}" - [(set_attr "type" "mmx")]) + [(set (match_operand:V4HI 0 "nonimmediate_operand" "=y,y,m") + (match_operand:V4HI 1 "vector_move_operand" "C,ym,y"))] + "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}" + [(set_attr "type" "mmxmov") + (set_attr "mode" "DI")]) (define_insn "movv2si_internal" - [(set (match_operand:V2SI 0 "nonimmediate_operand" "=y,m") - (match_operand:V2SI 1 "nonimmediate_operand" "ym,y"))] - "TARGET_MMX" - "movq\t{%1, %0|%0, %1}" - [(set_attr "type" "mmx")]) + [(set (match_operand:V2SI 0 "nonimmediate_operand" "=y,y,m") + (match_operand:V2SI 1 "vector_move_operand" "C,ym,y"))] + "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}" + [(set_attr "type" "mmxcvt") + (set_attr "mode" "DI")]) (define_insn "movv2sf_internal" - [(set (match_operand:V2SF 0 "nonimmediate_operand" "=y,m") - (match_operand:V2SF 1 "nonimmediate_operand" "ym,y"))] - "TARGET_3DNOW" - "movq\\t{%1, %0|%0, %1}" - [(set_attr "type" "mmx")]) + [(set (match_operand:V2SF 0 "nonimmediate_operand" "=y,y,m") + (match_operand:V2SF 1 "vector_move_operand" "C,ym,y"))] + "TARGET_3DNOW + && (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}" + [(set_attr "type" "mmxcvt") + (set_attr "mode" "DI")]) (define_expand "movti" - [(set (match_operand:TI 0 "general_operand" "") - (match_operand:TI 1 "general_operand" ""))] + [(set (match_operand:TI 0 "nonimmediate_operand" "") + (match_operand:TI 1 "nonimmediate_operand" ""))] "TARGET_SSE || TARGET_64BIT" { if (TARGET_64BIT) @@ -17908,9 +17938,72 @@ 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_SSE2 + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" + "@ + xorpd\t%0, %0 + movapd\t{%1, %0|%0, %1} + movapd\t{%1, %0|%0, %1}" + [(set_attr "type" "ssemov") + (set_attr "mode" "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_SSE2 + && (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_insn "movv16qi_internal" + [(set (match_operand:V16QI 0 "nonimmediate_operand" "=x,x,m") + (match_operand:V16QI 1 "vector_move_operand" "C,xm,x"))] + "TARGET_SSE2 + && (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_expand "movv2df" + [(set (match_operand:V2DF 0 "nonimmediate_operand" "") + (match_operand:V2DF 1 "nonimmediate_operand" ""))] + "TARGET_SSE2" +{ + ix86_expand_vector_move (V2DFmode, operands); + DONE; +}) + +(define_expand "movv8hi" + [(set (match_operand:V8HI 0 "nonimmediate_operand" "") + (match_operand:V8HI 1 "nonimmediate_operand" ""))] + "TARGET_SSE2" +{ + ix86_expand_vector_move (V8HImode, operands); + DONE; +}) + +(define_expand "movv16qi" + [(set (match_operand:V16QI 0 "nonimmediate_operand" "") + (match_operand:V16QI 1 "nonimmediate_operand" ""))] + "TARGET_SSE2" +{ + ix86_expand_vector_move (V16QImode, operands); + DONE; +}) + (define_expand "movv4sf" - [(set (match_operand:V4SF 0 "general_operand" "") - (match_operand:V4SF 1 "general_operand" ""))] + [(set (match_operand:V4SF 0 "nonimmediate_operand" "") + (match_operand:V4SF 1 "nonimmediate_operand" ""))] "TARGET_SSE" { ix86_expand_vector_move (V4SFmode, operands); @@ -17918,17 +18011,26 @@ }) (define_expand "movv4si" - [(set (match_operand:V4SI 0 "general_operand" "") - (match_operand:V4SI 1 "general_operand" ""))] - "TARGET_MMX" + [(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 "general_operand" "") - (match_operand:V2SI 1 "general_operand" ""))] + [(set (match_operand:V2SI 0 "nonimmediate_operand" "") + (match_operand:V2SI 1 "nonimmediate_operand" ""))] "TARGET_MMX" { ix86_expand_vector_move (V2SImode, operands); @@ -17936,8 +18038,8 @@ }) (define_expand "movv4hi" - [(set (match_operand:V4HI 0 "general_operand" "") - (match_operand:V4HI 1 "general_operand" ""))] + [(set (match_operand:V4HI 0 "nonimmediate_operand" "") + (match_operand:V4HI 1 "nonimmediate_operand" ""))] "TARGET_MMX" { ix86_expand_vector_move (V4HImode, operands); @@ -17945,8 +18047,8 @@ }) (define_expand "movv8qi" - [(set (match_operand:V8QI 0 "general_operand" "") - (match_operand:V8QI 1 "general_operand" ""))] + [(set (match_operand:V8QI 0 "nonimmediate_operand" "") + (match_operand:V8QI 1 "nonimmediate_operand" ""))] "TARGET_MMX" { ix86_expand_vector_move (V8QImode, operands); @@ -17954,14 +18056,97 @@ }) (define_expand "movv2sf" - [(set (match_operand:V2SF 0 "general_operand" "") - (match_operand:V2SF 1 "general_operand" ""))] + [(set (match_operand:V2SF 0 "nonimmediate_operand" "") + (match_operand:V2SF 1 "nonimmediate_operand" ""))] "TARGET_3DNOW" { ix86_expand_vector_move (V2SFmode, operands); DONE; }) +(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_SSE2" + "#") + +(define_insn "*pushv8hi" + [(set (match_operand:V8HI 0 "push_operand" "=<") + (match_operand:V8HI 1 "register_operand" "x"))] + "TARGET_SSE2" + "#") + +(define_insn "*pushv16qi" + [(set (match_operand:V16QI 0 "push_operand" "=<") + (match_operand:V16QI 1 "register_operand" "x"))] + "TARGET_SSE2" + "#") + +(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_SSE2" + "#") + +(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_3DNOW" + "#") + +(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_and_split "*pushti" [(set (match_operand:TI 0 "push_operand" "=<") (match_operand:TI 1 "nonmemory_operand" "x"))] @@ -17971,7 +18156,51 @@ [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) (set (mem:TI (reg:SI 7)) (match_dup 1))] "" - [(set_attr "type" "sse")]) + [(set_attr "type" "multi")]) + +(define_insn_and_split "*pushv2df" + [(set (match_operand:V2DF 0 "push_operand" "=<") + (match_operand:V2DF 1 "nonmemory_operand" "x"))] + "TARGET_SSE2" + "#" + "" + [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) + (set (mem:V2DF (reg:SI 7)) (match_dup 1))] + "" + [(set_attr "type" "multi")]) + +(define_insn_and_split "*pushv2di" + [(set (match_operand:V2DI 0 "push_operand" "=<") + (match_operand:V2DI 1 "nonmemory_operand" "x"))] + "TARGET_SSE2" + "#" + "" + [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) + (set (mem:V2DI (reg:SI 7)) (match_dup 1))] + "" + [(set_attr "type" "multi")]) + +(define_insn_and_split "*pushv8hi" + [(set (match_operand:V8HI 0 "push_operand" "=<") + (match_operand:V8HI 1 "nonmemory_operand" "x"))] + "TARGET_SSE2" + "#" + "" + [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) + (set (mem:V8HI (reg:SI 7)) (match_dup 1))] + "" + [(set_attr "type" "multi")]) + +(define_insn_and_split "*pushv16qi" + [(set (match_operand:V16QI 0 "push_operand" "=<") + (match_operand:V16QI 1 "nonmemory_operand" "x"))] + "TARGET_SSE2" + "#" + "" + [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) + (set (mem:V16QI (reg:SI 7)) (match_dup 1))] + "" + [(set_attr "type" "multi")]) (define_insn_and_split "*pushv4sf" [(set (match_operand:V4SF 0 "push_operand" "=<") @@ -17982,7 +18211,7 @@ [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) (set (mem:V4SF (reg:SI 7)) (match_dup 1))] "" - [(set_attr "type" "sse")]) + [(set_attr "type" "multi")]) (define_insn_and_split "*pushv4si" [(set (match_operand:V4SI 0 "push_operand" "=<") @@ -17993,7 +18222,7 @@ [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) (set (mem:V4SI (reg:SI 7)) (match_dup 1))] "" - [(set_attr "type" "sse")]) + [(set_attr "type" "multi")]) (define_insn_and_split "*pushv2si" [(set (match_operand:V2SI 0 "push_operand" "=<") @@ -18041,17 +18270,19 @@ (define_insn "movti_internal" [(set (match_operand:TI 0 "nonimmediate_operand" "=x,x,m") - (match_operand:TI 1 "general_operand" "O,xm,x"))] - "TARGET_SSE && !TARGET_64BIT" + (match_operand:TI 1 "vector_move_operand" "C,xm,x"))] + "TARGET_SSE && !TARGET_64BIT + && (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" "sse")]) + [(set_attr "type" "ssemov,ssemov,ssemov") + (set_attr "mode" "V4SF")]) (define_insn "*movti_rex64" [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o,x,mx,x") - (match_operand:TI 1 "general_operand" "riFo,riF,O,x,m"))] + (match_operand:TI 1 "general_operand" "riFo,riF,C,x,m"))] "TARGET_64BIT && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "@ @@ -18060,8 +18291,8 @@ xorps\t%0, %0 movaps\\t{%1, %0|%0, %1} movaps\\t{%1, %0|%0, %1}" - [(set_attr "type" "*,*,sse,sse,sse") - (set_attr "mode" "TI")]) + [(set_attr "type" "*,*,ssemov,ssemov,ssemov") + (set_attr "mode" "V4SF")]) (define_split [(set (match_operand:TI 0 "nonimmediate_operand" "") @@ -18073,74 +18304,116 @@ ;; These two patterns are useful for specifying exactly whether to use ;; movaps or movups -(define_insn "sse_movaps" - [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m") - (unspec:V4SF - [(match_operand:V4SF 1 "nonimmediate_operand" "xm,x")] 38))] +(define_expand "sse_movaps" + [(set (match_operand:V4SF 0 "nonimmediate_operand" "") + (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "")] + UNSPEC_MOVA))] "TARGET_SSE" - "@ - movaps\t{%1, %0|%0, %1} - movaps\t{%1, %0|%0, %1}" - [(set_attr "type" "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_movups" +(define_insn "*sse_movaps_1" [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m") - (unspec:V4SF - [(match_operand:V4SF 1 "nonimmediate_operand" "xm,x")] 39))] + (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" - "@ - movups\t{%1, %0|%0, %1} - movups\t{%1, %0|%0, %1}" - [(set_attr "type" "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")] 33))] + (unspec:SI [(match_operand:V4SF 1 "register_operand" "x")] + UNSPEC_MOVMSK))] "TARGET_SSE" "movmskps\t{%1, %0|%0, %1}" - [(set_attr "type" "sse")]) + [(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")] 33))] + (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" "sse")]) + [(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")] 32))] + (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" "sse")]) + [(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")] 32))] + (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" "sse")]) + [(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")] 34))] + (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "x")] + UNSPEC_MOVNT))] "TARGET_SSE" "movntps\t{%1, %0|%0, %1}" - [(set_attr "type" "sse")]) + [(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")] 34))] + (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" "sse")]) + [(set_attr "type" "mmxmov") + (set_attr "mode" "DI")]) (define_insn "sse_movhlps" [(set (match_operand:V4SF 0 "register_operand" "=x") @@ -18154,7 +18427,8 @@ (const_int 3)))] "TARGET_SSE" "movhlps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssecvt") + (set_attr "mode" "V4SF")]) (define_insn "sse_movlhps" [(set (match_operand:V4SF 0 "register_operand" "=x") @@ -18168,7 +18442,8 @@ (const_int 12)))] "TARGET_SSE" "movlhps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssecvt") + (set_attr "mode" "V4SF")]) (define_insn "sse_movhps" [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m") @@ -18179,7 +18454,8 @@ "TARGET_SSE && (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)" "movhps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssecvt") + (set_attr "mode" "V4SF")]) (define_insn "sse_movlps" [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m") @@ -18190,17 +18466,29 @@ "TARGET_SSE && (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)" "movlps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssecvt") + (set_attr "mode" "V4SF")]) -(define_insn "sse_loadss" +(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 - (match_operand:V4SF 1 "memory_operand" "m") - (vec_duplicate:V4SF (float:SF (const_int 0))) + (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" "sse")]) + [(set_attr "type" "ssemov") + (set_attr "mode" "SF")]) (define_insn "sse_movss" [(set (match_operand:V4SF 0 "register_operand" "=x") @@ -18210,7 +18498,8 @@ (const_int 1)))] "TARGET_SSE" "movss\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssemov") + (set_attr "mode" "SF")]) (define_insn "sse_storess" [(set (match_operand:SF 0 "memory_operand" "=m") @@ -18219,17 +18508,20 @@ (parallel [(const_int 0)])))] "TARGET_SSE" "movss\t{%1, %0|%0, %1}" - [(set_attr "type" "sse")]) + [(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")] 41))] + (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" "sse")]) + [(set_attr "type" "ssecvt") + (set_attr "mode" "V4SF")]) ;; SSE arithmetic @@ -18240,7 +18532,8 @@ (match_operand:V4SF 2 "nonimmediate_operand" "xm")))] "TARGET_SSE" "addps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "sseadd") + (set_attr "mode" "V4SF")]) (define_insn "vmaddv4sf3" [(set (match_operand:V4SF 0 "register_operand" "=x") @@ -18251,7 +18544,8 @@ (const_int 1)))] "TARGET_SSE" "addss\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "sseadd") + (set_attr "mode" "SF")]) (define_insn "subv4sf3" [(set (match_operand:V4SF 0 "register_operand" "=x") @@ -18259,7 +18553,8 @@ (match_operand:V4SF 2 "nonimmediate_operand" "xm")))] "TARGET_SSE" "subps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "sseadd") + (set_attr "mode" "V4SF")]) (define_insn "vmsubv4sf3" [(set (match_operand:V4SF 0 "register_operand" "=x") @@ -18270,7 +18565,8 @@ (const_int 1)))] "TARGET_SSE" "subss\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "sseadd") + (set_attr "mode" "SF")]) (define_insn "mulv4sf3" [(set (match_operand:V4SF 0 "register_operand" "=x") @@ -18278,7 +18574,8 @@ (match_operand:V4SF 2 "nonimmediate_operand" "xm")))] "TARGET_SSE" "mulps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssemul") + (set_attr "mode" "V4SF")]) (define_insn "vmmulv4sf3" [(set (match_operand:V4SF 0 "register_operand" "=x") @@ -18289,7 +18586,8 @@ (const_int 1)))] "TARGET_SSE" "mulss\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssemul") + (set_attr "mode" "SF")]) (define_insn "divv4sf3" [(set (match_operand:V4SF 0 "register_operand" "=x") @@ -18297,7 +18595,8 @@ (match_operand:V4SF 2 "nonimmediate_operand" "xm")))] "TARGET_SSE" "divps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssediv") + (set_attr "mode" "V4SF")]) (define_insn "vmdivv4sf3" [(set (match_operand:V4SF 0 "register_operand" "=x") @@ -18308,7 +18607,8 @@ (const_int 1)))] "TARGET_SSE" "divss\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssediv") + (set_attr "mode" "SF")]) ;; SSE square root/reciprocal @@ -18316,45 +18616,52 @@ (define_insn "rcpv4sf2" [(set (match_operand:V4SF 0 "register_operand" "=x") (unspec:V4SF - [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] 42))] + [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] UNSPEC_RCP))] "TARGET_SSE" "rcpps\t{%1, %0|%0, %1}" - [(set_attr "type" "sse")]) + [(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")] 42) + (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 "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")] 43))] + [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] UNSPEC_RSQRT))] "TARGET_SSE" "rsqrtps\t{%1, %0|%0, %1}" - [(set_attr "type" "sse")]) + [(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")] 43) + (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 "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 "type" "sse") + (set_attr "mode" "V4SF")]) (define_insn "vmsqrtv4sf2" [(set (match_operand:V4SF 0 "register_operand" "=x") @@ -18364,206 +18671,358 @@ (const_int 1)))] "TARGET_SSE" "sqrtss\t{%1, %0|%0, %1}" - [(set_attr "type" "sse")]) + [(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 elliminated +;; 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 elliminating 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 synthetize 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 (subreg:TI (match_operand:V4SF 0 "register_operand" "") 0) + (and:TI (subreg:TI (match_operand:V4SF 1 "register_operand" "") 0) + (subreg:TI (match_operand:V4SF 2 "nonimmediate_operand" "") 0)))] + "TARGET_SSE" + "") -(define_insn "*sse_andti3_df_1" - [(set (subreg:TI (match_operand:DF 0 "register_operand" "=Y") 0) - (and:TI (subreg:TI (match_operand:DF 1 "register_operand" "%0") 0) - (subreg:TI (match_operand:DF 2 "register_operand" "Y") 0)))] - "TARGET_SSE2" - "andpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) - -(define_insn "*sse_andti3_df_2" - [(set (subreg:TI (match_operand:DF 0 "register_operand" "=Y") 0) - (and:TI (subreg:TI (match_operand:DF 1 "register_operand" "0") 0) - (match_operand:TI 2 "nonimmediate_operand" "Ym")))] - "TARGET_SSE2" - "andpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) +(define_insn "*sse_andv4sf3" + [(set (subreg:TI (match_operand:V4SF 0 "register_operand" "=x") 0) + (and:TI (match_operand:TI 1 "nonimmediate_operand" "%0") + (match_operand:TI 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_insn "*sse_andti3_sf_1" +(define_insn "*sse_andsf3" [(set (subreg:TI (match_operand:SF 0 "register_operand" "=x") 0) - (and:TI (subreg:TI (match_operand:SF 1 "register_operand" "%0") 0) - (subreg:TI (match_operand:SF 2 "register_operand" "x") 0)))] - "TARGET_SSE" + (and:TI (match_operand:TI 1 "nonimmediate_operand" "%0") + (match_operand:TI 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" "sse")]) + [(set_attr "type" "sselog") + (set_attr "mode" "V4SF")]) + +(define_expand "sse_nandv4sf3" + [(set (subreg:TI (match_operand:V4SF 0 "register_operand" "") 0) + (and:TI (not:TI (subreg:TI (match_operand:V4SF 1 "register_operand" "") 0)) + (subreg:TI (match_operand:V4SF 2 "nonimmediate_operand" "") 0)))] + "TARGET_SSE" + "") + +(define_insn "*sse_nandv4sf3" + [(set (subreg:TI (match_operand:V4SF 0 "register_operand" "=x") 0) + (and:TI (not:TI (match_operand:TI 1 "register_operand" "0")) + (match_operand:TI 2 "nonimmediate_operand" "xm")))] + "TARGET_SSE" + "andnps\t{%2, %0|%0, %2}" + [(set_attr "type" "sselog") + (set_attr "mode" "V4SF")]) -(define_insn "*sse_andti3_sf_2" +(define_insn "*sse_nandsf3" [(set (subreg:TI (match_operand:SF 0 "register_operand" "=x") 0) - (and:TI (subreg:TI (match_operand:SF 1 "register_operand" "0") 0) - (match_operand:TI 2 "nonimmediate_operand" "xm")))] + (and:TI (not:TI (match_operand:TI 1 "register_operand" "0")) + (match_operand:TI 2 "nonimmediate_operand" "xm")))] "TARGET_SSE" - "andps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + "andnps\t{%2, %0|%0, %2}" + [(set_attr "type" "sselog") + (set_attr "mode" "V4SF")]) -(define_insn "sse_andti3" - [(set (match_operand:TI 0 "register_operand" "=x") - (and:TI (match_operand:TI 1 "nonimmediate_operand" "%0") +(define_expand "sse_iorv4sf3" + [(set (subreg:TI (match_operand:V4SF 0 "register_operand" "") 0) + (ior:TI (subreg:TI (match_operand:V4SF 1 "register_operand" "") 0) + (subreg:TI (match_operand:V4SF 2 "nonimmediate_operand" "") 0)))] + "TARGET_SSE" + "") + +(define_insn "*sse_iorv4sf3" + [(set (subreg:TI (match_operand:V4SF 0 "register_operand" "=x") 0) + (ior:TI (match_operand:TI 1 "nonimmediate_operand" "%0") (match_operand:TI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE && !TARGET_SSE2 + "TARGET_SSE && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "andps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + "orps\t{%2, %0|%0, %2}" + [(set_attr "type" "sselog") + (set_attr "mode" "V4SF")]) -(define_insn "*sse_andti3_sse2" - [(set (match_operand:TI 0 "register_operand" "=x") - (and:TI (match_operand:TI 1 "nonimmediate_operand" "%0") +(define_insn "*sse_iorsf3" + [(set (subreg:TI (match_operand:SF 0 "register_operand" "=x") 0) + (ior:TI (match_operand:TI 1 "nonimmediate_operand" "%0") (match_operand:TI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE2 + "TARGET_SSE && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "pand\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + "orps\t{%2, %0|%0, %2}" + [(set_attr "type" "sselog") + (set_attr "mode" "V4SF")]) -(define_insn "*sse_nandti3_df" - [(set (subreg:TI (match_operand:DF 0 "register_operand" "=Y") 0) - (and:TI (not:TI (subreg:TI (match_operand:DF 1 "register_operand" "0") 0)) - (match_operand:TI 2 "nonimmediate_operand" "Ym")))] - "TARGET_SSE2" - "andnpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) +(define_expand "sse_xorv4sf3" + [(set (subreg:TI (match_operand:V4SF 0 "register_operand" "") 0) + (xor:TI (subreg:TI (match_operand:V4SF 1 "register_operand" "") 0) + (subreg:TI (match_operand:V4SF 2 "nonimmediate_operand" "") 0)))] + "TARGET_SSE + && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" + "") + +(define_insn "*sse_xorv4sf3" + [(set (subreg:TI (match_operand:V4SF 0 "register_operand" "=x") 0) + (xor:TI (match_operand:TI 1 "nonimmediate_operand" "%0") + (match_operand:TI 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")]) -(define_insn "*sse_nandti3_sf" +(define_insn "*sse_xorsf3" [(set (subreg:TI (match_operand:SF 0 "register_operand" "=x") 0) - (and:TI (not:TI (subreg:TI (match_operand:SF 1 "register_operand" "0") 0)) + (xor:TI (match_operand:TI 1 "nonimmediate_operand" "%0") (match_operand:TI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE" - "andnps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + "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")]) -(define_insn "sse_nandti3" - [(set (match_operand:TI 0 "register_operand" "=x") - (and:TI (not:TI (match_operand:TI 1 "register_operand" "0")) +;; SSE2 double precision floating point logical operation + +(define_expand "sse2_andv2df3" + [(set (subreg:TI (match_operand:V2DF 0 "register_operand" "") 0) + (and:TI (subreg:TI (match_operand:V2DF 1 "register_operand" "") 0) + (subreg:TI (match_operand:V2DF 2 "nonimmediate_operand" "") 0)))] + "TARGET_SSE2" + "") + +(define_insn "*sse2_andv2df3" + [(set (subreg:TI (match_operand:V2DF 0 "register_operand" "=x") 0) + (and:TI (match_operand:TI 1 "nonimmediate_operand" "%0") (match_operand:TI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE && !TARGET_SSE2" - "andnps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + "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_insn "*sse_nandti3_sse2" - [(set (match_operand:TI 0 "register_operand" "=x") - (and:TI (not:TI (match_operand:TI 1 "register_operand" "0")) +(define_insn "*sse2_andv2df3" + [(set (subreg:TI (match_operand:DF 0 "register_operand" "=x") 0) + (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)" + "andpd\t{%2, %0|%0, %2}" + [(set_attr "type" "sselog") + (set_attr "mode" "V2DF")]) + +(define_expand "sse2_nandv2df3" + [(set (subreg:TI (match_operand:V2DF 0 "register_operand" "") 0) + (and:TI (not:TI (subreg:TI (match_operand:V2DF 1 "register_operand" "") 0)) + (subreg:TI (match_operand:V2DF 2 "nonimmediate_operand" "") 0)))] "TARGET_SSE2" - "pnand\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + "") -(define_insn "*sse_iorti3_df_1" - [(set (subreg:TI (match_operand:DF 0 "register_operand" "=Y") 0) - (ior:TI (subreg:TI (match_operand:DF 1 "register_operand" "%0") 0) - (subreg:TI (match_operand:DF 2 "register_operand" "Y") 0)))] +(define_insn "*sse2_nandv2df3" + [(set (subreg:TI (match_operand:V2DF 0 "register_operand" "=x") 0) + (and:TI (not:TI (match_operand:TI 1 "register_operand" "0")) + (match_operand:TI 2 "nonimmediate_operand" "xm")))] "TARGET_SSE2" - "orpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + "andnpd\t{%2, %0|%0, %2}" + [(set_attr "type" "sselog") + (set_attr "mode" "V2DF")]) -(define_insn "*sse_iorti3_df_2" +(define_insn "*sse_nandti3_df" [(set (subreg:TI (match_operand:DF 0 "register_operand" "=Y") 0) - (ior:TI (subreg:TI (match_operand:DF 1 "register_operand" "0") 0) + (and:TI (not:TI (match_operand:TI 1 "register_operand" "0")) (match_operand:TI 2 "nonimmediate_operand" "Ym")))] "TARGET_SSE2" - "orpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) - -(define_insn "*sse_iorti3_sf_1" - [(set (subreg:TI (match_operand:SF 0 "register_operand" "=x") 0) - (ior:TI (subreg:TI (match_operand:SF 1 "register_operand" "%0") 0) - (subreg:TI (match_operand:SF 2 "register_operand" "x") 0)))] - "TARGET_SSE" - "orps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + "andnpd\t{%2, %0|%0, %2}" + [(set_attr "type" "sselog") + (set_attr "mode" "V2DF")]) -(define_insn "*sse_iorti3_sf_2" - [(set (subreg:TI (match_operand:SF 0 "register_operand" "=x") 0) - (ior:TI (subreg:TI (match_operand:SF 1 "register_operand" "0") 0) - (match_operand:TI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE" - "orps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) +(define_expand "sse2_iorv2df3" + [(set (subreg:TI (match_operand:V2DF 0 "register_operand" "") 0) + (ior:TI (subreg:TI (match_operand:V2DF 1 "register_operand" "") 0) + (subreg:TI (match_operand:V2DF 2 "nonimmediate_operand" "") 0)))] + "TARGET_SSE2" + "") -(define_insn "sse_iorti3" - [(set (match_operand:TI 0 "register_operand" "=x") +(define_insn "*sse2_iorv2df3" + [(set (subreg:TI (match_operand:V2DF 0 "register_operand" "=x") 0) (ior:TI (match_operand:TI 1 "nonimmediate_operand" "%0") (match_operand:TI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE && !TARGET_SSE2 + "TARGET_SSE2 && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "orps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + "orpd\t{%2, %0|%0, %2}" + [(set_attr "type" "sselog") + (set_attr "mode" "V2DF")]) -(define_insn "*sse_iorti3_sse2" - [(set (match_operand:TI 0 "register_operand" "=x") +(define_insn "*sse2_iordf3" + [(set (subreg:TI (match_operand:DF 0 "register_operand" "=x") 0) (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" "sse")]) + "orpd\t{%2, %0|%0, %2}" + [(set_attr "type" "sselog") + (set_attr "mode" "V2DF")]) -(define_insn "*sse_xorti3_df_1" - [(set (subreg:TI (match_operand:DF 0 "register_operand" "=Y") 0) - (xor:TI (subreg:TI (match_operand:DF 1 "register_operand" "%0") 0) - (subreg:TI (match_operand:DF 2 "register_operand" "Y") 0)))] +(define_expand "sse2_xorv2df3" + [(set (subreg:TI (match_operand:V2DF 0 "register_operand" "") 0) + (xor:TI (subreg:TI (match_operand:V2DF 1 "nonimmediate_operand" "") 0) + (subreg:TI (match_operand:V2DF 2 "nonimmediate_operand" "") 0)))] "TARGET_SSE2" + "") + +(define_insn "*sse2_xorv2df3" + [(set (subreg:TI (match_operand:V2DF 0 "register_operand" "=x") 0) + (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)" "xorpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "sselog") + (set_attr "mode" "V2DF")]) -(define_insn "*sse_xorti3_df_2" - [(set (subreg:TI (match_operand:DF 0 "register_operand" "=Y") 0) - (xor:TI (subreg:TI (match_operand:DF 1 "register_operand" "0") 0) - (match_operand:TI 2 "nonimmediate_operand" "Ym")))] - "TARGET_SSE2" +(define_insn "*sse2_xordf3" + [(set (subreg:TI (match_operand:DF 0 "register_operand" "=x") 0) + (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)" "xorpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "sselog") + (set_attr "mode" "V2DF")]) -(define_insn "*sse_xorti3_sf_1" - [(set (subreg:TI (match_operand:SF 0 "register_operand" "=x") 0) - (xor:TI (subreg:TI (match_operand:SF 1 "register_operand" "%0") 0) - (subreg:TI (match_operand:SF 2 "register_operand" "x") 0)))] - "TARGET_SSE" - "xorps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) +;; 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 "*sse_xorti3_sf_2" - [(set (subreg:TI (match_operand:SF 0 "register_operand" "=x") 0) - (xor:TI (subreg:TI (match_operand:SF 1 "register_operand" "0") 0) +(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_SSE" - "xorps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + "TARGET_SSE2" + "pandn\t{%2, %0|%0, %2}" + [(set_attr "type" "sselog") + (set_attr "mode" "TI")]) -(define_insn "sse_xorti3" +(define_insn "sse2_nandv2di3" + [(set (match_operand:V2DI 0 "register_operand" "=x") + (and:V2DI (not: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)" + "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") - (xor:TI (match_operand:TI 1 "nonimmediate_operand" "%0") + (ior:TI (match_operand:TI 1 "nonimmediate_operand" "%0") (match_operand:TI 2 "nonimmediate_operand" "xm")))] - "TARGET_SSE && !TARGET_SSE2 + "TARGET_SSE2 && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - "xorps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + "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 "*sse_xorti3_sse2" +(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" "sse")]) + [(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") - (unspec:V4SF [(const_int 0)] 45))] + (unspec:V4SF [(const_int 0)] UNSPEC_NOP))] "TARGET_SSE" "xorps\t{%0, %0|%0, %0}" - [(set_attr "type" "sse") - (set_attr "memory" "none")]) + [(set_attr "type" "sselog") + (set_attr "memory" "none") + (set_attr "mode" "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 @@ -18574,7 +19033,8 @@ (match_operand:V4SF 2 "register_operand" "x")]))] "TARGET_SSE" "cmp%D3ps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssecmp") + (set_attr "mode" "V4SF")]) (define_insn "maskncmpv4sf3" [(set (match_operand:V4SI 0 "register_operand" "=x") @@ -18589,7 +19049,8 @@ else return "cmpn%D3ps\t{%2, %0|%0, %2}"; } - [(set_attr "type" "sse")]) + [(set_attr "type" "ssecmp") + (set_attr "mode" "V4SF")]) (define_insn "vmmaskcmpv4sf3" [(set (match_operand:V4SI 0 "register_operand" "=x") @@ -18597,11 +19058,12 @@ (match_operator:V4SI 3 "sse_comparison_operator" [(match_operand:V4SF 1 "register_operand" "0") (match_operand:V4SF 2 "register_operand" "x")]) - (match_dup 1) + (subreg:V4SI (match_dup 1) 0) (const_int 1)))] "TARGET_SSE" "cmp%D3ss\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssecmp") + (set_attr "mode" "SF")]) (define_insn "vmmaskncmpv4sf3" [(set (match_operand:V4SI 0 "register_operand" "=x") @@ -18619,33 +19081,34 @@ else return "cmpn%D3ss\t{%2, %0|%0, %2}"; } - [(set_attr "type" "sse")]) + [(set_attr "type" "ssecmp") + (set_attr "mode" "SF")]) (define_insn "sse_comi" [(set (reg:CCFP 17) - (match_operator:CCFP 2 "sse_comparison_operator" - [(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)]))]))] + (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" "sse")]) + [(set_attr "type" "ssecmp") + (set_attr "mode" "SF")]) (define_insn "sse_ucomi" [(set (reg:CCFPU 17) - (match_operator:CCFPU 2 "sse_comparison_operator" - [(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)]))]))] + (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" "sse")]) + [(set_attr "type" "ssecmp") + (set_attr "mode" "SF")]) ;; SSE unpack @@ -18666,7 +19129,8 @@ (const_int 5)))] "TARGET_SSE" "unpckhps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssecvt") + (set_attr "mode" "V4SF")]) (define_insn "sse_unpcklps" [(set (match_operand:V4SF 0 "register_operand" "=x") @@ -18684,7 +19148,8 @@ (const_int 5)))] "TARGET_SSE" "unpcklps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssecvt") + (set_attr "mode" "V4SF")]) ;; SSE min/max @@ -18695,7 +19160,8 @@ (match_operand:V4SF 2 "nonimmediate_operand" "xm")))] "TARGET_SSE" "maxps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "sse") + (set_attr "mode" "V4SF")]) (define_insn "vmsmaxv4sf3" [(set (match_operand:V4SF 0 "register_operand" "=x") @@ -18706,7 +19172,8 @@ (const_int 1)))] "TARGET_SSE" "maxss\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "sse") + (set_attr "mode" "SF")]) (define_insn "sminv4sf3" [(set (match_operand:V4SF 0 "register_operand" "=x") @@ -18714,7 +19181,8 @@ (match_operand:V4SF 2 "nonimmediate_operand" "xm")))] "TARGET_SSE" "minps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "sse") + (set_attr "mode" "V4SF")]) (define_insn "vmsminv4sf3" [(set (match_operand:V4SF 0 "register_operand" "=x") @@ -18725,8 +19193,8 @@ (const_int 1)))] "TARGET_SSE" "minss\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) - + [(set_attr "type" "sse") + (set_attr "mode" "SF")]) ;; SSE <-> integer/MMX conversions @@ -18739,7 +19207,8 @@ (const_int 12)))] "TARGET_SSE" "cvtpi2ps\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssecvt") + (set_attr "mode" "V4SF")]) (define_insn "cvtps2pi" [(set (match_operand:V2SI 0 "register_operand" "=y") @@ -18748,16 +19217,19 @@ (parallel [(const_int 0) (const_int 1)])))] "TARGET_SSE" "cvtps2pi\t{%1, %0|%0, %1}" - [(set_attr "type" "sse")]) + [(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")] 30) + (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" "sse")]) + [(set_attr "type" "ssecvt") + (set_attr "mode" "SF")]) (define_insn "cvtsi2ss" [(set (match_operand:V4SF 0 "register_operand" "=x") @@ -18768,7 +19240,21 @@ (const_int 14)))] "TARGET_SSE" "cvtsi2ss\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssecvt") + (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" "ssecvt") + (set_attr "athlon_decode" "vector,vector") + (set_attr "mode" "SF")]) (define_insn "cvtss2si" [(set (match_operand:SI 0 "register_operand" "=r") @@ -18777,16 +19263,42 @@ (parallel [(const_int 0)])))] "TARGET_SSE" "cvtss2si\t{%1, %0|%0, %1}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssecvt") + (set_attr "mode" "SF")]) + +(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" "ssecvt") + (set_attr "athlon_decode" "vector,vector") + (set_attr "mode" "SF")]) (define_insn "cvttss2si" [(set (match_operand:SI 0 "register_operand" "=r") (vec_select:SI - (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] 30) + (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] + UNSPEC_FIX) (parallel [(const_int 0)])))] "TARGET_SSE" "cvttss2si\t{%1, %0|%0, %1}" - [(set_attr "type" "sse")]) + [(set_attr "type" "ssecvt") + (set_attr "mode" "SF")]) + +(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" "ssecvt") + (set_attr "mode" "SF") + (set_attr "athlon_decode" "vector,vector")]) ;; MMX insns @@ -18795,59 +19307,77 @@ (define_insn "addv8qi3" [(set (match_operand:V8QI 0 "register_operand" "=y") - (plus:V8QI (match_operand:V8QI 1 "register_operand" "0") + (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" "mmx")]) + [(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") + (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" "mmx")]) + [(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") + (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" "mmx")]) + [(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") + (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" "mmx")]) + [(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") + (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" "mmx")]) + [(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") + (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" "mmx")]) + [(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") + (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" "mmx")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "DI")]) (define_insn "subv8qi3" [(set (match_operand:V8QI 0 "register_operand" "=y") @@ -18855,7 +19385,8 @@ (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] "TARGET_MMX" "psubb\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "DI")]) (define_insn "subv4hi3" [(set (match_operand:V4HI 0 "register_operand" "=y") @@ -18863,7 +19394,8 @@ (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] "TARGET_MMX" "psubw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "DI")]) (define_insn "subv2si3" [(set (match_operand:V2SI 0 "register_operand" "=y") @@ -18871,7 +19403,19 @@ (match_operand:V2SI 2 "nonimmediate_operand" "ym")))] "TARGET_MMX" "psubd\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(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") @@ -18879,7 +19423,8 @@ (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] "TARGET_MMX" "psubsb\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "DI")]) (define_insn "sssubv4hi3" [(set (match_operand:V4HI 0 "register_operand" "=y") @@ -18887,7 +19432,8 @@ (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] "TARGET_MMX" "psubsw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "DI")]) (define_insn "ussubv8qi3" [(set (match_operand:V8QI 0 "register_operand" "=y") @@ -18895,7 +19441,8 @@ (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] "TARGET_MMX" "psubusb\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "DI")]) (define_insn "ussubv4hi3" [(set (match_operand:V4HI 0 "register_operand" "=y") @@ -18903,7 +19450,8 @@ (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] "TARGET_MMX" "psubusw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "DI")]) (define_insn "mulv4hi3" [(set (match_operand:V4HI 0 "register_operand" "=y") @@ -18911,7 +19459,8 @@ (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] "TARGET_MMX" "pmullw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxmul") + (set_attr "mode" "DI")]) (define_insn "smulv4hi3_highpart" [(set (match_operand:V4HI 0 "register_operand" "=y") @@ -18924,7 +19473,8 @@ (const_int 16))))] "TARGET_MMX" "pmulhw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxmul") + (set_attr "mode" "DI")]) (define_insn "umulv4hi3_highpart" [(set (match_operand:V4HI 0 "register_operand" "=y") @@ -18937,7 +19487,8 @@ (const_int 16))))] "TARGET_SSE || TARGET_3DNOW_A" "pmulhuw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxmul") + (set_attr "mode" "DI")]) (define_insn "mmx_pmaddwd" [(set (match_operand:V2SI 0 "register_operand" "=y") @@ -18958,7 +19509,8 @@ (const_int 3)]))))))] "TARGET_MMX" "pmaddwd\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxmul") + (set_attr "mode" "DI")]) ;; MMX logical operations @@ -18968,49 +19520,58 @@ (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"))] 45))] + [(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" "mmx")]) + [(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"))] 45))] + [(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" "mmx") + [(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)] 45))] + (unspec:DI [(const_int 0)] UNSPEC_NOP))] "TARGET_MMX" "pxor\t{%0, %0|%0, %0}" - [(set_attr "type" "mmx") + [(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"))] 45))] + [(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" "mmx")]) + [(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"))] 45))] + (match_operand:DI 2 "nonimmediate_operand" "ym"))] + UNSPEC_NOP))] "TARGET_MMX" "pandn\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "DI")]) ;; MMX unsigned averages/sum of absolute differences @@ -19032,7 +19593,8 @@ (const_int 1)))] "TARGET_SSE || TARGET_3DNOW_A" "pavgb\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "mmxshft") + (set_attr "mode" "DI")]) (define_insn "mmx_uavgv4hi3" [(set (match_operand:V4HI 0 "register_operand" "=y") @@ -19047,15 +19609,18 @@ (const_int 1)))] "TARGET_SSE || TARGET_3DNOW_A" "pavgw\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "mmxshft") + (set_attr "mode" "DI")]) (define_insn "mmx_psadbw" - [(set (match_operand:V8QI 0 "register_operand" "=y") - (abs:V8QI (minus:V8QI (match_operand:V8QI 1 "register_operand" "0") - (match_operand:V8QI 2 "nonimmediate_operand" "ym"))))] + [(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" "sse")]) + [(set_attr "type" "mmxshft") + (set_attr "mode" "DI")]) ;; MMX insert/extract/shuffle @@ -19068,7 +19633,8 @@ (match_operand:SI 3 "immediate_operand" "i")))] "TARGET_SSE || TARGET_3DNOW_A" "pinsrw\t{%3, %2, %0|%0, %2, %3}" - [(set_attr "type" "sse")]) + [(set_attr "type" "mmxcvt") + (set_attr "mode" "DI")]) (define_insn "mmx_pextrw" [(set (match_operand:SI 0 "register_operand" "=r") @@ -19077,15 +19643,18 @@ [(match_operand:SI 2 "immediate_operand" "i")]))))] "TARGET_SSE || TARGET_3DNOW_A" "pextrw\t{%2, %1, %0|%0, %1, %2}" - [(set_attr "type" "sse")]) + [(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")] 41))] + (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" "sse")]) + [(set_attr "type" "mmxcvt") + (set_attr "mode" "DI")]) ;; MMX mask-generating comparisons @@ -19096,7 +19665,8 @@ (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] "TARGET_MMX" "pcmpeqb\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxcmp") + (set_attr "mode" "DI")]) (define_insn "eqv4hi3" [(set (match_operand:V4HI 0 "register_operand" "=y") @@ -19104,7 +19674,8 @@ (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] "TARGET_MMX" "pcmpeqw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxcmp") + (set_attr "mode" "DI")]) (define_insn "eqv2si3" [(set (match_operand:V2SI 0 "register_operand" "=y") @@ -19112,7 +19683,8 @@ (match_operand:V2SI 2 "nonimmediate_operand" "ym")))] "TARGET_MMX" "pcmpeqd\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxcmp") + (set_attr "mode" "DI")]) (define_insn "gtv8qi3" [(set (match_operand:V8QI 0 "register_operand" "=y") @@ -19120,7 +19692,8 @@ (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] "TARGET_MMX" "pcmpgtb\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxcmp") + (set_attr "mode" "DI")]) (define_insn "gtv4hi3" [(set (match_operand:V4HI 0 "register_operand" "=y") @@ -19128,7 +19701,8 @@ (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] "TARGET_MMX" "pcmpgtw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxcmp") + (set_attr "mode" "DI")]) (define_insn "gtv2si3" [(set (match_operand:V2SI 0 "register_operand" "=y") @@ -19136,7 +19710,8 @@ (match_operand:V2SI 2 "nonimmediate_operand" "ym")))] "TARGET_MMX" "pcmpgtd\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxcmp") + (set_attr "mode" "DI")]) ;; MMX max/min insns @@ -19147,7 +19722,8 @@ (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] "TARGET_SSE || TARGET_3DNOW_A" "pmaxub\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "DI")]) (define_insn "smaxv4hi3" [(set (match_operand:V4HI 0 "register_operand" "=y") @@ -19155,7 +19731,8 @@ (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] "TARGET_SSE || TARGET_3DNOW_A" "pmaxsw\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "DI")]) (define_insn "uminv8qi3" [(set (match_operand:V8QI 0 "register_operand" "=y") @@ -19163,7 +19740,8 @@ (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] "TARGET_SSE || TARGET_3DNOW_A" "pminub\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "DI")]) (define_insn "sminv4hi3" [(set (match_operand:V4HI 0 "register_operand" "=y") @@ -19171,7 +19749,8 @@ (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] "TARGET_SSE || TARGET_3DNOW_A" "pminsw\t{%2, %0|%0, %2}" - [(set_attr "type" "sse")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "DI")]) ;; MMX shifts @@ -19182,7 +19761,8 @@ (match_operand:DI 2 "nonmemory_operand" "yi")))] "TARGET_MMX" "psraw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxshft") + (set_attr "mode" "DI")]) (define_insn "ashrv2si3" [(set (match_operand:V2SI 0 "register_operand" "=y") @@ -19190,7 +19770,8 @@ (match_operand:DI 2 "nonmemory_operand" "yi")))] "TARGET_MMX" "psrad\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxshft") + (set_attr "mode" "DI")]) (define_insn "lshrv4hi3" [(set (match_operand:V4HI 0 "register_operand" "=y") @@ -19198,7 +19779,8 @@ (match_operand:DI 2 "nonmemory_operand" "yi")))] "TARGET_MMX" "psrlw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxshft") + (set_attr "mode" "DI")]) (define_insn "lshrv2si3" [(set (match_operand:V2SI 0 "register_operand" "=y") @@ -19206,17 +19788,20 @@ (match_operand:DI 2 "nonmemory_operand" "yi")))] "TARGET_MMX" "psrld\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(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"))] 45))] + (match_operand:DI 2 "nonmemory_operand" "yi"))] + UNSPEC_NOP))] "TARGET_MMX" "psrlq\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxshft") + (set_attr "mode" "DI")]) (define_insn "ashlv4hi3" [(set (match_operand:V4HI 0 "register_operand" "=y") @@ -19224,7 +19809,8 @@ (match_operand:DI 2 "nonmemory_operand" "yi")))] "TARGET_MMX" "psllw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxshft") + (set_attr "mode" "DI")]) (define_insn "ashlv2si3" [(set (match_operand:V2SI 0 "register_operand" "=y") @@ -19232,17 +19818,20 @@ (match_operand:DI 2 "nonmemory_operand" "yi")))] "TARGET_MMX" "pslld\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(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"))] 45))] + (match_operand:DI 2 "nonmemory_operand" "yi"))] + UNSPEC_NOP))] "TARGET_MMX" "psllq\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxshft") + (set_attr "mode" "DI")]) ;; MMX pack/unpack insns. @@ -19254,7 +19843,8 @@ (ss_truncate:V4QI (match_operand:V4HI 2 "register_operand" "y"))))] "TARGET_MMX" "packsswb\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxshft") + (set_attr "mode" "DI")]) (define_insn "mmx_packssdw" [(set (match_operand:V4HI 0 "register_operand" "=y") @@ -19263,7 +19853,8 @@ (ss_truncate:V2HI (match_operand:V2SI 2 "register_operand" "y"))))] "TARGET_MMX" "packssdw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxshft") + (set_attr "mode" "DI")]) (define_insn "mmx_packuswb" [(set (match_operand:V8QI 0 "register_operand" "=y") @@ -19272,7 +19863,8 @@ (us_truncate:V4QI (match_operand:V4HI 2 "register_operand" "y"))))] "TARGET_MMX" "packuswb\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxshft") + (set_attr "mode" "DI")]) (define_insn "mmx_punpckhbw" [(set (match_operand:V8QI 0 "register_operand" "=y") @@ -19298,7 +19890,8 @@ (const_int 85)))] "TARGET_MMX" "punpckhbw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxcvt") + (set_attr "mode" "DI")]) (define_insn "mmx_punpckhwd" [(set (match_operand:V4HI 0 "register_operand" "=y") @@ -19316,21 +19909,21 @@ (const_int 5)))] "TARGET_MMX" "punpckhwd\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxcvt") + (set_attr "mode" "DI")]) (define_insn "mmx_punpckhdq" [(set (match_operand:V2SI 0 "register_operand" "=y") (vec_merge:V2SI - (vec_select:V2SI (match_operand:V2SI 1 "register_operand" "0") - (parallel [(const_int 0) - (const_int 1)])) + (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" "mmx")]) + [(set_attr "type" "mmxcvt") + (set_attr "mode" "DI")]) (define_insn "mmx_punpcklbw" [(set (match_operand:V8QI 0 "register_operand" "=y") @@ -19356,7 +19949,8 @@ (const_int 85)))] "TARGET_MMX" "punpcklbw\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxcvt") + (set_attr "mode" "DI")]) (define_insn "mmx_punpcklwd" [(set (match_operand:V4HI 0 "register_operand" "=y") @@ -19374,7 +19968,8 @@ (const_int 5)))] "TARGET_MMX" "punpcklwd\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxcvt") + (set_attr "mode" "DI")]) (define_insn "mmx_punpckldq" [(set (match_operand:V2SI 0 "register_operand" "=y") @@ -19382,19 +19977,18 @@ (vec_select:V2SI (match_operand:V2SI 1 "register_operand" "0") (parallel [(const_int 1) (const_int 0)])) - (vec_select:V2SI (match_operand:V2SI 2 "register_operand" "y") - (parallel [(const_int 0) - (const_int 1)])) + (match_operand:V2SI 2 "register_operand" "y") (const_int 1)))] "TARGET_MMX" "punpckldq\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxcvt") + (set_attr "mode" "DI")]) ;; Miscellaneous stuff (define_insn "emms" - [(unspec_volatile [(const_int 0)] 31) + [(unspec_volatile [(const_int 0)] UNSPECV_EMMS) (clobber (reg:XF 8)) (clobber (reg:XF 9)) (clobber (reg:XF 10)) @@ -19417,23 +20011,24 @@ (set_attr "memory" "unknown")]) (define_insn "ldmxcsr" - [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] 37)] - "TARGET_MMX" + [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] + UNSPECV_LDMXCSR)] + "TARGET_SSE" "ldmxcsr\t%0" - [(set_attr "type" "mmx") + [(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)] 40))] - "TARGET_MMX" + (unspec_volatile:SI [(const_int 0)] UNSPECV_STMXCSR))] + "TARGET_SSE" "stmxcsr\t%0" - [(set_attr "type" "mmx") + [(set_attr "type" "sse") (set_attr "memory" "store")]) (define_expand "sfence" [(set (match_dup 0) - (unspec:BLK [(match_dup 0)] 44))] + (unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))] "TARGET_SSE || TARGET_3DNOW_A" { operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); @@ -19442,7 +20037,7 @@ (define_insn "*sfence_insn" [(set (match_operand:BLK 0 "" "") - (unspec:BLK [(match_dup 0)] 44))] + (unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))] "TARGET_SSE || TARGET_3DNOW_A" "sfence" [(set_attr "type" "sse") @@ -19457,7 +20052,7 @@ (reg:DI 25) (reg:DI 26) (reg:DI 27) - (reg:DI 28)] 13)) + (reg:DI 28)] UNSPEC_SSE_PROLOGUE_SAVE)) (use (match_operand:DI 1 "register_operand" "")) (use (match_operand:DI 2 "immediate_operand" "")) (use (label_ref:DI (match_operand 3 "" "")))])] @@ -19474,7 +20069,7 @@ (reg:DI 25) (reg:DI 26) (reg:DI 27) - (reg:DI 28)] 13)) + (reg:DI 28)] UNSPEC_SSE_PROLOGUE_SAVE)) (use (match_operand:DI 1 "register_operand" "r")) (use (match_operand:DI 2 "const_int_operand" "i")) (use (label_ref:DI (match_operand 3 "" "X")))] @@ -19517,7 +20112,8 @@ (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] "TARGET_3DNOW" "pfadd\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "V2SF")]) (define_insn "subv2sf3" [(set (match_operand:V2SF 0 "register_operand" "=y") @@ -19525,7 +20121,8 @@ (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] "TARGET_3DNOW" "pfsub\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "V2SF")]) (define_insn "subrv2sf3" [(set (match_operand:V2SF 0 "register_operand" "=y") @@ -19533,7 +20130,8 @@ (match_operand:V2SF 1 "register_operand" "0")))] "TARGET_3DNOW" "pfsubr\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "V2SF")]) (define_insn "gtv2sf3" [(set (match_operand:V2SI 0 "register_operand" "=y") @@ -19541,7 +20139,8 @@ (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] "TARGET_3DNOW" "pfcmpgt\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxcmp") + (set_attr "mode" "V2SF")]) (define_insn "gev2sf3" [(set (match_operand:V2SI 0 "register_operand" "=y") @@ -19549,7 +20148,8 @@ (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] "TARGET_3DNOW" "pfcmpge\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxcmp") + (set_attr "mode" "V2SF")]) (define_insn "eqv2sf3" [(set (match_operand:V2SI 0 "register_operand" "=y") @@ -19557,7 +20157,8 @@ (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] "TARGET_3DNOW" "pfcmpeq\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxcmp") + (set_attr "mode" "V2SF")]) (define_insn "pfmaxv2sf3" [(set (match_operand:V2SF 0 "register_operand" "=y") @@ -19565,7 +20166,8 @@ (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] "TARGET_3DNOW" "pfmax\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "V2SF")]) (define_insn "pfminv2sf3" [(set (match_operand:V2SF 0 "register_operand" "=y") @@ -19573,7 +20175,8 @@ (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] "TARGET_3DNOW" "pfmin\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "V2SF")]) (define_insn "mulv2sf3" [(set (match_operand:V2SF 0 "register_operand" "=y") @@ -19581,10 +20184,11 @@ (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] "TARGET_3DNOW" "pfmul\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxmul") + (set_attr "mode" "V2SF")]) (define_insn "femms" - [(unspec_volatile [(const_int 0)] 46) + [(unspec_volatile [(const_int 0)] UNSPECV_FEMMS) (clobber (reg:XF 8)) (clobber (reg:XF 9)) (clobber (reg:XF 10)) @@ -19603,14 +20207,16 @@ (clobber (reg:DI 36))] "TARGET_3DNOW" "femms" - [(set_attr "type" "mmx")]) + [(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" "mmx")]) + [(set_attr "type" "mmxcvt") + (set_attr "mode" "V2SF")]) (define_insn "pf2iw" [(set (match_operand:V2SI 0 "register_operand" "=y") @@ -19619,7 +20225,8 @@ (fix:V2SI (match_operand:V2SF 1 "nonimmediate_operand" "ym")))))] "TARGET_3DNOW_A" "pf2iw\\t{%1, %0|%0, %1}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxcvt") + (set_attr "mode" "V2SF")]) (define_insn "pfacc" [(set (match_operand:V2SF 0 "register_operand" "=y") @@ -19636,7 +20243,8 @@ (parallel [(const_int 1)])))))] "TARGET_3DNOW" "pfacc\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "V2SF")]) (define_insn "pfnacc" [(set (match_operand:V2SF 0 "register_operand" "=y") @@ -19653,7 +20261,8 @@ (parallel [(const_int 1)])))))] "TARGET_3DNOW_A" "pfnacc\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "V2SF")]) (define_insn "pfpnacc" [(set (match_operand:V2SF 0 "register_operand" "=y") @@ -19670,7 +20279,8 @@ (parallel [(const_int 1)])))))] "TARGET_3DNOW_A" "pfpnacc\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxadd") + (set_attr "mode" "V2SF")]) (define_insn "pi2fw" [(set (match_operand:V2SF 0 "register_operand" "=y") @@ -19686,14 +20296,16 @@ (parallel [(const_int 1)])))))))] "TARGET_3DNOW_A" "pi2fw\\t{%1, %0|%0, %1}" - [(set_attr "type" "mmx")]) + [(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" "mmx")]) + [(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. @@ -19702,50 +20314,62 @@ [(set (match_operand:V8QI 0 "register_operand" "=y") (unspec:V8QI [(match_operand:V8QI 1 "register_operand" "0") - (match_operand:V8QI 2 "nonimmediate_operand" "ym")] 49))] + (match_operand:V8QI 2 "nonimmediate_operand" "ym")] + UNSPEC_PAVGUSB))] "TARGET_3DNOW" "pavgusb\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxshft") + (set_attr "mode" "TI")]) ;; 3DNow reciprical and sqrt (define_insn "pfrcpv2sf2" [(set (match_operand:V2SF 0 "register_operand" "=y") - (unspec:V2SF [(match_operand:V2SF 1 "nonimmediate_operand" "ym")] 50))] + (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 "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")] 51))] + (match_operand:V2SF 2 "nonimmediate_operand" "ym")] + UNSPEC_PFRCPIT1))] "TARGET_3DNOW" "pfrcpit1\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(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")] 52))] + (match_operand:V2SF 2 "nonimmediate_operand" "ym")] + UNSPEC_PFRCPIT2))] "TARGET_3DNOW" "pfrcpit2\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(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")] 53))] + (unspec:V2SF [(match_operand:V2SF 1 "nonimmediate_operand" "ym")] + UNSPEC_PFRSQRT))] "TARGET_3DNOW" - "pfrsqrt\\t{%1, %0|%0, %1}" - [(set_attr "type" "mmx")]) + "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")] 54))] + (match_operand:V2SF 2 "nonimmediate_operand" "ym")] + UNSPEC_PFRSQIT1))] "TARGET_3DNOW" "pfrsqit1\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmx") + (set_attr "mode" "TI")]) (define_insn "pmulhrwv4hi3" [(set (match_operand:V4HI 0 "register_operand" "=y") @@ -19764,7 +20388,8 @@ (const_int 16))))] "TARGET_3DNOW" "pmulhrw\\t{%2, %0|%0, %2}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxmul") + (set_attr "mode" "TI")]) (define_insn "pswapdv2si2" [(set (match_operand:V2SI 0 "register_operand" "=y") @@ -19772,7 +20397,8 @@ (parallel [(const_int 1) (const_int 0)])))] "TARGET_3DNOW_A" "pswapd\\t{%1, %0|%0, %1}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxcvt") + (set_attr "mode" "TI")]) (define_insn "pswapdv2sf2" [(set (match_operand:V2SF 0 "register_operand" "=y") @@ -19780,7 +20406,8 @@ (parallel [(const_int 1) (const_int 0)])))] "TARGET_3DNOW_A" "pswapd\\t{%1, %0|%0, %1}" - [(set_attr "type" "mmx")]) + [(set_attr "type" "mmxcvt") + (set_attr "mode" "TI")]) (define_expand "prefetch" [(prefetch (match_operand 0 "address_operand" "") @@ -19843,7 +20470,8 @@ return patterns[locality]; } - [(set_attr "type" "sse")]) + [(set_attr "type" "sse") + (set_attr "memory" "none")]) (define_insn "*prefetch_3dnow" [(prefetch (match_operand:SI 0 "address_operand" "p") @@ -19870,4 +20498,1577 @@ else return "prefetchw\t%a0"; } - [(set_attr "type" "mmx")]) + [(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" +{ + if (GET_CODE (operands[3]) == UNORDERED) + return "cmpordps\t{%2, %0|%0, %2}"; + 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}"; + 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" "ssecmp") + (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" "ssecmp") + (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")]) + +(define_insn "sse2_movntsi" + [(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") + (fix:SI (vec_select:DF (match_operand:V2DF 1 "register_operand" "xm") + (parallel [(const_int 0)]))))] + "TARGET_SSE2" + "cvtsd2si\t{%1, %0|%0, %1}" + [(set_attr "type" "ssecvt") + (set_attr "mode" "SI")]) + +(define_insn "cvtsd2siq" + [(set (match_operand:DI 0 "register_operand" "=r") + (fix:DI (vec_select:DF (match_operand:V2DF 1 "register_operand" "xm") + (parallel [(const_int 0)]))))] + "TARGET_SSE2 && TARGET_64BIT" + "cvtsd2siq\t{%1, %0|%0, %1}" + [(set_attr "type" "ssecvt") + (set_attr "mode" "SI")]) + +(define_insn "cvttsd2si" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(vec_select:DF (match_operand:V2DF 1 "register_operand" "xm") + (parallel [(const_int 0)]))] UNSPEC_FIX))] + "TARGET_SSE2" + "cvttsd2si\t{%1, %0|%0, %1}" + [(set_attr "type" "ssecvt") + (set_attr "mode" "SI")]) + +(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" "ssecvt") + (set_attr "mode" "DI") + (set_attr "athlon_decode" "vector,vector")]) + +(define_insn "cvtsi2sd" + [(set (match_operand:V2DF 0 "register_operand" "=x") + (vec_merge:V2DF (match_operand:V2DF 1 "register_operand" "0") + (vec_duplicate:V2DF + (float:DF + (match_operand:SI 2 "nonimmediate_operand" "rm"))) + (const_int 2)))] + "TARGET_SSE2" + "cvtsi2sd\t{%2, %0|%0, %2}" + [(set_attr "type" "ssecvt") + (set_attr "mode" "DF")]) + +(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" "ssecvt") + (set_attr "mode" "DF") + (set_attr "athlon_decode" "vector,direct")]) + +;; Conversions between SF and DF + +(define_insn "cvtsd2ss" + [(set (match_operand:V4SF 0 "register_operand" "=x") + (vec_merge:V4SF (match_operand:V4SF 1 "register_operand" "0") + (vec_duplicate:V4SF + (float_truncate:V2SF + (match_operand:V2DF 2 "register_operand" "xm"))) + (const_int 14)))] + "TARGET_SSE2" + "cvtsd2ss\t{%2, %0|%0, %2}" + [(set_attr "type" "ssecvt") + (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 "register_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")]) + +(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")]) + +;; SSE2 variants of MMX insns + +;; MMX arithmetic + +(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" + "pxor\t{%0, %0|%0, %0}" + [(set_attr "type" "sseiadd") + (set_attr "memory" "none") + (set_attr "mode" "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 "immediate_operand" "i")))] + "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 "immediate_operand" "i")]))))] + "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:TI 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:TI 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:TI 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:TI 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:TI 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:TI 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:TI 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:TI 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:TI (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:TI (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:TI (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:TI (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:TI (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:TI (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:TI (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:TI (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:V2DF (match_operand:V2DF 1 "register_operand" "0") + (parallel [(const_int 1)])) + (vec_select:V2DF (match_operand:V2DF 2 "register_operand" "x") + (parallel [(const_int 0)]))))] + "TARGET_SSE2" + "unpckhpd\t{%2, %0|%0, %2}" + [(set_attr "type" "ssecvt") + (set_attr "mode" "TI")]) + +(define_insn "sse2_unpcklpd" + [(set (match_operand:V2DF 0 "register_operand" "=x") + (vec_concat:V2DF + (vec_select:V2DF (match_operand:V2DF 1 "register_operand" "0") + (parallel [(const_int 0)])) + (vec_select:V2DF (match_operand:V2DF 2 "register_operand" "x") + (parallel [(const_int 1)]))))] + "TARGET_SSE2" + "unpcklpd\t{%2, %0|%0, %2}" + [(set_attr "type" "ssecvt") + (set_attr "mode" "TI")]) + +;; 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")]) + +(define_insn "sse2_movlpd" + [(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 1)))] + "TARGET_SSE2 && (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)" + "movlpd\t{%2, %0|%0, %2}" + [(set_attr "type" "ssecvt") + (set_attr "mode" "V2DF")]) + +(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))); + 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 "register_operand" "=x") + (vec_merge:V2DF + (match_operand:V2DF 1 "register_operand" "0") + (match_operand:V2DF 2 "register_operand" "x") + (const_int 1)))] + "TARGET_SSE2" + "movsd\t{%2, %0|%0, %2}" + [(set_attr "type" "ssecvt") + (set_attr "mode" "DF")]) + +(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_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 "*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")]) diff --git a/contrib/gcc/config/sparc/freebsd.h b/contrib/gcc/config/sparc/freebsd.h index ad52ef4..2cad3cd 100644 --- a/contrib/gcc/config/sparc/freebsd.h +++ b/contrib/gcc/config/sparc/freebsd.h @@ -1,4 +1,4 @@ -/* Definitions for Sun Sparc64 running FreeBSD using the ELF format +/* Definitions for Sun SPARC64 running FreeBSD using the ELF format Copyright (C) 2001, 2002 Free Software Foundation, Inc. Contributed by David E. O'Brien <obrien@FreeBSD.org> and BSDi. @@ -29,7 +29,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Because we include sparc/sysv4.h. */ #undef CPP_PREDEFINES -#define CPP_PREDEFINES FBSD_CPP_PREDEFINES +/* Do not define it here, we now use TARGET_OS_CPP_BUILTINS. */ #define LINK_SPEC "%(link_arch) \ %{!mno-relax:%{!r:-relax}} \ @@ -55,14 +55,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ We use the GCC defaults instead. */ #undef WCHAR_TYPE -#undef WCHAR_UNSIGNED -#define WCHAR_UNSIGNED 0 - #undef WCHAR_TYPE_SIZE #define WCHAR_TYPE_SIZE 32 -/* Define for support of TFmode long double and REAL_ARITHMETIC. - Sparc ABI says that long double is 4 words. */ +/* Define for support of TFmode long double. + SPARC ABI says that long double is 4 words. */ #undef LONG_DOUBLE_TYPE_SIZE #define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64) diff --git a/contrib/gcc/configure b/contrib/gcc/configure index 89d3372..5f00c79 100755 --- a/contrib/gcc/configure +++ b/contrib/gcc/configure @@ -34,10 +34,15 @@ ac_help="$ac_help --enable-checking[=LIST] enable expensive run-time checks. With LIST, enable only specific categories of checks. - Categories are: misc,tree,rtl,gc,gcac; default - is misc,tree,gc" + Categories are: misc,tree,rtl,rtlflag,gc,gcac; + default is misc,tree,gc,rtlflag" ac_help="$ac_help - --disable-cpp don't provide a user-visible C preprocessor" + --enable-coverage[=LEVEL] + enable compiler\'s code coverage collection. + Use to measure compiler performance and locate + unused parts of the compiler. With LEVEL, specificy + optimization. Values are opt, noopt, + default is noopt" ac_help="$ac_help --with-cpp-install-dir=DIR install the user visible C preprocessor in DIR @@ -59,6 +64,8 @@ ac_help="$ac_help ac_help="$ac_help --with-libiconv-prefix=DIR search for libiconv in DIR/include and DIR/lib" ac_help="$ac_help + --enable-initfini-array use .init_array/.fini_array sections" +ac_help="$ac_help --enable-nls use Native Language Support (default)" ac_help="$ac_help --with-libiconv-prefix=DIR search for libiconv in DIR/include and DIR/lib" @@ -87,6 +94,8 @@ ac_help="$ac_help --enable-sjlj-exceptions arrange to use setjmp/longjmp exception handling" ac_help="$ac_help + --enable-libunwind-exceptions force use libunwind for exceptions" +ac_help="$ac_help --enable-version-specific-runtime-libs specify that runtime libraries should be installed in a compiler-specific directory" @@ -109,7 +118,6 @@ program_suffix=NONE program_transform_name=s,x,x, silent= site= -sitefile= srcdir= target=NONE verbose= @@ -224,7 +232,6 @@ Configuration: --help print this message --no-create do not create output files --quiet, --silent do not print \`checking...' messages - --site-file=FILE use FILE as the site file --version print the version of autoconf that created configure Directory and file names: --prefix=PREFIX install architecture-independent files in PREFIX @@ -395,11 +402,6 @@ EOF -site=* | --site=* | --sit=*) site="$ac_optarg" ;; - -site-file | --site-file | --site-fil | --site-fi | --site-f) - ac_prev=sitefile ;; - -site-file=* | --site-file=* | --site-fil=* | --site-fi=* | --site-f=*) - sitefile="$ac_optarg" ;; - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) @@ -565,16 +567,12 @@ fi srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` # Prefer explicitly selected file to automatically selected ones. -if test -z "$sitefile"; then - if test -z "$CONFIG_SITE"; then - if test "x$prefix" != xNONE; then - CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" - else - CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" - fi +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi -else - CONFIG_SITE="$sitefile" fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then @@ -629,7 +627,7 @@ copy=cp # - two terminals occur directly after each other # - the path contains an element with a dot in it echo $ac_n "checking LIBRARY_PATH variable""... $ac_c" 1>&6 -echo "configure:633: checking LIBRARY_PATH variable" >&5 +echo "configure:631: checking LIBRARY_PATH variable" >&5 case ${LIBRARY_PATH} in [:\;]* | *[:\;] | *[:\;][:\;]* | *[:\;]. | .[:\;]*| . | *[:\;].[:\;]* ) library_path_setting="contains current directory" @@ -654,7 +652,7 @@ fi # - two terminals occur directly after each other # - the path contains an element with a dot in it echo $ac_n "checking GCC_EXEC_PREFIX variable""... $ac_c" 1>&6 -echo "configure:658: checking GCC_EXEC_PREFIX variable" >&5 +echo "configure:656: checking GCC_EXEC_PREFIX variable" >&5 case ${GCC_EXEC_PREFIX} in [:\;]* | *[:\;] | *[:\;][:\;]* | *[:\;]. | .[:\;]*| . | *[:\;].[:\;]* ) gcc_exec_prefix_setting="contains current directory" @@ -793,206 +791,6 @@ if test x${gcc_gxx_include_dir} = x; then fi fi -# Determine whether or not multilibs are enabled. -# Check whether --enable-multilib or --disable-multilib was given. -if test "${enable_multilib+set}" = set; then - enableval="$enable_multilib" - : -else - enable_multilib=yes -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= -ac_tree_checking= -ac_rtl_checking= -ac_gc_checking= -ac_gc_always_collect= -case "${enableval}" in -yes) ac_checking=1 ; ac_tree_checking=1 ; ac_gc_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 ;; - rtl) ac_rtl_checking=1 ;; - gc) ac_gc_checking=1 ;; - gcac) ac_gc_always_collect=1 ;; - *) { echo "configure: error: unknown check category $check" 1>&2; exit 1; } ;; - esac - done - ;; -esac - -fi - -if test x$ac_checking != x ; then - cat >> confdefs.h <<\EOF -#define ENABLE_CHECKING 1 -EOF - -fi -if test x$ac_tree_checking != x ; then - cat >> confdefs.h <<\EOF -#define ENABLE_TREE_CHECKING 1 -EOF - -fi -if test x$ac_rtl_checking != x ; then - cat >> confdefs.h <<\EOF -#define ENABLE_RTL_CHECKING 1 -EOF - -fi -if test x$ac_gc_checking != x ; then - cat >> confdefs.h <<\EOF -#define ENABLE_GC_CHECKING 1 -EOF - -fi -if test x$ac_gc_always_collect != x ; then - cat >> confdefs.h <<\EOF -#define ENABLE_GC_ALWAYS_COLLECT 1 -EOF - -fi - - -# Check whether --enable-cpp or --disable-cpp was given. -if test "${enable_cpp+set}" = set; then - enableval="$enable_cpp" - : -else - enable_cpp=yes -fi - - -# Check whether --with-cpp_install_dir or --without-cpp_install_dir was given. -if test "${with_cpp_install_dir+set}" = set; then - withval="$with_cpp_install_dir" - if test x$withval = xyes; then - { echo "configure: error: option --with-cpp-install-dir requires an argument" 1>&2; exit 1; } -elif test x$withval != xno; then - cpp_install_dir=$withval -fi -fi - - -# Enable __cxa_atexit for C++. -# Check whether --enable-__cxa_atexit or --disable-__cxa_atexit was given. -if test "${enable___cxa_atexit+set}" = set; then - enableval="$enable___cxa_atexit" - : -fi - -if test x$enable___cxa_atexit = xyes; then - cat >> confdefs.h <<\EOF -#define DEFAULT_USE_CXA_ATEXIT 1 -EOF - -fi - -# Enable Multibyte Characters for C/C++ -# Check whether --enable-c-mbchar or --disable-c-mbchar was given. -if test "${enable_c_mbchar+set}" = set; then - enableval="$enable_c_mbchar" - if test x$enable_c_mbchar != xno; then - cat >> confdefs.h <<\EOF -#define MULTIBYTE_CHARS 1 -EOF - -fi -fi - - -# Enable threads -# Pass with no value to take the default -# Pass with a value to specify a thread package -# Check whether --enable-threads or --disable-threads was given. -if test "${enable_threads+set}" = set; then - enableval="$enable_threads" - : -else - enable_threads='' -fi - - -enable_threads_flag=$enable_threads -# Check if a valid thread package -case x${enable_threads_flag} in - x | xno) - # No threads - target_thread_file='single' - ;; - xyes) - # default - target_thread_file='' - ;; - xdecosf1 | xirix | xmach | xos2 | xposix | xpthreads | xsingle | \ - xsolaris | xwin32 | xdce | xrtems| xvxworks | xaix) - target_thread_file=$enable_threads_flag - ;; - *) - echo "$enable_threads is an unknown thread package" 1>&2 - exit 1 - ;; -esac - -# Check whether --enable-objc-gc or --disable-objc-gc was given. -if test "${enable_objc_gc+set}" = set; then - enableval="$enable_objc_gc" - if test x$enable_objc_gc = xno; then - objc_boehm_gc='' -else - objc_boehm_gc=1 -fi -else - objc_boehm_gc='' -fi - - -# Check whether --with-dwarf2 or --without-dwarf2 was given. -if test "${with_dwarf2+set}" = set; then - withval="$with_dwarf2" - dwarf2="$with_dwarf2" -else - dwarf2=no -fi - - -# Check whether --enable-shared or --disable-shared was given. -if test "${enable_shared+set}" = set; then - enableval="$enable_shared" - - case $enable_shared in - yes | no) ;; - *) - enable_shared=no - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," - for pkg in $enableval; do - if test "X$pkg" = "Xgcc" || test "X$pkg" = "Xlibgcc"; then - enable_shared=yes - fi - done - IFS="$ac_save_ifs" - ;; - esac - -else - enable_shared=yes -fi - - - # Determine the host, build, and target systems ac_aux_dir= for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do @@ -1041,7 +839,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } fi echo $ac_n "checking host system type""... $ac_c" 1>&6 -echo "configure:1045: checking host system type" >&5 +echo "configure:843: checking host system type" >&5 host_alias=$host case "$host_alias" in @@ -1062,7 +860,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$host" 1>&6 echo $ac_n "checking target system type""... $ac_c" 1>&6 -echo "configure:1066: checking target system type" >&5 +echo "configure:864: checking target system type" >&5 target_alias=$target case "$target_alias" in @@ -1080,7 +878,7 @@ target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$target" 1>&6 echo $ac_n "checking build system type""... $ac_c" 1>&6 -echo "configure:1084: checking build system type" >&5 +echo "configure:882: checking build system type" >&5 build_alias=$build case "$build_alias" in @@ -1128,7 +926,7 @@ test "$program_transform_name" = "" && program_transform_name="s,x,x," # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1132: checking for $ac_word" >&5 +echo "configure:930: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1158,7 +956,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1162: checking for $ac_word" >&5 +echo "configure:960: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1209,7 +1007,7 @@ fi # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1213: checking for $ac_word" >&5 +echo "configure:1011: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1241,7 +1039,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1245: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:1043: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -1252,12 +1050,12 @@ cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF -#line 1256 "configure" +#line 1054 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:1261: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1059: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -1283,12 +1081,12 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:1287: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:1085: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:1292: checking whether we are using GNU C" >&5 +echo "configure:1090: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1297,7 +1095,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1301: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1099: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -1316,7 +1114,7 @@ ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:1320: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:1118: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1349,10 +1147,10 @@ fi if test "x$CC" != xcc; then echo $ac_n "checking whether $CC and cc understand -c and -o together""... $ac_c" 1>&6 -echo "configure:1353: checking whether $CC and cc understand -c and -o together" >&5 +echo "configure:1151: checking whether $CC and cc understand -c and -o together" >&5 else echo $ac_n "checking whether cc understands -c and -o together""... $ac_c" 1>&6 -echo "configure:1356: checking whether cc understands -c and -o together" >&5 +echo "configure:1154: checking whether cc understands -c and -o together" >&5 fi set dummy $CC; ac_cc="`echo $2 | sed -e 's/[^a-zA-Z0-9_]/_/g' -e 's/^[0-9]/_/'`" @@ -1364,16 +1162,16 @@ else # We do the test twice because some compilers refuse to overwrite an # existing .o file with -o, though they will create one. ac_try='${CC-cc} -c conftest.c -o conftest.o 1>&5' -if { (eval echo configure:1368: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } && - test -f conftest.o && { (eval echo configure:1369: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; +if { (eval echo configure:1166: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } && + test -f conftest.o && { (eval echo configure:1167: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; then eval ac_cv_prog_cc_${ac_cc}_c_o=yes if test "x$CC" != xcc; then # Test first that cc exists at all. - if { ac_try='cc -c conftest.c 1>&5'; { (eval echo configure:1374: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + if { ac_try='cc -c conftest.c 1>&5'; { (eval echo configure:1172: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then ac_try='cc -c conftest.c -o conftest.o 1>&5' - if { (eval echo configure:1376: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } && - test -f conftest.o && { (eval echo configure:1377: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; + if { (eval echo configure:1174: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } && + test -f conftest.o && { (eval echo configure:1175: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; then # cc works too. : @@ -1419,7 +1217,7 @@ fi # 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 $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1423: checking for $ac_word" >&5 +echo "configure:1221: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_GNATBIND'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1451,7 +1249,7 @@ if test -n "$ac_tool_prefix"; then # Extract the first word of "gnatbind", so it can be a program name with args. set dummy gnatbind; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1455: checking for $ac_word" >&5 +echo "configure:1253: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_GNATBIND'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1484,7 +1282,7 @@ fi fi echo $ac_n "checking for compiler driver that understands Ada""... $ac_c" 1>&6 -echo "configure:1488: checking for compiler driver that understands Ada" >&5 +echo "configure:1286: checking for compiler driver that understands Ada" >&5 if eval "test \"`echo '$''{'gcc_cv_prog_adac'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1493,10 +1291,7 @@ procedure conftest is begin null; end conftest; EOF gcc_cv_prog_adac=no # Have to do ac_tool_prefix and user overrides by hand. -user_adac=$ADAC -user_cc=$CC -for cand in ${ac_tool_prefix}$user_adac $user_adac \ - ${ac_tool_prefix}$user_cc $user_cc \ +for cand in ${ADAC+"$ADAC"} ${CC+"$CC"} \ ${ac_tool_prefix}gcc gcc \ ${ac_tool_prefix}cc cc \ ${ac_tool_prefix}gnatgcc gnatgcc \ @@ -1529,21 +1324,21 @@ fi echo $ac_n "checking whether ${CC-cc} accepts -Wno-long-long""... $ac_c" 1>&6 -echo "configure:1533: checking whether ${CC-cc} accepts -Wno-long-long" >&5 +echo "configure:1328: checking whether ${CC-cc} accepts -Wno-long-long" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_no_long_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else save_CFLAGS="$CFLAGS" CFLAGS="-Wno-long-long" cat > conftest.$ac_ext <<EOF -#line 1540 "configure" +#line 1335 "configure" #include "confdefs.h" int main() { ; return 0; } EOF -if { (eval echo configure:1547: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1342: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_prog_cc_no_long_long=yes else @@ -1560,7 +1355,7 @@ echo "$ac_t""$ac_cv_prog_cc_no_long_long" 1>&6 if test x$have_gnat != xno ; then echo $ac_n "checking whether ${ADAC} accepts -Wno-long-long""... $ac_c" 1>&6 -echo "configure:1564: checking whether ${ADAC} accepts -Wno-long-long" >&5 +echo "configure:1359: checking whether ${ADAC} accepts -Wno-long-long" >&5 if eval "test \"`echo '$''{'ac_cv_prog_adac_no_long_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1588,7 +1383,7 @@ fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:1592: checking how to run the C preprocessor" >&5 +echo "configure:1387: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -1603,13 +1398,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext <<EOF -#line 1607 "configure" +#line 1402 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1613: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1408: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1620,13 +1415,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext <<EOF -#line 1624 "configure" +#line 1419 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1630: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1425: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1637,13 +1432,13 @@ else rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext <<EOF -#line 1641 "configure" +#line 1436 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1647: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1442: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1668,21 +1463,21 @@ fi echo "$ac_t""$CPP" 1>&6 echo $ac_n "checking for inline""... $ac_c" 1>&6 -echo "configure:1672: checking for inline" >&5 +echo "configure:1467: checking for inline" >&5 if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat > conftest.$ac_ext <<EOF -#line 1679 "configure" +#line 1474 "configure" #include "confdefs.h" int main() { } $ac_kw foo() { ; return 0; } EOF -if { (eval echo configure:1686: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1481: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_inline=$ac_kw; break else @@ -1708,19 +1503,19 @@ EOF esac echo $ac_n "checking for volatile""... $ac_c" 1>&6 -echo "configure:1712: checking for volatile" >&5 +echo "configure:1507: checking for volatile" >&5 if eval "test \"`echo '$''{'gcc_cv_c_volatile'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1717 "configure" +#line 1512 "configure" #include "confdefs.h" int main() { volatile int foo; ; return 0; } EOF -if { (eval echo configure:1724: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1519: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* gcc_cv_c_volatile=yes else @@ -1742,7 +1537,7 @@ fi echo $ac_n "checking for long double""... $ac_c" 1>&6 -echo "configure:1746: checking for long double" >&5 +echo "configure:1541: checking for long double" >&5 if eval "test \"`echo '$''{'gcc_cv_c_long_double'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1750,7 +1545,7 @@ else gcc_cv_c_long_double=yes else cat > conftest.$ac_ext <<EOF -#line 1754 "configure" +#line 1549 "configure" #include "confdefs.h" int main() { @@ -1760,7 +1555,7 @@ long double foo = 0.0; switch (0) case 0: case (sizeof(long double) >= sizeof(double)):; ; return 0; } EOF -if { (eval echo configure:1764: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1559: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* gcc_cv_c_long_double=yes else @@ -1782,19 +1577,19 @@ EOF fi echo $ac_n "checking for long long int""... $ac_c" 1>&6 -echo "configure:1786: checking for long long int" >&5 +echo "configure:1581: checking for long long int" >&5 if eval "test \"`echo '$''{'ac_cv_c_long_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1791 "configure" +#line 1586 "configure" #include "confdefs.h" int main() { long long int i; ; return 0; } EOF -if { (eval echo configure:1798: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1593: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_long_long=yes else @@ -1814,19 +1609,19 @@ EOF fi echo $ac_n "checking for __int64""... $ac_c" 1>&6 -echo "configure:1818: checking for __int64" >&5 +echo "configure:1613: checking for __int64" >&5 if eval "test \"`echo '$''{'ac_cv_c___int64'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1823 "configure" +#line 1618 "configure" #include "confdefs.h" int main() { __int64 i; ; return 0; } EOF -if { (eval echo configure:1830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1625: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c___int64=yes else @@ -1847,19 +1642,19 @@ EOF fi echo $ac_n "checking for built-in _Bool""... $ac_c" 1>&6 -echo "configure:1851: checking for built-in _Bool" >&5 +echo "configure:1646: checking for built-in _Bool" >&5 if eval "test \"`echo '$''{'gcc_cv_c__bool'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1856 "configure" +#line 1651 "configure" #include "confdefs.h" int main() { _Bool foo; ; return 0; } EOF -if { (eval echo configure:1863: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1658: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* gcc_cv_c__bool=yes else @@ -1883,13 +1678,13 @@ fi # sizeof(char) is 1 by definition. echo $ac_n "checking size of short""... $ac_c" 1>&6 -echo "configure:1887: checking size of short" >&5 +echo "configure:1682: checking size of short" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence. cat > conftest.$ac_ext <<EOF -#line 1893 "configure" +#line 1688 "configure" #include "confdefs.h" #include "confdefs.h" #include <sys/types.h> @@ -1899,7 +1694,7 @@ int main() { switch (0) case 0: case (sizeof (short) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:1903: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1698: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_sizeof_short=$ac_size else @@ -1922,13 +1717,13 @@ EOF echo $ac_n "checking size of int""... $ac_c" 1>&6 -echo "configure:1926: checking size of int" >&5 +echo "configure:1721: checking size of int" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence. cat > conftest.$ac_ext <<EOF -#line 1932 "configure" +#line 1727 "configure" #include "confdefs.h" #include "confdefs.h" #include <sys/types.h> @@ -1938,7 +1733,7 @@ int main() { switch (0) case 0: case (sizeof (int) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:1942: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1737: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_sizeof_int=$ac_size else @@ -1961,13 +1756,13 @@ EOF echo $ac_n "checking size of long""... $ac_c" 1>&6 -echo "configure:1965: checking size of long" >&5 +echo "configure:1760: checking size of long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence. cat > conftest.$ac_ext <<EOF -#line 1971 "configure" +#line 1766 "configure" #include "confdefs.h" #include "confdefs.h" #include <sys/types.h> @@ -1977,7 +1772,7 @@ int main() { switch (0) case 0: case (sizeof (long) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:1981: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1776: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_sizeof_long=$ac_size else @@ -2001,13 +1796,13 @@ EOF if test $ac_cv_c_long_long = yes; then echo $ac_n "checking size of long long""... $ac_c" 1>&6 -echo "configure:2005: checking size of long long" >&5 +echo "configure:1800: checking size of long long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence. cat > conftest.$ac_ext <<EOF -#line 2011 "configure" +#line 1806 "configure" #include "confdefs.h" #include "confdefs.h" #include <sys/types.h> @@ -2017,7 +1812,7 @@ int main() { switch (0) case 0: case (sizeof (long long) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:2021: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1816: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_sizeof_long_long=$ac_size else @@ -2042,13 +1837,13 @@ EOF fi if test $ac_cv_c___int64 = yes; then echo $ac_n "checking size of __int64""... $ac_c" 1>&6 -echo "configure:2046: checking size of __int64" >&5 +echo "configure:1841: checking size of __int64" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof___int64'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence. cat > conftest.$ac_ext <<EOF -#line 2052 "configure" +#line 1847 "configure" #include "confdefs.h" #include "confdefs.h" #include <sys/types.h> @@ -2058,7 +1853,7 @@ int main() { switch (0) case 0: case (sizeof (__int64) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:2062: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1857: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_sizeof___int64=$ac_size else @@ -2083,12 +1878,12 @@ EOF fi echo $ac_n "checking execution character set""... $ac_c" 1>&6 -echo "configure:2087: checking execution character set" >&5 +echo "configure:1882: checking execution character set" >&5 if eval "test \"`echo '$''{'ac_cv_c_charset'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2092 "configure" +#line 1887 "configure" #include "confdefs.h" #if '\n' == 0x0A && ' ' == 0x20 && '0' == 0x30 \ && 'A' == 0x41 && 'a' == 0x61 && '!' == 0x21 @@ -2104,7 +1899,7 @@ rm -f conftest* if test x${ac_cv_c_charset+set} != xset; then cat > conftest.$ac_ext <<EOF -#line 2108 "configure" +#line 1903 "configure" #include "confdefs.h" #if '\n' == 0x15 && ' ' == 0x40 && '0' == 0xF0 \ && 'A' == 0xC1 && 'a' == 0x81 && '!' == 0x5A @@ -2143,6 +1938,314 @@ if test "x$GCC" = "xyes"; then fi +# Determine whether or not multilibs are enabled. +# Check whether --enable-multilib or --disable-multilib was given. +if test "${enable_multilib+set}" = set; then + enableval="$enable_multilib" + : +else + enable_multilib=yes +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= +ac_tree_checking= +ac_rtl_checking= +ac_rtlflag_checking= +ac_gc_checking= +ac_gc_always_collect= +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 ;; + valgrind) ac_checking_valgrind=1 ;; + *) { echo "configure: error: unknown check category $check" 1>&2; exit 1; } ;; + esac + done + ;; +esac + +fi + +nocommon_flag="" +if test x$ac_checking != x ; then + cat >> confdefs.h <<\EOF +#define ENABLE_CHECKING 1 +EOF + + nocommon_flag=-fno-common +fi + +if test x$ac_tree_checking != x ; then + cat >> confdefs.h <<\EOF +#define ENABLE_TREE_CHECKING 1 +EOF + +fi +if test x$ac_rtl_checking != x ; then + cat >> confdefs.h <<\EOF +#define ENABLE_RTL_CHECKING 1 +EOF + +fi +if test x$ac_rtlflag_checking != x ; then + cat >> confdefs.h <<\EOF +#define ENABLE_RTL_FLAG_CHECKING 1 +EOF + +fi +if test x$ac_gc_checking != x ; then + cat >> confdefs.h <<\EOF +#define ENABLE_GC_CHECKING 1 +EOF + +fi +if test x$ac_gc_always_collect != x ; then + cat >> confdefs.h <<\EOF +#define ENABLE_GC_ALWAYS_COLLECT 1 +EOF + +fi +valgrind_path_defines= +valgrind_command= +if test x$ac_checking_valgrind != x ; then + # It is certainly possible that there's valgrind but no valgrind.h. + # GCC relies on making annotations so we must have both. + ac_safe=`echo "valgrind.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for valgrind.h""... $ac_c" 1>&6 +echo "configure:2034: checking for valgrind.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2039 "configure" +#include "confdefs.h" +#include <valgrind.h> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2044: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + have_valgrind_h=yes +else + echo "$ac_t""no" 1>&6 +have_valgrind_h=no +fi + + # Extract the first word of "valgrind", so it can be a program name with args. +set dummy valgrind; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2069: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_valgrind_path'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$valgrind_path" in + /*) + ac_cv_path_valgrind_path="$valgrind_path" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if $ac_dir/$ac_word --version | grep valgrind- >/dev/null 2>&1; then + ac_cv_path_valgrind_path="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +valgrind_path="$ac_cv_path_valgrind_path" +if test -n "$valgrind_path"; then + echo "$ac_t""$valgrind_path" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test "x$valgrind_path" = "x" || test $have_valgrind_h = no; then + { echo "configure: error: *** Can't find both valgrind and valgrind.h" 1>&2; exit 1; } + fi + valgrind_path_defines=-DVALGRIND_PATH='\"'$valgrind_path'\"' + valgrind_command="$valgrind_path -q" + cat >> confdefs.h <<\EOF +#define ENABLE_VALGRIND_CHECKING 1 +EOF + +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 -O0" + ;; +opt) + coverage_flags="-fprofile-arcs -ftest-coverage -O2" + ;; +*) + { echo "configure: error: unknown coverage setting $enableval" 1>&2; exit 1; } + ;; +esac +else + coverage_flags="" +fi + + + +# Check whether --with-cpp_install_dir or --without-cpp_install_dir was given. +if test "${with_cpp_install_dir+set}" = set; then + withval="$with_cpp_install_dir" + if test x$withval = xyes; then + { echo "configure: error: option --with-cpp-install-dir requires an argument" 1>&2; exit 1; } +elif test x$withval != xno; then + cpp_install_dir=$withval +fi +fi + + +# Enable __cxa_atexit for C++. +# Check whether --enable-__cxa_atexit or --disable-__cxa_atexit was given. +if test "${enable___cxa_atexit+set}" = set; then + enableval="$enable___cxa_atexit" + : +fi + +if test x$enable___cxa_atexit = xyes; then + cat >> confdefs.h <<\EOF +#define DEFAULT_USE_CXA_ATEXIT 1 +EOF + +fi + +# Enable Multibyte Characters for C/C++ +# Check whether --enable-c-mbchar or --disable-c-mbchar was given. +if test "${enable_c_mbchar+set}" = set; then + enableval="$enable_c_mbchar" + if test x$enable_c_mbchar != xno; then + cat >> confdefs.h <<\EOF +#define MULTIBYTE_CHARS 1 +EOF + +fi +fi + + +# Enable threads +# Pass with no value to take the default +# Pass with a value to specify a thread package +# Check whether --enable-threads or --disable-threads was given. +if test "${enable_threads+set}" = set; then + enableval="$enable_threads" + : +else + enable_threads='' +fi + + +enable_threads_flag=$enable_threads +# Check if a valid thread package +case x${enable_threads_flag} in + x | xno) + # No threads + target_thread_file='single' + ;; + xyes) + # default + target_thread_file='' + ;; + xdecosf1 | xirix | xmach | xos2 | xposix | xpthreads | xsingle | \ + xsolaris | xwin32 | xdce | xrtems| xvxworks | xaix) + target_thread_file=$enable_threads_flag + ;; + *) + echo "$enable_threads is an unknown thread package" 1>&2 + exit 1 + ;; +esac + +# Check whether --enable-objc-gc or --disable-objc-gc was given. +if test "${enable_objc_gc+set}" = set; then + enableval="$enable_objc_gc" + if test x$enable_objc_gc = xno; then + objc_boehm_gc='' +else + objc_boehm_gc=1 +fi +else + objc_boehm_gc='' +fi + + +# Check whether --with-dwarf2 or --without-dwarf2 was given. +if test "${with_dwarf2+set}" = set; then + withval="$with_dwarf2" + dwarf2="$with_dwarf2" +else + dwarf2=no +fi + + +# Check whether --enable-shared or --disable-shared was given. +if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + + case $enable_shared in + yes | no) ;; + *) + enable_shared=no + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "Xgcc" || test "X$pkg" = "Xlibgcc"; then + enable_shared=yes + fi + done + IFS="$ac_save_ifs" + ;; + esac + +else + enable_shared=yes +fi + + + # Stage specific cflags for build. stage1_cflags= case $build in @@ -2165,7 +2268,7 @@ esac echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -echo "configure:2169: checking whether ${MAKE-make} sets \${MAKE}" >&5 +echo "configure:2272: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2193,7 +2296,7 @@ fi echo $ac_n "checking whether a default assembler was specified""... $ac_c" 1>&6 -echo "configure:2197: checking whether a default assembler was specified" >&5 +echo "configure:2300: checking whether a default assembler was specified" >&5 if test x"${DEFAULT_ASSEMBLER+set}" = x"set"; then if test x"$gas_flag" = x"no"; then echo "$ac_t""yes ($DEFAULT_ASSEMBLER)" 1>&6 @@ -2205,7 +2308,7 @@ else fi echo $ac_n "checking whether a default linker was specified""... $ac_c" 1>&6 -echo "configure:2209: checking whether a default linker was specified" >&5 +echo "configure:2312: checking whether a default linker was specified" >&5 if test x"${DEFAULT_LINKER+set}" = x"set"; then if test x"$gnu_ld_flag" = x"no"; then echo "$ac_t""yes ($DEFAULT_LINKER)" 1>&6 @@ -2217,12 +2320,12 @@ else fi echo $ac_n "checking for GNU C library""... $ac_c" 1>&6 -echo "configure:2221: checking for GNU C library" >&5 +echo "configure:2324: checking for GNU C library" >&5 if eval "test \"`echo '$''{'gcc_cv_glibc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2226 "configure" +#line 2329 "configure" #include "confdefs.h" #include <features.h> int main() { @@ -2232,7 +2335,7 @@ int main() { #endif ; return 0; } EOF -if { (eval echo configure:2236: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2339: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* gcc_cv_glibc=yes else @@ -2258,7 +2361,7 @@ 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 $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2262: checking for $ac_word" >&5 +echo "configure:2365: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2288,7 +2391,7 @@ test -n "$AWK" && break done echo $ac_n "checking whether ln works""... $ac_c" 1>&6 -echo "configure:2292: checking whether ln works" >&5 +echo "configure:2395: checking whether ln works" >&5 if eval "test \"`echo '$''{'gcc_cv_prog_LN'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2320,7 +2423,7 @@ else fi echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 -echo "configure:2324: checking whether ln -s works" >&5 +echo "configure:2427: checking whether ln -s works" >&5 if eval "test \"`echo '$''{'gcc_cv_prog_LN_S'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2354,7 +2457,7 @@ fi # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2358: checking for $ac_word" >&5 +echo "configure:2461: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2392,7 +2495,7 @@ fi # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:2396: checking for a BSD compatible install" >&5 +echo "configure:2499: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2443,12 +2546,12 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:2447: checking for ANSI C header files" >&5 +echo "configure:2550: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2452 "configure" +#line 2555 "configure" #include "confdefs.h" #include <stdlib.h> #include <stdarg.h> @@ -2456,7 +2559,7 @@ else #include <float.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2460: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2563: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2473,7 +2576,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext <<EOF -#line 2477 "configure" +#line 2580 "configure" #include "confdefs.h" #include <string.h> EOF @@ -2491,7 +2594,7 @@ 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 <<EOF -#line 2495 "configure" +#line 2598 "configure" #include "confdefs.h" #include <stdlib.h> EOF @@ -2512,7 +2615,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext <<EOF -#line 2516 "configure" +#line 2619 "configure" #include "confdefs.h" #include <ctype.h> #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -2523,7 +2626,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:2527: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2630: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -2547,12 +2650,12 @@ EOF fi echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 -echo "configure:2551: checking whether time.h and sys/time.h may both be included" >&5 +echo "configure:2654: checking whether time.h and sys/time.h may both be included" >&5 if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2556 "configure" +#line 2659 "configure" #include "confdefs.h" #include <sys/types.h> #include <sys/time.h> @@ -2561,7 +2664,7 @@ int main() { struct tm *tp; ; return 0; } EOF -if { (eval echo configure:2565: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2668: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_time=yes else @@ -2582,19 +2685,19 @@ EOF fi echo $ac_n "checking for working stdbool.h""... $ac_c" 1>&6 -echo "configure:2586: checking for working stdbool.h" >&5 +echo "configure:2689: checking for working stdbool.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdbool_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2591 "configure" +#line 2694 "configure" #include "confdefs.h" #include <stdbool.h> int main() { bool foo = false; ; return 0; } EOF -if { (eval echo configure:2598: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2701: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_stdbool_h=yes else @@ -2615,12 +2718,12 @@ EOF fi echo $ac_n "checking whether string.h and strings.h may both be included""... $ac_c" 1>&6 -echo "configure:2619: checking whether string.h and strings.h may both be included" >&5 +echo "configure:2722: checking whether string.h and strings.h may both be included" >&5 if eval "test \"`echo '$''{'gcc_cv_header_string'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2624 "configure" +#line 2727 "configure" #include "confdefs.h" #include <string.h> #include <strings.h> @@ -2628,7 +2731,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:2632: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2735: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* gcc_cv_header_string=yes else @@ -2649,12 +2752,12 @@ EOF fi echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6 -echo "configure:2653: checking for sys/wait.h that is POSIX.1 compatible" >&5 +echo "configure:2756: checking for sys/wait.h that is POSIX.1 compatible" >&5 if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2658 "configure" +#line 2761 "configure" #include "confdefs.h" #include <sys/types.h> #include <sys/wait.h> @@ -2670,7 +2773,7 @@ wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } EOF -if { (eval echo configure:2674: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_sys_wait_h=yes else @@ -2691,23 +2794,23 @@ EOF fi for ac_hdr in limits.h stddef.h string.h strings.h stdlib.h time.h \ - fcntl.h unistd.h sys/file.h sys/time.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 do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:2701: checking for $ac_hdr" >&5 +echo "configure:2804: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2706 "configure" +#line 2809 "configure" #include "confdefs.h" #include <$ac_hdr> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2711: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2814: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2737,17 +2840,17 @@ done # Check for thread headers. ac_safe=`echo "thread.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for thread.h""... $ac_c" 1>&6 -echo "configure:2741: checking for thread.h" >&5 +echo "configure:2844: checking for thread.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2746 "configure" +#line 2849 "configure" #include "confdefs.h" #include <thread.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2751: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2854: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2771,17 +2874,17 @@ fi ac_safe=`echo "pthread.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for pthread.h""... $ac_c" 1>&6 -echo "configure:2775: checking for pthread.h" >&5 +echo "configure:2878: checking for pthread.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2780 "configure" +#line 2883 "configure" #include "confdefs.h" #include <pthread.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2785: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2888: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2806,12 +2909,12 @@ fi # These tests can't be done till we know if we have limits.h. echo $ac_n "checking for CHAR_BIT""... $ac_c" 1>&6 -echo "configure:2810: checking for CHAR_BIT" >&5 +echo "configure:2913: checking for CHAR_BIT" >&5 if eval "test \"`echo '$''{'gcc_cv_decl_char_bit'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2815 "configure" +#line 2918 "configure" #include "confdefs.h" #ifdef HAVE_LIMITS_H #include <limits.h> @@ -2836,7 +2939,7 @@ fi echo "$ac_t""$gcc_cv_decl_char_bit" 1>&6 if test $gcc_cv_decl_char_bit = no; then echo $ac_n "checking number of bits in a byte""... $ac_c" 1>&6 -echo "configure:2840: checking number of bits in a byte" >&5 +echo "configure:2943: checking number of bits in a byte" >&5 if eval "test \"`echo '$''{'gcc_cv_c_nbby'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2844,7 +2947,7 @@ else gcc_cv_c_nbby= while test $i -lt 65; do cat > conftest.$ac_ext <<EOF -#line 2848 "configure" +#line 2951 "configure" #include "confdefs.h" int main() { @@ -2854,7 +2957,7 @@ switch(0) { ; } ; return 0; } EOF -if { (eval echo configure:2858: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2961: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* gcc_cv_c_nbby=$i; break else @@ -2879,7 +2982,7 @@ EOF fi fi echo $ac_n "checking byte ordering""... $ac_c" 1>&6 -echo "configure:2883: checking byte ordering" >&5 +echo "configure:2986: checking byte ordering" >&5 if eval "test \"`echo '$''{'ac_cv_c_compile_endian'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2893,7 +2996,7 @@ ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$a cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext <<EOF -#line 2897 "configure" +#line 3000 "configure" #include "confdefs.h" #ifdef HAVE_LIMITS_H @@ -2913,7 +3016,7 @@ cat > conftest.$ac_ext <<EOF 'X', '\n' }; EOF -if { (eval echo configure:2917: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3020: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then od -c conftest.o | sed 's/^[0-7]*[ ]*/ / s/\*/./g @@ -2952,7 +3055,7 @@ EOF fi echo $ac_n "checking floating point format""... $ac_c" 1>&6 -echo "configure:2956: checking floating point format" >&5 +echo "configure:3059: checking floating point format" >&5 if eval "test \"`echo '$''{'ac_cv_c_float_format'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2965,7 +3068,7 @@ ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$a cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext <<EOF -#line 2969 "configure" +#line 3072 "configure" #include "confdefs.h" /* This will not work unless sizeof(double) == 8. */ extern char sizeof_double_must_be_8 [sizeof(double) == 8 ? 1 : -1]; @@ -2987,7 +3090,7 @@ struct possibility table [] = C(-5.22995989424860458374e+10) /* IBMHEXFP - s/390 format, EBCDIC */ }; EOF -if { (eval echo configure:2991: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3094: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then od -c conftest.o | sed 's/^[0-7]*[ ]*/ / s/\*/./g @@ -3076,7 +3179,7 @@ fi # Extract the first word of "mktemp", so it can be a program name with args. set dummy mktemp; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3080: checking for $ac_word" >&5 +echo "configure:3183: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_have_mktemp_command'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3115,7 +3218,7 @@ else # Extract the first word of "makeinfo", so it can be a program name with args. set dummy makeinfo; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3119: checking for $ac_word" >&5 +echo "configure:3222: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_MAKEINFO'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3144,16 +3247,16 @@ fi if test -n "$MAKEINFO"; then # Found it, now check the version. echo $ac_n "checking for modern makeinfo""... $ac_c" 1>&6 -echo "configure:3148: checking for modern makeinfo" >&5 +echo "configure:3251: checking for modern makeinfo" >&5 if eval "test \"`echo '$''{'gcc_cv_prog_makeinfo_modern'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_prog_version=`$MAKEINFO --version 2>&1 | sed -n 's/^.*GNU texinfo.* \([0-9][0-9.]*\).*$/\1/p'` - echo "configure:3154: version of makeinfo is $ac_prog_version" >&5 + echo "configure:3257: version of makeinfo is $ac_prog_version" >&5 case $ac_prog_version in '') gcc_cv_prog_makeinfo_modern=no;; - 4.[1-9]*) + 4.[2-9]*) gcc_cv_prog_makeinfo_modern=yes;; *) gcc_cv_prog_makeinfo_modern=no;; esac @@ -3178,7 +3281,7 @@ fi # Is pod2man recent enough to regenerate manpages? echo $ac_n "checking for recent Pod::Man""... $ac_c" 1>&6 -echo "configure:3182: checking for recent Pod::Man" >&5 +echo "configure:3285: checking for recent Pod::Man" >&5 if (perl -e 'use 1.10 Pod::Man') >/dev/null 2>&1; then echo "$ac_t""yes" 1>&6 GENERATED_MANPAGES=generated-manpages @@ -3194,7 +3297,7 @@ else # Extract the first word of "flex", so it can be a program name with args. set dummy flex; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3198: checking for $ac_word" >&5 +echo "configure:3301: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_FLEX'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3211,7 +3314,7 @@ else fi done IFS="$ac_save_ifs" - test -z "$ac_cv_prog_FLEX" && ac_cv_prog_FLEX="false" + test -z "$ac_cv_prog_FLEX" && ac_cv_prog_FLEX="${CONFIG_SHELL-/bin/sh} ${srcdir}/../missing flex" fi fi FLEX="$ac_cv_prog_FLEX" @@ -3231,7 +3334,7 @@ else # Extract the first word of "bison", so it can be a program name with args. set dummy bison; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3235: checking for $ac_word" >&5 +echo "configure:3338: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_BISON'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3248,7 +3351,7 @@ else fi done IFS="$ac_save_ifs" - test -z "$ac_cv_prog_BISON" && ac_cv_prog_BISON="false" + test -z "$ac_cv_prog_BISON" && ac_cv_prog_BISON="${CONFIG_SHELL-/bin/sh} ${srcdir}/../missing bison" fi fi BISON="$ac_cv_prog_BISON" @@ -3263,7 +3366,7 @@ fi # These libraries may be used by collect2. # We may need a special search path to get them linked. echo $ac_n "checking for collect2 libraries""... $ac_c" 1>&6 -echo "configure:3267: checking for collect2 libraries" >&5 +echo "configure:3370: checking for collect2 libraries" >&5 if eval "test \"`echo '$''{'gcc_cv_collect2_libs'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3274,7 +3377,7 @@ for libs in '' -lld -lmld \ do LIBS="$libs" cat > conftest.$ac_ext <<EOF -#line 3278 "configure" +#line 3381 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -3285,7 +3388,7 @@ int main() { ldopen() ; return 0; } EOF -if { (eval echo configure:3289: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3392: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* gcc_cv_collect2_libs="$libs"; break else @@ -3311,14 +3414,14 @@ save_LIBS="$LIBS" LIBS= echo $ac_n "checking for library containing exc_resume""... $ac_c" 1>&6 -echo "configure:3315: checking for library containing exc_resume" >&5 +echo "configure:3418: checking for library containing exc_resume" >&5 if eval "test \"`echo '$''{'ac_cv_search_exc_resume'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_func_search_save_LIBS="$LIBS" ac_cv_search_exc_resume="no" cat > conftest.$ac_ext <<EOF -#line 3322 "configure" +#line 3425 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -3329,7 +3432,7 @@ int main() { exc_resume() ; return 0; } EOF -if { (eval echo configure:3333: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3436: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_exc_resume="none required" else @@ -3340,7 +3443,7 @@ rm -f conftest* test "$ac_cv_search_exc_resume" = "no" && for i in exc; do LIBS="-l$i $ac_func_search_save_LIBS" cat > conftest.$ac_ext <<EOF -#line 3344 "configure" +#line 3447 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -3351,7 +3454,7 @@ int main() { exc_resume() ; return 0; } EOF -if { (eval echo configure:3355: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3458: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_exc_resume="-l$i" break @@ -3375,17 +3478,87 @@ GNAT_LIBEXC="$LIBS" LIBS="$save_LIBS" +# Some systems put ldexp and frexp in libm instead of libc; assume +# they're both in the same place. jcf-dump needs them. +save_LIBS="$LIBS" +LIBS= + +echo $ac_n "checking for library containing ldexp""... $ac_c" 1>&6 +echo "configure:3488: checking for library containing ldexp" >&5 +if eval "test \"`echo '$''{'ac_cv_search_ldexp'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_func_search_save_LIBS="$LIBS" +ac_cv_search_ldexp="no" +cat > conftest.$ac_ext <<EOF +#line 3495 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char ldexp(); + +int main() { +ldexp() +; return 0; } +EOF +if { (eval echo configure:3506: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_search_ldexp="none required" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +test "$ac_cv_search_ldexp" = "no" && for i in m; do +LIBS="-l$i $ac_func_search_save_LIBS" +cat > conftest.$ac_ext <<EOF +#line 3517 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char ldexp(); + +int main() { +ldexp() +; return 0; } +EOF +if { (eval echo configure:3528: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_search_ldexp="-l$i" +break +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +done +LIBS="$ac_func_search_save_LIBS" +fi + +echo "$ac_t""$ac_cv_search_ldexp" 1>&6 +if test "$ac_cv_search_ldexp" != "no"; then + test "$ac_cv_search_ldexp" = "none required" || LIBS="$ac_cv_search_ldexp $LIBS" + +else : + +fi +LDEXP_LIB="$LIBS" +LIBS="$save_LIBS" + + # See if the stage1 system preprocessor understands the ANSI C # preprocessor stringification operator. (Used by symcat.h.) echo $ac_n "checking for preprocessor stringizing operator""... $ac_c" 1>&6 -echo "configure:3384: checking for preprocessor stringizing operator" >&5 +echo "configure:3557: checking for preprocessor stringizing operator" >&5 if eval "test \"`echo '$''{'ac_cv_c_stringize'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3389 "configure" +#line 3562 "configure" #include "confdefs.h" #define x(y) #y @@ -3418,12 +3591,12 @@ echo "$ac_t""${ac_cv_c_stringize}" 1>&6 # Use <inttypes.h> only if it exists, # doesn't clash with <sys/types.h>, and declares intmax_t. echo $ac_n "checking for inttypes.h""... $ac_c" 1>&6 -echo "configure:3422: checking for inttypes.h" >&5 +echo "configure:3595: checking for inttypes.h" >&5 if eval "test \"`echo '$''{'gcc_cv_header_inttypes_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3427 "configure" +#line 3600 "configure" #include "confdefs.h" #include <sys/types.h> #include <inttypes.h> @@ -3431,7 +3604,7 @@ int main() { intmax_t i = -1; ; return 0; } EOF -if { (eval echo configure:3435: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3608: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* gcc_cv_header_inttypes_h=yes else @@ -3454,15 +3627,16 @@ 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 lstat + fwrite_unlocked fprintf_unlocked getrusage nl_langinfo lstat \ + scandir alphasort gettimeofday mmap do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3461: checking for $ac_func" >&5 +echo "configure:3635: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3466 "configure" +#line 3640 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -3485,7 +3659,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:3489: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3663: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3511,12 +3685,12 @@ done echo $ac_n "checking for ssize_t""... $ac_c" 1>&6 -echo "configure:3515: checking for ssize_t" >&5 +echo "configure:3689: checking for ssize_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_ssize_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3520 "configure" +#line 3694 "configure" #include "confdefs.h" #include <sys/types.h> #if STDC_HEADERS @@ -3547,12 +3721,12 @@ fi # Try to determine the array type of the second argument of getgroups # for the target system (int or gid_t). echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 -echo "configure:3551: checking for uid_t in sys/types.h" >&5 +echo "configure:3725: checking for uid_t in sys/types.h" >&5 if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3556 "configure" +#line 3730 "configure" #include "confdefs.h" #include <sys/types.h> EOF @@ -3581,7 +3755,7 @@ EOF fi echo $ac_n "checking type of array argument to getgroups""... $ac_c" 1>&6 -echo "configure:3585: checking type of array argument to getgroups" >&5 +echo "configure:3759: checking type of array argument to getgroups" >&5 if eval "test \"`echo '$''{'ac_cv_type_getgroups'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3589,7 +3763,7 @@ else ac_cv_type_getgroups=cross else cat > conftest.$ac_ext <<EOF -#line 3593 "configure" +#line 3767 "configure" #include "confdefs.h" /* Thanks to Mike Rendell for this test. */ @@ -3614,7 +3788,7 @@ main() } EOF -if { (eval echo configure:3618: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:3792: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_type_getgroups=gid_t else @@ -3628,7 +3802,7 @@ fi if test $ac_cv_type_getgroups = cross; then cat > conftest.$ac_ext <<EOF -#line 3632 "configure" +#line 3806 "configure" #include "confdefs.h" #include <unistd.h> EOF @@ -3669,7 +3843,7 @@ fi echo $ac_n "checking whether the printf functions support %p""... $ac_c" 1>&6 -echo "configure:3673: checking whether the printf functions support %p" >&5 +echo "configure:3847: checking whether the printf functions support %p" >&5 if eval "test \"`echo '$''{'gcc_cv_func_printf_ptr'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3677,7 +3851,7 @@ else gcc_cv_func_printf_ptr=no else cat > conftest.$ac_ext <<EOF -#line 3681 "configure" +#line 3855 "configure" #include "confdefs.h" #include <stdio.h> @@ -3690,7 +3864,7 @@ int main() return (p != q); } EOF -if { (eval echo configure:3694: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:3868: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then gcc_cv_func_printf_ptr=yes else @@ -3713,6 +3887,135 @@ EOF fi +if test $ac_cv_header_sys_mman_h != yes \ + || test $ac_cv_func_mmap != yes; then + gcc_cv_func_mmap_file=no + gcc_cv_func_mmap_dev_zero=no + gcc_cv_func_mmap_anon=no +else + echo $ac_n "checking whether read-only mmap of a plain file works""... $ac_c" 1>&6 +echo "configure:3898: checking whether read-only mmap of a plain file works" >&5 +if eval "test \"`echo '$''{'gcc_cv_func_mmap_file'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # Add a system to this blacklist if + # mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a + # memory area containing the same data that you'd get if you applied + # read() to the same fd. The only system known to have a problem here + # is VMS, where text files have record structure. + case "$host_os" in + vms*) + gcc_cv_func_mmap_file=no ;; + *) + gcc_cv_func_mmap_file=yes;; + esac +fi + +echo "$ac_t""$gcc_cv_func_mmap_file" 1>&6 + echo $ac_n "checking whether mmap from /dev/zero works""... $ac_c" 1>&6 +echo "configure:3917: checking whether mmap from /dev/zero works" >&5 +if eval "test \"`echo '$''{'gcc_cv_func_mmap_dev_zero'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # Add a system to this blacklist if it has mmap() but /dev/zero + # does not exist, or if mmapping /dev/zero does not give anonymous + # zeroed pages with both the following properties: + # 1. If you map N consecutive pages in with one call, and then + # unmap any subset of those pages, the pages that were not + # explicitly unmapped remain accessible. + # 2. If you map two adjacent blocks of memory and then unmap them + # both at once, they must both go away. + # Systems known to be in this category are Windows (all variants), + # VMS, and Darwin. + case "$host_os" in + vms* | cygwin* | pe | mingw* | darwin*) + gcc_cv_func_mmap_dev_zero=no ;; + *) + gcc_cv_func_mmap_dev_zero=yes;; + esac +fi + +echo "$ac_t""$gcc_cv_func_mmap_dev_zero" 1>&6 + + # Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for. + echo $ac_n "checking for MAP_ANON(YMOUS)""... $ac_c" 1>&6 +echo "configure:3943: checking for MAP_ANON(YMOUS)" >&5 +if eval "test \"`echo '$''{'gcc_cv_decl_map_anon'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3948 "configure" +#include "confdefs.h" +#include <sys/types.h> +#include <sys/mman.h> +#include <unistd.h> + +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + +int main() { +int n = MAP_ANONYMOUS; +; return 0; } +EOF +if { (eval echo configure:3962: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + gcc_cv_decl_map_anon=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gcc_cv_decl_map_anon=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gcc_cv_decl_map_anon" 1>&6 + + if test $gcc_cv_decl_map_anon = no; then + gcc_cv_func_mmap_anon=no + else + echo $ac_n "checking whether mmap with MAP_ANON(YMOUS) works""... $ac_c" 1>&6 +echo "configure:3980: checking whether mmap with MAP_ANON(YMOUS) works" >&5 +if eval "test \"`echo '$''{'gcc_cv_func_mmap_anon'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # Add a system to this blacklist if it has mmap() and MAP_ANON or + # MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) + # doesn't give anonymous zeroed pages with the same properties listed + # above for use of /dev/zero. + # Systems known to be in this category are Windows, VMS, and SCO Unix. + case "$host_os" in + vms* | cygwin* | pe | mingw* | sco* | udk* ) + gcc_cv_func_mmap_anon=no ;; + *) + gcc_cv_func_mmap_anon=yes;; + esac +fi + +echo "$ac_t""$gcc_cv_func_mmap_anon" 1>&6 + fi +fi + +if test $gcc_cv_func_mmap_file = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MMAP_FILE 1 +EOF + +fi +if test $gcc_cv_func_mmap_dev_zero = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MMAP_DEV_ZERO 1 +EOF + +fi +if test $gcc_cv_func_mmap_anon = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MMAP_ANON 1 +EOF + +fi + case "${host}" in *-*-uwin*) @@ -3728,12 +4031,12 @@ case "${host}" in ;; esac echo $ac_n "checking for pid_t""... $ac_c" 1>&6 -echo "configure:3732: checking for pid_t" >&5 +echo "configure:4035: checking for pid_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3737 "configure" +#line 4040 "configure" #include "confdefs.h" #include <sys/types.h> #if STDC_HEADERS @@ -3762,17 +4065,17 @@ fi ac_safe=`echo "vfork.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for vfork.h""... $ac_c" 1>&6 -echo "configure:3766: checking for vfork.h" >&5 +echo "configure:4069: checking for vfork.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3771 "configure" +#line 4074 "configure" #include "confdefs.h" #include <vfork.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3776: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4079: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -3797,18 +4100,18 @@ else fi echo $ac_n "checking for working vfork""... $ac_c" 1>&6 -echo "configure:3801: checking for working vfork" >&5 +echo "configure:4104: checking for working vfork" >&5 if eval "test \"`echo '$''{'ac_cv_func_vfork_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then echo $ac_n "checking for vfork""... $ac_c" 1>&6 -echo "configure:3807: checking for vfork" >&5 +echo "configure:4110: checking for vfork" >&5 if eval "test \"`echo '$''{'ac_cv_func_vfork'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3812 "configure" +#line 4115 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char vfork(); below. */ @@ -3831,7 +4134,7 @@ vfork(); ; return 0; } EOF -if { (eval echo configure:3835: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4138: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_vfork=yes" else @@ -3853,7 +4156,7 @@ fi ac_cv_func_vfork_works=$ac_cv_func_vfork else cat > conftest.$ac_ext <<EOF -#line 3857 "configure" +#line 4160 "configure" #include "confdefs.h" /* Thanks to Paul Eggert for this test. */ #include <stdio.h> @@ -3948,7 +4251,7 @@ main() { } } EOF -if { (eval echo configure:3952: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4255: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_func_vfork_works=yes else @@ -3970,472 +4273,6 @@ EOF fi -for ac_func in getpagesize -do -echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3977: checking for $ac_func" >&5 -if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext <<EOF -#line 3982 "configure" -#include "confdefs.h" -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func(); below. */ -#include <assert.h> -/* Override any gcc2 internal prototype to avoid an error. */ -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char $ac_func(); - -int main() { - -/* 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_$ac_func) || defined (__stub___$ac_func) -choke me -#else -$ac_func(); -#endif - -; return 0; } -EOF -if { (eval echo configure:4005: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_func_$ac_func=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_func_$ac_func=no" -fi -rm -f conftest* -fi - -if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` - cat >> confdefs.h <<EOF -#define $ac_tr_func 1 -EOF - -else - echo "$ac_t""no" 1>&6 -fi -done - -# The test program for the next two tests is the same except for one -# set of ifdefs. -cat >ct-mmap.inc <<'EOF' -#include <sys/types.h> -#include <sys/mman.h> -#include <fcntl.h> -#include <signal.h> -#include <setjmp.h> -#include <stdio.h> - -#if !defined (MAP_ANONYMOUS) && defined (MAP_ANON) -# define MAP_ANONYMOUS MAP_ANON -#endif - -/* This mess was copied from the GNU getpagesize.h. */ -#ifndef HAVE_GETPAGESIZE -# ifdef HAVE_UNISTD_H -# include <unistd.h> -# endif - -/* Assume that all systems that can run configure have sys/param.h. */ -# ifndef HAVE_SYS_PARAM_H -# define HAVE_SYS_PARAM_H 1 -# endif - -# ifdef _SC_PAGESIZE -# define getpagesize() sysconf(_SC_PAGESIZE) -# else /* no _SC_PAGESIZE */ -# ifdef HAVE_SYS_PARAM_H -# include <sys/param.h> -# ifdef EXEC_PAGESIZE -# define getpagesize() EXEC_PAGESIZE -# else /* no EXEC_PAGESIZE */ -# ifdef NBPG -# define getpagesize() NBPG * CLSIZE -# ifndef CLSIZE -# define CLSIZE 1 -# endif /* no CLSIZE */ -# else /* no NBPG */ -# ifdef NBPC -# define getpagesize() NBPC -# else /* no NBPC */ -# ifdef PAGESIZE -# define getpagesize() PAGESIZE -# endif /* PAGESIZE */ -# endif /* no NBPC */ -# endif /* no NBPG */ -# endif /* no EXEC_PAGESIZE */ -# else /* no HAVE_SYS_PARAM_H */ -# define getpagesize() 8192 /* punt totally */ -# endif /* no HAVE_SYS_PARAM_H */ -# endif /* no _SC_PAGESIZE */ - -#endif /* no HAVE_GETPAGESIZE */ - -#ifndef MAP_FAILED -# define MAP_FAILED -1 -#endif - -#undef perror_exit -#define perror_exit(str, val) \ - do { perror(str); exit(val); } while (0) - -/* Some versions of cygwin mmap require that munmap is called with the - same parameters as mmap. GCC expects that this is not the case. - Test for various forms of this problem. Warning - icky signal games. */ - -static sigset_t unblock_sigsegv; -static jmp_buf r; -static size_t pg; -static int devzero; - -static char * -anonmap (size) - size_t size; -{ -#ifdef USE_MAP_ANON - return (char *) mmap (0, size, PROT_READ|PROT_WRITE, - MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); -#else - return (char *) mmap (0, size, PROT_READ|PROT_WRITE, - MAP_PRIVATE, devzero, 0); -#endif -} - -static void -sigsegv (unused) - int unused; -{ - sigprocmask (SIG_UNBLOCK, &unblock_sigsegv, 0); - longjmp (r, 1); -} - -/* Basic functionality test. */ -void -test_0 () -{ - char *x = anonmap (pg); - if (x == (char *) MAP_FAILED) - perror_exit("test 0 mmap", 2); - - *(int *)x += 1; - - if (munmap(x, pg) < 0) - perror_exit("test 0 munmap", 3); -} - -/* 1. If we map a 2-page region and unmap its second page, the first page - must remain. */ -static void -test_1 () -{ - char *x = anonmap (pg * 2); - if (x == (char *)MAP_FAILED) - perror_exit ("test 1 mmap", 4); - - signal (SIGSEGV, sigsegv); - if (setjmp (r)) - perror_exit ("test 1 fault", 5); - - x[0] = 1; - x[pg] = 1; - - if (munmap (x + pg, pg) < 0) - perror_exit ("test 1 munmap 1", 6); - x[0] = 2; - - if (setjmp (r) == 0) - { - x[pg] = 1; - perror_exit ("test 1 no fault", 7); - } - if (munmap (x, pg) < 0) - perror_exit ("test 1 munmap 2", 8); -} - -/* 2. If we map a 2-page region and unmap its first page, the second - page must remain. */ -static void -test_2 () -{ - char *x = anonmap (pg * 2); - if (x == (char *)MAP_FAILED) - perror_exit ("test 2 mmap", 9); - - signal (SIGSEGV, sigsegv); - if (setjmp (r)) - perror_exit ("test 2 fault", 10); - - x[0] = 1; - x[pg] = 1; - - if (munmap (x, pg) < 0) - perror_exit ("test 2 munmap 1", 11); - - x[pg] = 2; - - if (setjmp (r) == 0) - { - x[0] = 1; - perror_exit ("test 2 no fault", 12); - } - - if (munmap (x+pg, pg) < 0) - perror_exit ("test 2 munmap 2", 13); -} - -/* 3. If we map two adjacent 1-page regions and unmap them both with - one munmap, both must go away. - - Getting two adjacent 1-page regions with two mmap calls is slightly - tricky. All OS's tested skip over already-allocated blocks; therefore - we have been careful to unmap all allocated regions in previous tests. - HP/UX allocates pages backward in memory. No OS has yet been observed - to be so perverse as to leave unmapped space between consecutive calls - to mmap. */ - -static void -test_3 () -{ - char *x, *y, *z; - - x = anonmap (pg); - if (x == (char *)MAP_FAILED) - perror_exit ("test 3 mmap 1", 14); - y = anonmap (pg); - if (y == (char *)MAP_FAILED) - perror_exit ("test 3 mmap 2", 15); - - if (y != x + pg) - { - if (y == x - pg) - z = y, y = x, x = z; - else - { - fprintf (stderr, "test 3 nonconsecutive pages - %lx, %lx\n", - (unsigned long)x, (unsigned long)y); - exit (16); - } - } - - signal (SIGSEGV, sigsegv); - if (setjmp (r)) - perror_exit ("test 3 fault", 17); - - x[0] = 1; - y[0] = 1; - - if (munmap (x, pg*2) < 0) - perror_exit ("test 3 munmap", 18); - - if (setjmp (r) == 0) - { - x[0] = 1; - perror_exit ("test 3 no fault 1", 19); - } - - signal (SIGSEGV, sigsegv); - if (setjmp (r) == 0) - { - y[0] = 1; - perror_exit ("test 3 no fault 2", 20); - } -} - -int -main () -{ - sigemptyset (&unblock_sigsegv); - sigaddset (&unblock_sigsegv, SIGSEGV); - pg = getpagesize (); -#ifndef USE_MAP_ANON - devzero = open ("/dev/zero", O_RDWR); - if (devzero < 0) - perror_exit ("open /dev/zero", 1); -#endif - - test_0(); - test_1(); - test_2(); - test_3(); - - exit(0); -} -EOF - -echo $ac_n "checking for working mmap from /dev/zero""... $ac_c" 1>&6 -echo "configure:4276: checking for working mmap from /dev/zero" >&5 -if eval "test \"`echo '$''{'ac_cv_func_mmap_dev_zero'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - # If this is not cygwin, and /dev/zero is a character device, it's probably - # safe to assume it works. - case "$host_os" in - cygwin* | win32 | pe | mingw* ) ac_cv_func_mmap_dev_zero=buggy ;; - * ) if test -c /dev/zero - then ac_cv_func_mmap_dev_zero=yes - else ac_cv_func_mmap_dev_zero=no - fi ;; - esac -else - cat > conftest.$ac_ext <<EOF -#line 4292 "configure" -#include "confdefs.h" -#include "ct-mmap.inc" -EOF -if { (eval echo configure:4296: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null -then - ac_cv_func_mmap_dev_zero=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - if test $? -lt 4 - then ac_cv_func_mmap_dev_zero=no - else ac_cv_func_mmap_dev_zero=buggy - fi -fi -rm -fr conftest* -fi - - -fi - -echo "$ac_t""$ac_cv_func_mmap_dev_zero" 1>&6 -if test $ac_cv_func_mmap_dev_zero = yes; then - cat >> confdefs.h <<\EOF -#define HAVE_MMAP_DEV_ZERO 1 -EOF - -fi - -echo $ac_n "checking for working mmap with MAP_ANON(YMOUS)""... $ac_c" 1>&6 -echo "configure:4323: checking for working mmap with MAP_ANON(YMOUS)" >&5 -if eval "test \"`echo '$''{'ac_cv_func_mmap_anon'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - # Unlike /dev/zero, it is not safe to assume MAP_ANON(YMOUS) works - # just because it's there. Some SCO Un*xen define it but don't implement it. - ac_cv_func_mmap_anon=no -else - cat > conftest.$ac_ext <<EOF -#line 4333 "configure" -#include "confdefs.h" -#define USE_MAP_ANON -#include "ct-mmap.inc" -EOF -if { (eval echo configure:4338: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null -then - ac_cv_func_mmap_anon=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - if test $? -lt 4 - then ac_cv_func_mmap_anon=no - else ac_cv_func_mmap_anon=buggy - fi -fi -rm -fr conftest* -fi - - -fi - -echo "$ac_t""$ac_cv_func_mmap_anon" 1>&6 -if test $ac_cv_func_mmap_anon = yes; then - cat >> confdefs.h <<\EOF -#define HAVE_MMAP_ANON 1 -EOF - -fi -rm -f ct-mmap.inc - -echo $ac_n "checking for working mmap of a file""... $ac_c" 1>&6 -echo "configure:4366: checking for working mmap of a file" >&5 -if eval "test \"`echo '$''{'ac_cv_func_mmap_file'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - # Create a file one thousand bytes long. -for i in 1 2 3 4 5 6 7 8 9 0 -do for j in 1 2 3 4 5 6 7 8 9 0 -do echo $i $j xxxxx -done -done > conftestdata$$ - -if test "$cross_compiling" = yes; then - ac_cv_func_mmap_file=no -else - cat > conftest.$ac_ext <<EOF -#line 4381 "configure" -#include "confdefs.h" - -/* Test by Zack Weinberg. Modified from MMAP_ANYWHERE test by - Richard Henderson and Alexandre Oliva. - Check whether read-only mmap of a plain file works. */ -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/mman.h> - -int main() -{ - char *x; - int fd; - struct stat st; - - fd = open("conftestdata$$", O_RDONLY); - if (fd < 0) - exit(1); - - if (fstat (fd, &st)) - exit(2); - - x = (char*)mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (x == (char *) -1) - exit(3); - - if (x[0] != '1' || x[1] != ' ' || x[2] != '1' || x[3] != ' ') - exit(4); - - if (munmap(x, st.st_size) < 0) - exit(5); - - exit(0); -} -EOF -if { (eval echo configure:4418: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null -then - ac_cv_func_mmap_file=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - ac_cv_func_mmap_file=no -fi -rm -fr conftest* -fi - -fi - -echo "$ac_t""$ac_cv_func_mmap_file" 1>&6 -if test $ac_cv_func_mmap_file = yes; then - cat >> confdefs.h <<\EOF -#define HAVE_MMAP_FILE 1 -EOF - -fi - @@ -4453,7 +4290,7 @@ fi echo $ac_n "checking for iconv""... $ac_c" 1>&6 -echo "configure:4457: checking for iconv" >&5 +echo "configure:4294: checking for iconv" >&5 if eval "test \"`echo '$''{'am_cv_func_iconv'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -4461,7 +4298,7 @@ else am_cv_func_iconv="no, consider installing GNU libiconv" am_cv_lib_iconv=no cat > conftest.$ac_ext <<EOF -#line 4465 "configure" +#line 4302 "configure" #include "confdefs.h" #include <stdlib.h> #include <iconv.h> @@ -4471,7 +4308,7 @@ iconv_t cd = iconv_open("",""); iconv_close(cd); ; return 0; } EOF -if { (eval echo configure:4475: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4312: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* am_cv_func_iconv=yes else @@ -4483,7 +4320,7 @@ rm -f conftest* am_save_LIBS="$LIBS" LIBS="$LIBS $am_cv_libiconv_ldpath -liconv" cat > conftest.$ac_ext <<EOF -#line 4487 "configure" +#line 4324 "configure" #include "confdefs.h" #include <stdlib.h> #include <iconv.h> @@ -4493,7 +4330,7 @@ iconv_t cd = iconv_open("",""); iconv_close(cd); ; return 0; } EOF -if { (eval echo configure:4497: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4334: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* am_cv_lib_iconv=yes am_cv_func_iconv=yes @@ -4514,13 +4351,13 @@ echo "$ac_t""$am_cv_func_iconv" 1>&6 EOF echo $ac_n "checking for iconv declaration""... $ac_c" 1>&6 -echo "configure:4518: checking for iconv declaration" >&5 +echo "configure:4355: checking for iconv declaration" >&5 if eval "test \"`echo '$''{'am_cv_proto_iconv'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4524 "configure" +#line 4361 "configure" #include "confdefs.h" #include <stdlib.h> @@ -4539,7 +4376,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:4543: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4380: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* am_cv_proto_iconv_arg1="" else @@ -4572,17 +4409,17 @@ 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 \ + fprintf_unlocked strstr errno vasprintf \ malloc realloc calloc free basename getopt clock do ac_tr_decl=HAVE_DECL_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` echo $ac_n "checking whether $ac_func is declared""... $ac_c" 1>&6 -echo "configure:4581: checking whether $ac_func is declared" >&5 +echo "configure:4418: checking whether $ac_func is declared" >&5 if eval "test \"`echo '$''{'gcc_cv_have_decl_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4586 "configure" +#line 4423 "configure" #include "confdefs.h" #undef $ac_tr_decl #define $ac_tr_decl 1 @@ -4596,7 +4433,7 @@ char *(*pfn) = (char *(*)) $ac_func ; #endif ; return 0; } EOF -if { (eval echo configure:4600: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4437: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "gcc_cv_have_decl_$ac_func=yes" else @@ -4666,6 +4503,9 @@ EOF cat >> confdefs.h <<\EOF #define HAVE_DECL_ERRNO 1 EOF + cat >> confdefs.h <<\EOF +#define HAVE_DECL_VASPRINTF 1 +EOF \ cat >> confdefs.h <<\EOF #define HAVE_DECL_MALLOC 1 @@ -4695,12 +4535,12 @@ for ac_func in getrlimit setrlimit getrusage do ac_tr_decl=HAVE_DECL_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` echo $ac_n "checking whether $ac_func is declared""... $ac_c" 1>&6 -echo "configure:4699: checking whether $ac_func is declared" >&5 +echo "configure:4539: checking whether $ac_func is declared" >&5 if eval "test \"`echo '$''{'gcc_cv_have_decl_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4704 "configure" +#line 4544 "configure" #include "confdefs.h" #undef $ac_tr_decl #define $ac_tr_decl 1 @@ -4718,7 +4558,7 @@ char *(*pfn) = (char *(*)) $ac_func ; #endif ; return 0; } EOF -if { (eval echo configure:4722: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4562: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "gcc_cv_have_decl_$ac_func=yes" else @@ -4756,16 +4596,43 @@ EOF fi +cat > conftest.$ac_ext <<EOF +#line 4601 "configure" +#include "confdefs.h" + +#include "ansidecl.h" +#include "system.h" +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif + +int main() { +rlim_t l = 0; +; return 0; } +EOF +if { (eval echo configure:4614: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + cat >> confdefs.h <<\EOF +#define rlim_t long +EOF + +fi +rm -f conftest* + for ac_func in times do ac_tr_decl=HAVE_DECL_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` echo $ac_n "checking whether $ac_func is declared""... $ac_c" 1>&6 -echo "configure:4764: checking whether $ac_func is declared" >&5 +echo "configure:4631: checking whether $ac_func is declared" >&5 if eval "test \"`echo '$''{'gcc_cv_have_decl_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4769 "configure" +#line 4636 "configure" #include "confdefs.h" #undef $ac_tr_decl #define $ac_tr_decl 1 @@ -4783,7 +4650,7 @@ char *(*pfn) = (char *(*)) $ac_func ; #endif ; return 0; } EOF -if { (eval echo configure:4787: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4654: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "gcc_cv_have_decl_$ac_func=yes" else @@ -4817,13 +4684,13 @@ fi # More time-related stuff. echo $ac_n "checking for struct tms""... $ac_c" 1>&6 -echo "configure:4821: checking for struct tms" >&5 +echo "configure:4688: checking for struct tms" >&5 if eval "test \"`echo '$''{'ac_cv_struct_tms'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4827 "configure" +#line 4694 "configure" #include "confdefs.h" #include "ansidecl.h" @@ -4836,7 +4703,7 @@ int main() { struct tms tms; ; return 0; } EOF -if { (eval echo configure:4840: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4707: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tms=yes else @@ -4859,13 +4726,13 @@ fi # use gcc_cv_* here because this doesn't match the behavior of AC_CHECK_TYPE. # revisit after autoconf 2.50. echo $ac_n "checking for clock_t""... $ac_c" 1>&6 -echo "configure:4863: checking for clock_t" >&5 +echo "configure:4730: checking for clock_t" >&5 if eval "test \"`echo '$''{'gcc_cv_type_clock_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4869 "configure" +#line 4736 "configure" #include "confdefs.h" #include "ansidecl.h" @@ -4875,7 +4742,7 @@ int main() { clock_t x; ; return 0; } EOF -if { (eval echo configure:4879: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4746: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* gcc_cv_type_clock_t=yes else @@ -4895,17 +4762,57 @@ EOF fi +# Check whether --enable-initfini-array or --disable-initfini-array was given. +if test "${enable_initfini_array+set}" = set; then + enableval="$enable_initfini_array" + gcc_cv_initfinit_array=$enableval +else + echo $ac_n "checking for .preinit_array/.init_array/.fini_array support""... $ac_c" 1>&6 +echo "configure:4772: checking for .preinit_array/.init_array/.fini_array support" >&5 +if eval "test \"`echo '$''{'gcc_cv_initfinit_array'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <<EOF +static int x = -1; +int main (void) { return x; } +int foo (void) { x = 0; } +int (*fp) (void) __attribute__ ((section (".init_array"))) = foo; +EOF + if { ac_try='${CC-cc} -o conftest conftest.c 1>&AS_MESSAGE_LOG_FD'; { (eval echo configure:4782: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } + then + if ./conftest; then + gcc_cv_initfinit_array=yes + else + gcc_cv_initfinit_array=no + fi + else + gcc_cv_initfinit_array=no + fi + rm -f conftest* +fi + +echo "$ac_t""$gcc_cv_initfinit_array" 1>&6 + + if test $gcc_cv_initfinit_array = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_INITFINI_ARRAY 1 +EOF + + fi +fi + + # Restore CFLAGS from before the gcc_AC_NEED_DECLARATIONS tests. CFLAGS="$saved_CFLAGS" # mkdir takes a single argument on some systems. echo $ac_n "checking if mkdir takes one argument""... $ac_c" 1>&6 -echo "configure:4904: checking if mkdir takes one argument" >&5 +echo "configure:4811: checking if mkdir takes one argument" >&5 if eval "test \"`echo '$''{'gcc_cv_mkdir_takes_one_arg'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4909 "configure" +#line 4816 "configure" #include "confdefs.h" #include <sys/types.h> @@ -4922,7 +4829,7 @@ int main() { mkdir ("foo", 0); ; return 0; } EOF -if { (eval echo configure:4926: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4833: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* gcc_cv_mkdir_takes_one_arg=no else @@ -4949,6 +4856,7 @@ objext='.o' +target_gtfiles= build_xm_file= build_xm_defines= build_install_headers_dir=install-headers-tar @@ -4990,21 +4898,6 @@ if test x"$dwarf2" = xyes then tm_file="$tm_file tm-dwarf2.h" fi -if test x$float_format = x -then float_format=i64 -fi - -if test $float_format = none -then float_h_file=Makefile.in -else float_h_file=float-$float_format.h -fi - -# Handle cpp installation. -if test x$enable_cpp != xno -then - tmake_file="$tmake_file t-install-cpp" -fi - # Say what files are being used for the output code and MD file. echo "Using \`$srcdir/config/$out_file' for machine-specific logic." echo "Using \`$srcdir/config/$md_file' as machine description file." @@ -5092,6 +4985,20 @@ if test x$thread_file = x; then fi fi +# Look for a file containing extra machine modes. +if test -n "$extra_modes" && test -f $srcdir/config/$extra_modes; then + extra_modes_file='$(srcdir)'/config/${extra_modes} + + cat >> confdefs.h <<EOF +#define EXTRA_MODES_FILE "$extra_modes" +EOF + + cat >> confdefs.h <<\EOF +#define EXTRA_CC_MODES 1 +EOF + +fi + # 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 hconfig include auto-host.h @@ -5126,7 +5033,7 @@ else cd .. rm -rf $tempdir build_auto=auto-build.h - FORBUILD=../$build + FORBUILD=../$build_alias fi @@ -5190,14 +5097,14 @@ fi echo $ac_n "checking for library containing strerror""... $ac_c" 1>&6 -echo "configure:5194: checking for library containing strerror" >&5 +echo "configure:5101: checking for library containing strerror" >&5 if eval "test \"`echo '$''{'ac_cv_search_strerror'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_func_search_save_LIBS="$LIBS" ac_cv_search_strerror="no" cat > conftest.$ac_ext <<EOF -#line 5201 "configure" +#line 5108 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -5208,7 +5115,7 @@ int main() { strerror() ; return 0; } EOF -if { (eval echo configure:5212: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5119: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_strerror="none required" else @@ -5219,7 +5126,7 @@ rm -f conftest* test "$ac_cv_search_strerror" = "no" && for i in cposix; do LIBS="-l$i $ac_func_search_save_LIBS" cat > conftest.$ac_ext <<EOF -#line 5223 "configure" +#line 5130 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -5230,7 +5137,7 @@ int main() { strerror() ; return 0; } EOF -if { (eval echo configure:5234: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5141: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_strerror="-l$i" break @@ -5253,12 +5160,12 @@ fi echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:5257: checking for working const" >&5 +echo "configure:5164: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5262 "configure" +#line 5169 "configure" #include "confdefs.h" int main() { @@ -5307,7 +5214,7 @@ ccp = (char const *const *) p; ; return 0; } EOF -if { (eval echo configure:5311: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5218: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -5328,12 +5235,12 @@ EOF fi echo $ac_n "checking for off_t""... $ac_c" 1>&6 -echo "configure:5332: checking for off_t" >&5 +echo "configure:5239: checking for off_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5337 "configure" +#line 5244 "configure" #include "confdefs.h" #include <sys/types.h> #if STDC_HEADERS @@ -5361,12 +5268,12 @@ EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:5365: checking for size_t" >&5 +echo "configure:5272: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5370 "configure" +#line 5277 "configure" #include "confdefs.h" #include <sys/types.h> #if STDC_HEADERS @@ -5396,19 +5303,19 @@ fi # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 -echo "configure:5400: checking for working alloca.h" >&5 +echo "configure:5307: checking for working alloca.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5405 "configure" +#line 5312 "configure" #include "confdefs.h" #include <alloca.h> int main() { char *p = alloca(2 * sizeof(int)); ; return 0; } EOF -if { (eval echo configure:5412: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5319: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_header_alloca_h=yes else @@ -5429,12 +5336,12 @@ EOF fi echo $ac_n "checking for alloca""... $ac_c" 1>&6 -echo "configure:5433: checking for alloca" >&5 +echo "configure:5340: checking for alloca" >&5 if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5438 "configure" +#line 5345 "configure" #include "confdefs.h" #ifdef __GNUC__ @@ -5462,7 +5369,7 @@ int main() { char *p = (char *) alloca(1); ; return 0; } EOF -if { (eval echo configure:5466: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5373: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_func_alloca_works=yes else @@ -5494,12 +5401,12 @@ EOF echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 -echo "configure:5498: checking whether alloca needs Cray hooks" >&5 +echo "configure:5405: checking whether alloca needs Cray hooks" >&5 if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5503 "configure" +#line 5410 "configure" #include "confdefs.h" #if defined(CRAY) && ! defined(CRAY2) webecray @@ -5524,12 +5431,12 @@ echo "$ac_t""$ac_cv_os_cray" 1>&6 if test $ac_cv_os_cray = yes; then for ac_func in _getb67 GETB67 getb67; do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:5528: checking for $ac_func" >&5 +echo "configure:5435: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5533 "configure" +#line 5440 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -5552,7 +5459,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:5556: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5463: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -5579,7 +5486,7 @@ done fi echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 -echo "configure:5583: checking stack direction for C alloca" >&5 +echo "configure:5490: checking stack direction for C alloca" >&5 if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -5587,7 +5494,7 @@ else ac_cv_c_stack_direction=0 else cat > conftest.$ac_ext <<EOF -#line 5591 "configure" +#line 5498 "configure" #include "confdefs.h" find_stack_direction () { @@ -5606,7 +5513,7 @@ main () exit (find_stack_direction() < 0); } EOF -if { (eval echo configure:5610: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:5517: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_c_stack_direction=1 else @@ -5629,12 +5536,12 @@ fi echo $ac_n "checking whether we are using the GNU C Library 2.1 or newer""... $ac_c" 1>&6 -echo "configure:5633: checking whether we are using the GNU C Library 2.1 or newer" >&5 +echo "configure:5540: checking whether we are using the GNU C Library 2.1 or newer" >&5 if eval "test \"`echo '$''{'ac_cv_gnu_library_2_1'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5638 "configure" +#line 5545 "configure" #include "confdefs.h" #include <features.h> @@ -5670,17 +5577,17 @@ stdlib.h string.h unistd.h sys/param.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:5674: checking for $ac_hdr" >&5 +echo "configure:5581: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5679 "configure" +#line 5586 "configure" #include "confdefs.h" #include <$ac_hdr> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5684: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5591: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -5711,12 +5618,12 @@ getgid getuid mempcpy munmap putenv setenv setlocale stpcpy strchr strcasecmp \ strdup strtoul tsearch __argz_count __argz_stringify __argz_next do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:5715: checking for $ac_func" >&5 +echo "configure:5622: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5720 "configure" +#line 5627 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -5739,7 +5646,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:5743: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5650: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -5780,7 +5687,7 @@ fi echo $ac_n "checking for iconv""... $ac_c" 1>&6 -echo "configure:5784: checking for iconv" >&5 +echo "configure:5691: checking for iconv" >&5 if eval "test \"`echo '$''{'am_cv_func_iconv'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -5788,7 +5695,7 @@ else am_cv_func_iconv="no, consider installing GNU libiconv" am_cv_lib_iconv=no cat > conftest.$ac_ext <<EOF -#line 5792 "configure" +#line 5699 "configure" #include "confdefs.h" #include <stdlib.h> #include <iconv.h> @@ -5798,7 +5705,7 @@ iconv_t cd = iconv_open("",""); iconv_close(cd); ; return 0; } EOF -if { (eval echo configure:5802: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5709: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* am_cv_func_iconv=yes else @@ -5810,7 +5717,7 @@ rm -f conftest* am_save_LIBS="$LIBS" LIBS="$LIBS $am_cv_libiconv_ldpath -liconv" cat > conftest.$ac_ext <<EOF -#line 5814 "configure" +#line 5721 "configure" #include "confdefs.h" #include <stdlib.h> #include <iconv.h> @@ -5820,7 +5727,7 @@ iconv_t cd = iconv_open("",""); iconv_close(cd); ; return 0; } EOF -if { (eval echo configure:5824: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5731: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* am_cv_lib_iconv=yes am_cv_func_iconv=yes @@ -5841,13 +5748,13 @@ echo "$ac_t""$am_cv_func_iconv" 1>&6 EOF echo $ac_n "checking for iconv declaration""... $ac_c" 1>&6 -echo "configure:5845: checking for iconv declaration" >&5 +echo "configure:5752: checking for iconv declaration" >&5 if eval "test \"`echo '$''{'am_cv_proto_iconv'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5851 "configure" +#line 5758 "configure" #include "confdefs.h" #include <stdlib.h> @@ -5866,7 +5773,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:5870: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* am_cv_proto_iconv_arg1="" else @@ -5895,19 +5802,19 @@ EOF echo $ac_n "checking for nl_langinfo and CODESET""... $ac_c" 1>&6 -echo "configure:5899: checking for nl_langinfo and CODESET" >&5 +echo "configure:5806: checking for nl_langinfo and CODESET" >&5 if eval "test \"`echo '$''{'am_cv_langinfo_codeset'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5904 "configure" +#line 5811 "configure" #include "confdefs.h" #include <langinfo.h> int main() { char* cs = nl_langinfo(CODESET); ; return 0; } EOF -if { (eval echo configure:5911: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5818: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* am_cv_langinfo_codeset=yes else @@ -5930,19 +5837,19 @@ EOF if test $ac_cv_header_locale_h = yes; then echo $ac_n "checking for LC_MESSAGES""... $ac_c" 1>&6 -echo "configure:5934: checking for LC_MESSAGES" >&5 +echo "configure:5841: checking for LC_MESSAGES" >&5 if eval "test \"`echo '$''{'am_cv_val_LC_MESSAGES'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5939 "configure" +#line 5846 "configure" #include "confdefs.h" #include <locale.h> int main() { return LC_MESSAGES ; return 0; } EOF -if { (eval echo configure:5946: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5853: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* am_cv_val_LC_MESSAGES=yes else @@ -5963,7 +5870,7 @@ EOF fi fi echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6 -echo "configure:5967: checking whether NLS is requested" >&5 +echo "configure:5874: checking whether NLS is requested" >&5 # Check whether --enable-nls or --disable-nls was given. if test "${enable_nls+set}" = set; then enableval="$enable_nls" @@ -5986,7 +5893,7 @@ fi EOF echo $ac_n "checking whether included gettext is requested""... $ac_c" 1>&6 -echo "configure:5990: checking whether included gettext is requested" >&5 +echo "configure:5897: checking whether included gettext is requested" >&5 # Check whether --with-included-gettext or --without-included-gettext was given. if test "${with_included_gettext+set}" = set; then withval="$with_included_gettext" @@ -6006,17 +5913,17 @@ fi ac_safe=`echo "libintl.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for libintl.h""... $ac_c" 1>&6 -echo "configure:6010: checking for libintl.h" >&5 +echo "configure:5917: checking for libintl.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 6015 "configure" +#line 5922 "configure" #include "confdefs.h" #include <libintl.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6020: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5927: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -6037,12 +5944,12 @@ if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then EOF echo $ac_n "checking for GNU gettext in libc""... $ac_c" 1>&6 -echo "configure:6041: checking for GNU gettext in libc" >&5 +echo "configure:5948: checking for GNU gettext in libc" >&5 if eval "test \"`echo '$''{'gt_cv_func_gnugettext1_libc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 6046 "configure" +#line 5953 "configure" #include "confdefs.h" #include <libintl.h> extern int _nl_msg_cat_cntr; @@ -6051,7 +5958,7 @@ bindtextdomain ("", ""); return (int) gettext ("") + _nl_msg_cat_cntr ; return 0; } EOF -if { (eval echo configure:6055: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5962: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* gt_cv_func_gnugettext1_libc=yes else @@ -6067,14 +5974,14 @@ echo "$ac_t""$gt_cv_func_gnugettext1_libc" 1>&6 if test "$gt_cv_func_gnugettext1_libc" != "yes"; then echo $ac_n "checking for GNU gettext in libintl""... $ac_c" 1>&6 -echo "configure:6071: checking for GNU gettext in libintl" >&5 +echo "configure:5978: checking for GNU gettext in libintl" >&5 if eval "test \"`echo '$''{'gt_cv_func_gnugettext1_libintl'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else gt_save_LIBS="$LIBS" LIBS="$LIBS -lintl $LIBICONV" cat > conftest.$ac_ext <<EOF -#line 6078 "configure" +#line 5985 "configure" #include "confdefs.h" #include <libintl.h> extern int _nl_msg_cat_cntr; @@ -6083,7 +5990,7 @@ bindtextdomain ("", ""); return (int) gettext ("") + _nl_msg_cat_cntr ; return 0; } EOF -if { (eval echo configure:6087: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5994: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* gt_cv_func_gnugettext1_libintl=yes else @@ -6116,12 +6023,12 @@ EOF for ac_func in dcgettext do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:6120: checking for $ac_func" >&5 +echo "configure:6027: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 6125 "configure" +#line 6032 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -6144,7 +6051,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:6148: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6055: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -6173,7 +6080,7 @@ done # Extract the first word of "msgfmt", so it can be a program name with args. set dummy msgfmt; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:6177: checking for $ac_word" >&5 +echo "configure:6084: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6207,7 +6114,7 @@ fi # Extract the first word of "gmsgfmt", so it can be a program name with args. set dummy gmsgfmt; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:6211: checking for $ac_word" >&5 +echo "configure:6118: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6244,7 +6151,7 @@ fi # Extract the first word of "xgettext", so it can be a program name with args. set dummy xgettext; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:6248: checking for $ac_word" >&5 +echo "configure:6155: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6294,7 +6201,7 @@ fi # Extract the first word of "msgfmt", so it can be a program name with args. set dummy msgfmt; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:6298: checking for $ac_word" >&5 +echo "configure:6205: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6328,7 +6235,7 @@ fi # Extract the first word of "gmsgfmt", so it can be a program name with args. set dummy gmsgfmt; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:6332: checking for $ac_word" >&5 +echo "configure:6239: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6364,7 +6271,7 @@ fi # Extract the first word of "xgettext", so it can be a program name with args. set dummy xgettext; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:6368: checking for $ac_word" >&5 +echo "configure:6275: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6436,7 +6343,7 @@ 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 $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:6440: checking for $ac_word" >&5 +echo "configure:6347: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_INTLBISON'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6469,7 +6376,7 @@ done ac_verc_fail=yes else echo $ac_n "checking version of bison""... $ac_c" 1>&6 -echo "configure:6473: checking version of bison" >&5 +echo "configure:6380: checking version of bison" >&5 ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` case $ac_prog_version in '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; @@ -6514,7 +6421,7 @@ EOF if test "x$CATOBJEXT" != x; then echo $ac_n "checking for catalogs to be installed""... $ac_c" 1>&6 -echo "configure:6518: checking for catalogs to be installed" >&5 +echo "configure:6425: checking for catalogs to be installed" >&5 # Look for .po and .gmo files in the source directory. CATALOGS= XLINGUAS= @@ -6572,7 +6479,7 @@ fi case $host_os in win32 | pe | cygwin* | mingw32* | uwin*) echo $ac_n "checking whether windows registry support is requested""... $ac_c" 1>&6 -echo "configure:6576: checking whether windows registry support is requested" >&5 +echo "configure:6483: checking whether windows registry support is requested" >&5 if test "x$enable_win32_registry" != xno; then cat >> confdefs.h <<\EOF #define ENABLE_WIN32_REGISTRY 1 @@ -6581,14 +6488,14 @@ EOF echo "$ac_t""yes" 1>&6 echo $ac_n "checking for library containing RegOpenKeyExA""... $ac_c" 1>&6 -echo "configure:6585: checking for library containing RegOpenKeyExA" >&5 +echo "configure:6492: checking for library containing RegOpenKeyExA" >&5 if eval "test \"`echo '$''{'ac_cv_search_RegOpenKeyExA'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_func_search_save_LIBS="$LIBS" ac_cv_search_RegOpenKeyExA="no" cat > conftest.$ac_ext <<EOF -#line 6592 "configure" +#line 6499 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -6599,7 +6506,7 @@ int main() { RegOpenKeyExA() ; return 0; } EOF -if { (eval echo configure:6603: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6510: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_RegOpenKeyExA="none required" else @@ -6610,7 +6517,7 @@ rm -f conftest* test "$ac_cv_search_RegOpenKeyExA" = "no" && for i in advapi32; do LIBS="-l$i $ac_func_search_save_LIBS" cat > conftest.$ac_ext <<EOF -#line 6614 "configure" +#line 6521 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -6621,7 +6528,7 @@ int main() { RegOpenKeyExA() ; return 0; } EOF -if { (eval echo configure:6625: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6532: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_RegOpenKeyExA="-l$i" break @@ -6663,7 +6570,7 @@ esac if test "x$enable_win32_registry" != xno; then echo $ac_n "checking registry key on windows hosts""... $ac_c" 1>&6 -echo "configure:6667: checking registry key on windows hosts" >&5 +echo "configure:6574: checking registry key on windows hosts" >&5 cat >> confdefs.h <<EOF #define WIN32_REGISTRY_KEY "$gcc_cv_win32_registry_key" EOF @@ -6674,9 +6581,9 @@ fi esac # Get an absolute path to the GCC top-level source directory -holddir=`pwd` +holddir=`${PWDCMD-pwd}` cd $srcdir -topdir=`pwd` +topdir=`${PWDCMD-pwd}` cd $holddir # Conditionalize the makefile for this host machine. @@ -6738,7 +6645,7 @@ for f in $tm_file; do ansidecl.h ) tm_file_list="${tm_file_list} \$(srcdir)/../include/ansidecl.h" ;; defaults.h ) - tm_file_list="${tm_file_list} $f" ;; + tm_file_list="${tm_file_list} \$(srcdir)/$f" ;; *) tm_file_list="${tm_file_list} \$(srcdir)/config/$f" ;; esac done @@ -6753,8 +6660,10 @@ for f in $host_xm_file; do case $f in ansidecl.h ) host_xm_file_list="${host_xm_file_list} \$(srcdir)/../include/ansidecl.h" ;; - auto-host.h | defaults.h ) + auto-host.h ) host_xm_file_list="${host_xm_file_list} $f" ;; + defaults.h ) + host_xm_file_list="${host_xm_file_list} \$(srcdir)/$f" ;; *) host_xm_file_list="${host_xm_file_list} \$(srcdir)/config/$f" ;; esac done @@ -6764,8 +6673,10 @@ for f in $build_xm_file; do case $f in ansidecl.h ) build_xm_file_list="${build_xm_file_list} \$(srcdir)/../include/ansidecl.h" ;; - auto-build.h | auto-host.h | defaults.h ) + auto-build.h | auto-host.h ) build_xm_file_list="${build_xm_file_list} $f" ;; + defaults.h ) + host_xm_file_list="${host_xm_file_list} \$(srcdir)/$f" ;; *) build_xm_file_list="${build_xm_file_list} \$(srcdir)/config/$f" ;; esac done @@ -6780,6 +6691,11 @@ then CROSS="-DCROSS_COMPILE" ALL=all.cross SYSTEM_HEADER_DIR='$(CROSS_SYSTEM_HEADER_DIR)' + case "$host","$target" in + i?86-*-*,x86_64-*-* \ + | powerpc*-*-*,powerpc64*-*-*) + CROSS="$CROSS -DNATIVE_CROSS" ;; + esac fi # If this is a cross-compiler that does not @@ -6806,8 +6722,8 @@ fi # FIXME. # These are the normal (build=host) settings: -HOST_PREFIX= -HOST_PREFIX_1=ignore- +BUILD_PREFIX= +BUILD_PREFIX_1=ignore- HOST_CC='$(CC)' HOST_CFLAGS='$(ALL_CFLAGS)' @@ -6817,8 +6733,8 @@ STMP_FIXPROTO=stmp-fixproto # And these apply if build != host. if test x$build != x$host then - HOST_PREFIX=build- - HOST_PREFIX_1=build- + BUILD_PREFIX=build- + BUILD_PREFIX_1=build- HOST_CC='$(CC_FOR_BUILD)' HOST_CFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS_FOR_BUILD) $(XCFLAGS)' @@ -6868,7 +6784,7 @@ fi # Figure out what assembler we will be using. echo $ac_n "checking what assembler to use""... $ac_c" 1>&6 -echo "configure:6872: checking what assembler to use" >&5 +echo "configure:6788: checking what assembler to use" >&5 gcc_cv_as= gcc_cv_gas_major_version= gcc_cv_gas_minor_version= @@ -6962,7 +6878,7 @@ fi # Figure out what linker we will be using. echo $ac_n "checking what linker to use""... $ac_c" 1>&6 -echo "configure:6966: checking what linker to use" >&5 +echo "configure:6882: checking what linker to use" >&5 gcc_cv_ld= gcc_cv_gld_major_version= gcc_cv_gld_minor_version= @@ -7055,7 +6971,7 @@ fi # Figure out what nm we will be using. echo $ac_n "checking what nm to use""... $ac_c" 1>&6 -echo "configure:7059: checking what nm to use" >&5 +echo "configure:6975: checking what nm to use" >&5 if test -x nm$host_exeext; then gcc_cv_nm=./nm$host_exeext elif test "x$program_prefix" != xNONE; then @@ -7067,7 +6983,7 @@ echo "$ac_t""$gcc_cv_nm" 1>&6 # Figure out what objdump we will be using. echo $ac_n "checking what objdump to use""... $ac_c" 1>&6 -echo "configure:7071: checking what objdump to use" >&5 +echo "configure:6987: checking what objdump to use" >&5 if test -x objdump$host_exeext; then gcc_cv_objdump=./objdump$host_exeext elif test "x$program_prefix" != xNONE; then @@ -7079,7 +6995,7 @@ echo "$ac_t""$gcc_cv_objdump" 1>&6 # Figure out what assembler alignment features are present. echo $ac_n "checking assembler alignment features""... $ac_c" 1>&6 -echo "configure:7083: checking assembler alignment features" >&5 +echo "configure:6999: checking assembler alignment features" >&5 gcc_cv_as_alignment_features=none if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then # Gas version 2.6 and later support for .balign and .p2align. @@ -7127,7 +7043,7 @@ fi echo "$ac_t""$gcc_cv_as_alignment_features" 1>&6 echo $ac_n "checking assembler subsection support""... $ac_c" 1>&6 -echo "configure:7131: checking assembler subsection support" >&5 +echo "configure:7047: checking assembler subsection support" >&5 gcc_cv_as_subsections=no if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 9 -o "$gcc_cv_gas_major_version" -gt 2 && grep 'obj_format = elf' ../gas/Makefile > /dev/null; then @@ -7167,7 +7083,7 @@ fi echo "$ac_t""$gcc_cv_as_subsections" 1>&6 echo $ac_n "checking assembler weak support""... $ac_c" 1>&6 -echo "configure:7171: checking assembler weak support" >&5 +echo "configure:7087: checking assembler weak support" >&5 gcc_cv_as_weak=no if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 2 -o "$gcc_cv_gas_major_version" -gt 2; then @@ -7190,7 +7106,7 @@ fi echo "$ac_t""$gcc_cv_as_weak" 1>&6 echo $ac_n "checking assembler hidden support""... $ac_c" 1>&6 -echo "configure:7194: checking assembler hidden support" >&5 +echo "configure:7110: checking assembler hidden support" >&5 gcc_cv_as_hidden=no if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then if test "$gcc_cv_gas_major_version" -eq 2 \ @@ -7211,13 +7127,13 @@ elif test x$gcc_cv_as != x; then fi rm -f conftest.s conftest.o conftest.nm1 conftest.nm2 - # GNU LD versions before 2.12.1 have buggy support for STV_HIDDEN. + # GNU LD versions before 2.12.1 have buggy support for STV_HIDDEN. # This is irritatingly difficult to feature test for. Look for # the date string after the version number. ld_ver=`$gcc_cv_ld --version 2>/dev/null | head -1` if echo "$ld_ver" | grep GNU > /dev/null; then - ld_vers=`echo $ld_ver | sed -n 's,^.*[ ]\([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=`echo $ld_ver | sed -n 's,^.*[ ]\([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'` 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 @@ -7242,7 +7158,6 @@ elif test x$gcc_cv_as != x; then fi fi fi - if test x"$gcc_cv_as_hidden" = xyes; then cat >> confdefs.h <<\EOF #define HAVE_GAS_HIDDEN 1 @@ -7251,10 +7166,23 @@ EOF fi echo "$ac_t""$gcc_cv_as_hidden" 1>&6 libgcc_visibility=$gcc_cv_as_hidden +case "$target" in + mips-sgi-irix6*) + if test x"$gnu_ld_flag" = x"no"; then + # Even if using gas with .hidden support, the resulting object files + # cannot be linked with the IRIX 6 O32 linker. With the N32 and + # N64 linkers, the problem is that the linker refuses to accept + # -call_shared (passed by default to the linker) and -r (used to + # link the object file generated without .hidden directives with + # one that hides symbols), so we also lose. + libgcc_visibility=no + fi + ;; +esac echo $ac_n "checking assembler leb128 support""... $ac_c" 1>&6 -echo "configure:7258: checking assembler leb128 support" >&5 +echo "configure:7186: checking assembler leb128 support" >&5 gcc_cv_as_leb128=no if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 11 -o "$gcc_cv_gas_major_version" -gt 2 && grep 'obj_format = elf' ../gas/Makefile > /dev/null; then @@ -7299,7 +7227,7 @@ fi echo "$ac_t""$gcc_cv_as_leb128" 1>&6 echo $ac_n "checking assembler eh_frame optimization""... $ac_c" 1>&6 -echo "configure:7303: checking assembler eh_frame optimization" >&5 +echo "configure:7231: checking assembler eh_frame optimization" >&5 gcc_cv_as_eh_frame=no if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 12 -o "$gcc_cv_gas_major_version" -gt 2 && grep 'obj_format = elf' ../gas/Makefile > /dev/null; then @@ -7380,7 +7308,7 @@ fi echo "$ac_t""$gcc_cv_as_eh_frame" 1>&6 echo $ac_n "checking assembler section merging support""... $ac_c" 1>&6 -echo "configure:7384: checking assembler section merging support" >&5 +echo "configure:7312: checking assembler section merging support" >&5 gcc_cv_as_shf_merge=no if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 12 -o "$gcc_cv_gas_major_version" -gt 2 && grep 'obj_format = elf' ../gas/Makefile > /dev/null; then @@ -7402,11 +7330,151 @@ EOF fi echo "$ac_t""$gcc_cv_as_shf_merge" 1>&6 +echo $ac_n "checking assembler thread-local storage support""... $ac_c" 1>&6 +echo "configure:7335: checking assembler thread-local storage support" >&5 +gcc_cv_as_tls=no +conftest_s= +tls_first_major= +tls_first_minor= +case "$target" in + alpha*-*-*) + conftest_s=' + .section ".tdata","awT",@progbits +foo: .long 25 + .text + ldq $27,__tls_get_addr($29) !literal!1 + lda $16,foo($29) !tlsgd!1 + jsr $26,($27),__tls_get_addr !lituse_tlsgd!1 + ldq $27,__tls_get_addr($29) !literal!2 + lda $16,foo($29) !tlsldm!2 + jsr $26,($27),__tls_get_addr !lituse_tlsldm!2 + ldq $1,foo($29) !gotdtprel + ldah $2,foo($29) !dtprelhi + lda $3,foo($2) !dtprello + lda $4,foo($29) !dtprel + ldq $1,foo($29) !gottprel + ldah $2,foo($29) !tprelhi + lda $3,foo($2) !tprello + lda $4,foo($29) !tprel' + tls_first_major=2 + tls_first_minor=13 + ;; + i[34567]86-*-*) + conftest_s=' + .section ".tdata","awT",@progbits +foo: .long 25 + .text + movl %gs:0, %eax + leal foo@TLSGD(,%ebx,1), %eax + leal foo@TLSLDM(%ebx), %eax + leal foo@DTPOFF(%eax), %edx + movl foo@GOTTPOFF(%ebx), %eax + subl foo@GOTTPOFF(%ebx), %eax + addl foo@GOTNTPOFF(%ebx), %eax + movl foo@INDNTPOFF, %eax + movl $foo@TPOFF, %eax + subl $foo@TPOFF, %eax + leal foo@NTPOFF(%ecx), %eax' + tls_first_major=2 + tls_first_minor=14 + ;; + x86_64-*-*) + conftest_s=' + .section ".tdata","awT",@progbits +foo: .long 25 + .text + movq %fs:0, %rax + leaq foo@TLSGD(%rip), %rdi + leaq foo@TLSLD(%rip), %rdi + leaq foo@DTPOFF(%rax), %rdx + movq foo@GOTTPOFF(%rip), %rax + movq $foo@TPOFF, %rax' + tls_first_major=2 + tls_first_minor=14 + ;; + ia64-*-*) + conftest_s=' + .section ".tdata","awT",@progbits +foo: data8 25 + .text + addl r16 = @ltoff(@dtpmod(foo#)), gp + addl r17 = @ltoff(@dtprel(foo#)), gp + addl r18 = @ltoff(@tprel(foo#)), gp + addl r19 = @dtprel(foo#), gp + adds r21 = @dtprel(foo#), r13 + movl r23 = @dtprel(foo#) + addl r20 = @tprel(foo#), gp + adds r22 = @tprel(foo#), r13 + movl r24 = @tprel(foo#)' + tls_first_major=2 + tls_first_minor=13 + ;; + s390-*-*) + conftest_s=' + .section ".tdata","awT",@progbits +foo: .long 25 + .text + .long foo@TLSGD + .long foo@TLSLDM + .long foo@DTPOFF + .long foo@NTPOFF + .long foo@GOTNTPOFF + .long foo@INDNTPOFF + l %r1,foo@GOTNTPOFF(%r12) + l %r1,0(%r1):tls_load:foo + bas %r14,0(%r1,%r13):tls_gdcall:foo + bas %r14,0(%r1,%r13):tls_ldcall:foo' + tls_first_major=2 + tls_first_minor=14 + ;; + s390x-*-*) + conftest_s=' + .section ".tdata","awT",@progbits +foo: .long 25 + .text + .quad foo@TLSGD + .quad foo@TLSLDM + .quad foo@DTPOFF + .quad foo@NTPOFF + .quad foo@GOTNTPOFF + lg %r1,foo@GOTNTPOFF(%r12) + larl %r1,foo@INDNTPOFF + brasl %r14,__tls_get_offset@PLT:tls_gdcall:foo + brasl %r14,__tls_get_offset@PLT:tls_ldcall:foo' + tls_first_major=2 + tls_first_minor=14 + ;; +esac +if test -z "$tls_first_major"; then + : +elif test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x +then + if test "$gcc_cv_gas_major_version" -eq "$tls_first_major" \ + -a "$gcc_cv_gas_minor_version" -ge "$tls_first_minor" \ + -o "$gcc_cv_gas_major_version" -gt "$tls_first_major"; then + gcc_cv_as_tls=yes + fi +elif test x$gcc_cv_as != x; then + echo "$conftest_s" > conftest.s + if $gcc_cv_as --fatal-warnings -o conftest.o conftest.s > /dev/null 2>&1 + then + gcc_cv_as_tls=yes + fi + rm -f conftest.s conftest.o +fi +if test "$gcc_cv_as_tls" = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_AS_TLS 1 +EOF + +fi +echo "$ac_t""$gcc_cv_as_tls" 1>&6 + case "$target" in # All TARGET_ABI_OSF targets. alpha*-*-osf* | alpha*-*-linux* | alpha*-*-*bsd*) echo $ac_n "checking assembler supports explicit relocations""... $ac_c" 1>&6 -echo "configure:7410: checking assembler supports explicit relocations" >&5 +echo "configure:7478: checking assembler supports explicit relocations" >&5 if eval "test \"`echo '$''{'gcc_cv_as_explicit_relocs'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7456,7 +7524,7 @@ EOF ;; sparc*-*-*) echo $ac_n "checking assembler .register pseudo-op support""... $ac_c" 1>&6 -echo "configure:7460: checking assembler .register pseudo-op support" >&5 +echo "configure:7528: checking assembler .register pseudo-op support" >&5 if eval "test \"`echo '$''{'gcc_cv_as_register_pseudo_op'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7484,7 +7552,7 @@ EOF fi echo $ac_n "checking assembler supports -relax""... $ac_c" 1>&6 -echo "configure:7488: checking assembler supports -relax" >&5 +echo "configure:7556: checking assembler supports -relax" >&5 if eval "test \"`echo '$''{'gcc_cv_as_relax_opt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7512,7 +7580,7 @@ EOF fi echo $ac_n "checking assembler and linker support unaligned pc related relocs""... $ac_c" 1>&6 -echo "configure:7516: checking assembler and linker support unaligned pc related relocs" >&5 +echo "configure:7584: checking assembler and linker support unaligned pc related relocs" >&5 if eval "test \"`echo '$''{'gcc_cv_as_sparc_ua_pcrel'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7539,7 +7607,7 @@ EOF fi echo $ac_n "checking assembler and linker support unaligned pc related relocs against hidden symbols""... $ac_c" 1>&6 -echo "configure:7543: checking assembler and linker support unaligned pc related relocs against hidden symbols" >&5 +echo "configure:7611: checking assembler and linker support unaligned pc related relocs against hidden symbols" >&5 if eval "test \"`echo '$''{'gcc_cv_as_sparc_ua_pcrel_hidden'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7579,7 +7647,7 @@ EOF fi echo $ac_n "checking for assembler offsetable %lo() support""... $ac_c" 1>&6 -echo "configure:7584: checking for assembler offsetable %lo() support" >&5 +echo "configure:7651: checking for assembler offsetable %lo() support" >&5 if eval "test \"`echo '$''{'gcc_cv_as_offsetable_lo10'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7618,7 +7686,7 @@ EOF i[34567]86-*-* | x86_64-*-*) echo $ac_n "checking assembler instructions""... $ac_c" 1>&6 -echo "configure:7624: checking assembler instructions" >&5 +echo "configure:7690: checking assembler instructions" >&5 gcc_cv_as_instructions= if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 9 -o "$gcc_cv_gas_major_version" -gt 2; then @@ -7645,7 +7713,7 @@ EOF echo "$ac_t""$gcc_cv_as_instructions" 1>&6 echo $ac_n "checking assembler GOTOFF in data directives""... $ac_c" 1>&6 -echo "configure:7651: checking assembler GOTOFF in data directives" >&5 +echo "configure:7717: checking assembler GOTOFF in data directives" >&5 gcc_cv_as_gotoff_in_data=no if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x then @@ -7672,10 +7740,52 @@ EOF echo "$ac_t""$gcc_cv_as_gotoff_in_data" 1>&6 ;; + + ia64*-*-*) + echo $ac_n "checking assembler supports ltoffx and ldxmov""... $ac_c" 1>&6 +echo "configure:7747: checking assembler supports ltoffx and ldxmov" >&5 +if eval "test \"`echo '$''{'gcc_cv_as_ltoffx_ldxmov_relocs'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + gcc_cv_as_ltoffx_ldxmov_relocs=unknown + if test x$gcc_cv_gas_major_version != x \ + -a x$gcc_cv_gas_minor_version != x + then + if test "$gcc_cv_gas_major_version" -eq 2 \ + -a "$gcc_cv_gas_minor_version" -ge 14 \ + -o "$gcc_cv_gas_major_version" -gt 2; then + gcc_cv_as_ltoffx_ldxmov_relocs=yes + fi + elif test x$gcc_cv_as != x; then + cat > conftest.s << 'EOF' + .text + addl r15 = @ltoffx(x#), gp + ;; + ld8.mov r16 = [r15], x# +EOF + if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then + gcc_cv_as_ltoffx_ldxmov_relocs=yes + else + gcc_cv_as_ltoffx_ldxmov_relocs=no + fi + rm -f conftest.s conftest.o + fi + +fi + +echo "$ac_t""$gcc_cv_as_ltoffx_ldxmov_relocs" 1>&6 + if test "x$gcc_cv_as_ltoffx_ldxmov_relocs" = xyes; then + cat >> confdefs.h <<\EOF +#define HAVE_AS_LTOFFX_LDXMOV_RELOCS 1 +EOF + + fi + ;; esac echo $ac_n "checking assembler dwarf2 debug_line support""... $ac_c" 1>&6 -echo "configure:7681: checking assembler dwarf2 debug_line support" >&5 +echo "configure:7789: checking assembler dwarf2 debug_line support" >&5 gcc_cv_as_dwarf2_debug_line=no # ??? Not all targets support dwarf2 debug_line, even within a version # of gas. Moreover, we need to emit a valid instruction to trigger any @@ -7684,7 +7794,8 @@ gcc_cv_as_dwarf2_debug_line=no # ??? Once 2.11 is released, probably need to add first known working # version to the per-target configury. case "$target" in - i?86*-*-* | mips*-*-* | alpha*-*-* | powerpc*-*-* | sparc*-*-* | m68*-*-* | x86_64*-*-*) + i?86*-*-* | mips*-*-* | alpha*-*-* | powerpc*-*-* | sparc*-*-* | m68*-*-* \ + | x86_64*-*-* | hppa*-*-* | arm*-*-* | strongarm*-*-* | xscale*-*-*) insn="nop" ;; ia64*-*-*) @@ -7731,7 +7842,7 @@ fi echo "$ac_t""$gcc_cv_as_dwarf2_debug_line" 1>&6 echo $ac_n "checking assembler --gdwarf2 support""... $ac_c" 1>&6 -echo "configure:7737: checking assembler --gdwarf2 support" >&5 +echo "configure:7846: checking assembler --gdwarf2 support" >&5 gcc_cv_as_gdwarf2_flag=no if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then @@ -7740,7 +7851,7 @@ then -o "$gcc_cv_gas_major_version" -gt 2 \ && grep 'obj_format = elf' ../gas/Makefile > /dev/null \ && test x"$insn" != x ; then - gcc_cv_as_gdwarf2_debug_flag="yes" + gcc_cv_as_gdwarf2_flag="yes" fi elif test x$gcc_cv_as != x -a x"$insn" != x ; then echo '' > conftest.s @@ -7760,7 +7871,7 @@ fi echo "$ac_t""$gcc_cv_as_gdwarf2_flag" 1>&6 echo $ac_n "checking assembler --gstabs support""... $ac_c" 1>&6 -echo "configure:7766: checking assembler --gstabs support" >&5 +echo "configure:7875: checking assembler --gstabs support" >&5 gcc_cv_as_gstabs_flag=no if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then @@ -7769,13 +7880,20 @@ then -o "$gcc_cv_gas_major_version" -gt 2 \ && grep 'obj_format = elf' ../gas/Makefile > /dev/null \ && test x"$insn" != x ; then - gcc_cv_as_gstabs_debug_flag="yes" + gcc_cv_as_gstabs_flag="yes" fi elif test x$gcc_cv_as != x -a x"$insn" != x ; then echo '' > conftest.s # ??? This fails with non-gnu grep. if $gcc_cv_as --gstabs -o conftest.o conftest.s > /dev/null 2>&1 ; then gcc_cv_as_gstabs_flag="yes" + # The native Solaris 9/Intel assembler doesn't understand --gstabs + # and warns about it, but still exits successfully. So check for + # this. + if $gcc_cv_as --gstabs -o conftest.o conftest.s 2>&1 | \ + grep -i warning > /dev/null ; then + gcc_cv_as_gstabs_flag="no" + fi fi rm -f conftest.s conftest.o fi @@ -7787,8 +7905,46 @@ EOF fi echo "$ac_t""$gcc_cv_as_gstabs_flag" 1>&6 +echo $ac_n "checking linker read-only and read-write section mixing""... $ac_c" 1>&6 +echo "configure:7910: checking linker read-only and read-write section mixing" >&5 +gcc_cv_ld_ro_rw_mix=unknown +if test x$gcc_cv_gld_major_version != x -a x$gcc_cv_gld_minor_version != x; then + if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 10 -o "$gcc_cv_gld_major_version" -gt 2 && grep 'EMUL = elf' ../ld/Makefile > /dev/null; then + gcc_cv_ld_ro_rw_mix=read-write + fi +elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x ; then + echo '.section myfoosect, "a"' > conftest1.s + echo '.section myfoosect, "aw"' > conftest2.s + echo '.byte 1' >> conftest2.s + echo '.section myfoosect, "a"' > conftest3.s + echo '.byte 0' >> conftest3.s + if $gcc_cv_as -o conftest1.o conftest1.s > /dev/null 2>&1 \ + && $gcc_cv_as -o conftest2.o conftest2.s > /dev/null 2>&1 \ + && $gcc_cv_as -o conftest3.o conftest3.s > /dev/null 2>&1 \ + && $gcc_cv_ld -shared -o conftest1.so conftest1.o \ + conftest2.o conftest3.o > /dev/null 2>&1; then + gcc_cv_ld_ro_rw_mix=`$gcc_cv_objdump -h conftest1.so \ + | sed -e '/myfoosect/!d' -e N` + if echo "$gcc_cv_ld_ro_rw_mix" | grep CONTENTS > /dev/null; then + if echo "$gcc_cv_ld_ro_rw_mix" | grep READONLY > /dev/null; then + gcc_cv_ld_ro_rw_mix=read-only + else + gcc_cv_ld_ro_rw_mix=read-write + fi + fi + fi + rm -f conftest.* conftest[123].* +fi +if test x$gcc_cv_ld_ro_rw_mix = xread-write; then + cat >> confdefs.h <<\EOF +#define HAVE_LD_RO_RW_SECTION_MIXING 1 +EOF + +fi +echo "$ac_t""$gcc_cv_ld_ro_rw_mix" 1>&6 + echo $ac_n "checking linker PT_GNU_EH_FRAME support""... $ac_c" 1>&6 -echo "configure:7794: checking linker PT_GNU_EH_FRAME support" >&5 +echo "configure:7948: checking linker PT_GNU_EH_FRAME support" >&5 gcc_cv_ld_eh_frame_hdr=no if test x$gcc_cv_gld_major_version != x -a x$gcc_cv_gld_minor_version != x; then if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 12 -o "$gcc_cv_gld_major_version" -gt 2 && grep 'EMUL = elf' ../ld/Makefile > /dev/null; then @@ -7800,97 +7956,48 @@ elif test x$gcc_cv_ld != x; then gcc_cv_ld_eh_frame_hdr=yes fi fi -echo "$ac_t""$gcc_cv_ld_eh_frame_hdr" 1>&6 if test x"$gcc_cv_ld_eh_frame_hdr" = xyes; then - echo $ac_n "checking whether linker eh_frame optimizations work properly""... $ac_c" 1>&6 -echo "configure:7809: checking whether linker eh_frame optimizations work properly" >&5 - gcc_cv_ld_eh_frame_hdr_works=no - if test x$gcc_cv_gld_major_version != x -a x$gcc_cv_gld_minor_version != x; then - if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 13 -o "$gcc_cv_gld_major_version" -gt 2 && grep 'EMUL = elf' ../ld/Makefile > /dev/null; then - gcc_cv_ld_eh_frame_hdr_works=yes - fi - elif test x$gcc_cv_ld != x; then - for gcc_WS in 4 8; do - cat > conftest.s <<EOF - .text -.LFB1: .skip 64 -.LFE1: -.LFB2: .skip 64 -.LFE2: -.LFB3: .skip 64 -.LFE3: - .section .eh_frame,"aw",@progbits -.Lframe1: - .4byte .LECIE1-.LSCIE1 -.LSCIE1: - .4byte 0x0 - .byte 0x1 - .ascii "zR\0" - .uleb128 0x1 - .sleb128 -4 - .byte 0x8 - .uleb128 0x1 - .byte 0x50 - .byte 0xc - .uleb128 0x4 - .uleb128 0x4 - .byte 0x88 - .uleb128 0x1 - .balign ${gcc_WS} -.LECIE1: -.LSFDE1: - .4byte .LEFDE1-.LASFDE1 -.LASFDE1: - .4byte .LASFDE1-.Lframe1 - .${gcc_WS}byte .LFB1 - .${gcc_WS}byte .LFE1-.LFB1 - .uleb128 0x0 - .balign ${gcc_WS} -.LEFDE1: -.LSFDE2: - .4byte .LEFDE2-.LASFDE2 -.LASFDE2: - .4byte .LASFDE2-.Lframe1 - .${gcc_WS}byte .LFB2 - .${gcc_WS}byte .LFE2-.LFB2 - .uleb128 0x0 - .balign ${gcc_WS} -.LEFDE2: -.LSFDE3: - .4byte .LEFDE3-.LASFDE3 -.LASFDE3: - .4byte .LASFDE3-.Lframe1 - .${gcc_WS}byte .LFB3 - .${gcc_WS}byte .LFE3-.LFB3 - .uleb128 0x0 - .balign ${gcc_WS} -.LEFDE3: - .4byte 0 -EOF - if ($gcc_cv_as -o conftest.o conftest.s; exit $?) 1>&5 2>&1; then - if ($gcc_cv_ld --eh-frame-hdr -shared -o conftest.so conftest.o; exit $?) 1>&5 2>&1; then - if $gcc_cv_objdump -h conftest.so 2>&5 \ - | grep 'eh_frame_hdr[ ]*0*[01][048cC][ ]' 1>&5 2>&1; then - gcc_cv_ld_eh_frame_hdr_works=yes; break - else - $gcc_cv_objdump -h conftest.so 2>/dev/null | grep eh_frame_hdr 1>&5 2>&1 - fi - fi - fi - rm -f conftest.* - done - fi - echo "$ac_t""$gcc_cv_ld_eh_frame_hdr_works" 1>&6 -fi -if test x"$gcc_cv_ld_eh_frame_hdr" = xyes \ - && test x"$gcc_cv_ld_eh_frame_hdr_works" = xyes; then cat >> confdefs.h <<\EOF #define HAVE_LD_EH_FRAME_HDR 1 EOF fi +echo "$ac_t""$gcc_cv_ld_eh_frame_hdr" 1>&6 -if test "$prefix" != "/usr" && test "$prefix" != "/usr/local" ; then +# Miscellaneous target-specific checks. +case "$target" in + mips*-*-*) + echo $ac_n "checking whether libgloss uses STARTUP directives consistently""... $ac_c" 1>&6 +echo "configure:7972: checking whether libgloss uses STARTUP directives consistently" >&5 + gcc_cv_mips_libgloss_startup=no + gcc_cv_libgloss_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/libgloss + 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 + for f in $gcc_cv_libgloss_srcdir/mips/idt.ld $test_prefix/$target_alias/lib/idt.ld + do + if grep '^STARTUP' $f > /dev/null 2>&1; then + gcc_cv_mips_libgloss_startup=yes + break + fi + done + if test x"$gcc_cv_mips_libgloss_startup" = xyes; then + cat >> confdefs.h <<\EOF +#define HAVE_MIPS_LIBGLOSS_STARTUP_DIRECTIVES 1 +EOF + + fi + echo "$ac_t""$gcc_cv_mips_libgloss_startup" 1>&6 + ;; +esac + +if test "$prefix" != "/usr" && test "x$prefix" != "x$local_prefix" ; then cat >> confdefs.h <<EOF #define PREFIX_INCLUDE_DIR "$prefix/include" EOF @@ -7911,8 +8018,8 @@ if test x"${enable_languages+set}" != xset; then enable_languages=all fi else - if test x"${enable_languages}" = x || - test x"${enable_languages}" = xyes; + if test x"${enable_languages}" = x \ + || test x"${enable_languages}" = xyes; then { echo "configure: error: --enable-languages needs at least one language argument" 1>&2; exit 1; } fi @@ -7950,6 +8057,8 @@ do esac done +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 @@ -7973,6 +8082,7 @@ do *,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) @@ -7989,6 +8099,35 @@ do esac done +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 + +if test "x$missing_languages" != x; then + { echo "configure: error: +The following requested languages were not found:${missing_languages} +The following languages were available: c${found_languages}" 1>&2; exit 1; } +fi + # Make gthr-default.h if we have a thread file. gthread_flags= if test $thread_file != single; then @@ -8033,7 +8172,7 @@ fi echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 -echo "configure:8039: checking whether to enable maintainer-specific portions of Makefiles" >&5 +echo "configure:8176: checking whether to enable maintainer-specific portions of Makefiles" >&5 # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then enableval="$enable_maintainer_mode" @@ -8063,6 +8202,22 @@ EOF fi +# Use libunwind based exception handling. +# Check whether --enable-libunwind-exceptions or --disable-libunwind-exceptions was given. +if test "${enable_libunwind_exceptions+set}" = set; then + enableval="$enable_libunwind_exceptions" + use_libunwind_exceptions=$enableval +else + use_libunwind_exceptions=no +fi + +if test x"$use_libunwind_exceptions" = xyes; then + cat >> confdefs.h <<\EOF +#define USE_LIBUNWIND_EXCEPTIONS 1 +EOF + +fi + # 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. @@ -8088,9 +8243,14 @@ all_languages= all_boot_languages= all_compilers= all_stagestuff= -all_outputs='Makefile intl/Makefile fixinc/Makefile gccbug mklibgcc' +all_outputs='Makefile intl/Makefile fixinc/Makefile gccbug mklibgcc mkheaders' # List of language makefile fragments. all_lang_makefiles= +# Files for gengtype +all_gtfiles="$target_gtfiles" +# Files for gengtype with language +all_gtfiles_files_langs= +all_gtfiles_files_files= # Add the language fragments. # Languages are added via two mechanisms. Some information must be @@ -8111,6 +8271,7 @@ do compilers= stagestuff= outputs= + gtfiles= . ${srcdir}/$s/config-lang.in if test "x$language" = x then @@ -8129,9 +8290,32 @@ do 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 + if test $f != ".." + then + all_gtfiles_files_langs="$all_gtfiles_files_langs ${s} " + all_gtfiles_files_files="$all_gtfiles_files_files ${f} " + fi + done fi done +# Pick up gtfiles for c +gtfiles= +s="c" +. ${srcdir}/c-config-lang.in +all_gtfiles="$all_gtfiles $gtfiles" +for f in .. $gtfiles +do + if test $f != ".." + then + all_gtfiles_files_langs="$all_gtfiles_files_langs ${s} " + all_gtfiles_files_files="$all_gtfiles_files_files ${f} " + fi +done + check_languages= for language in .. $all_languages do @@ -8254,8 +8438,7 @@ fi -# Nothing to do for FLOAT_H, float_format already handled. -objdir=`pwd` +objdir=`${PWDCMD-pwd}` # Process the language and host/target makefile fragments. @@ -8325,6 +8508,11 @@ ${CONFIG_SHELL-/bin/sh} $srcdir/configure.frag $srcdir "$subdirs" "$dep_host_xma + + + + + # Echo that links are built if test x$host = x$target then @@ -8493,8 +8681,6 @@ s%@includedir@%$includedir%g s%@oldincludedir@%$oldincludedir%g s%@infodir@%$infodir%g s%@mandir@%$mandir%g -s%@enable_multilib@%$enable_multilib%g -s%@enable_shared@%$enable_shared%g s%@host@%$host%g s%@host_alias@%$host_alias%g s%@host_cpu@%$host_cpu%g @@ -8518,6 +8704,13 @@ s%@ADAC@%$ADAC%g s%@strict1_warn@%$strict1_warn%g s%@CPP@%$CPP%g s%@warn_cflags@%$warn_cflags%g +s%@enable_multilib@%$enable_multilib%g +s%@nocommon_flag@%$nocommon_flag%g +s%@valgrind_path@%$valgrind_path%g +s%@valgrind_path_defines@%$valgrind_path_defines%g +s%@valgrind_command@%$valgrind_command%g +s%@coverage_flags@%$coverage_flags%g +s%@enable_shared@%$enable_shared%g s%@stage1_cflags@%$stage1_cflags%g s%@SET_MAKE@%$SET_MAKE%g s%@AWK@%$AWK%g @@ -8535,10 +8728,13 @@ s%@FLEX@%$FLEX%g s%@BISON@%$BISON%g s%@COLLECT2_LIBS@%$COLLECT2_LIBS%g s%@GNAT_LIBEXC@%$GNAT_LIBEXC%g +s%@LDEXP_LIB@%$LDEXP_LIB%g s%@TARGET_GETGROUPS_T@%$TARGET_GETGROUPS_T%g s%@LIBICONV@%$LIBICONV%g +s%@gcc_cv_initfinit_array@%$gcc_cv_initfinit_array%g s%@manext@%$manext%g s%@objext@%$objext%g +s%@extra_modes_file@%$extra_modes_file%g s%@FORBUILD@%$FORBUILD%g s%@PACKAGE@%$PACKAGE%g s%@VERSION@%$VERSION%g @@ -8566,8 +8762,8 @@ s%@CROSS@%$CROSS%g s%@ALL@%$ALL%g s%@SYSTEM_HEADER_DIR@%$SYSTEM_HEADER_DIR%g s%@inhibit_libc@%$inhibit_libc%g -s%@HOST_PREFIX@%$HOST_PREFIX%g -s%@HOST_PREFIX_1@%$HOST_PREFIX_1%g +s%@BUILD_PREFIX@%$BUILD_PREFIX%g +s%@BUILD_PREFIX_1@%$BUILD_PREFIX_1%g s%@HOST_CC@%$HOST_CC%g s%@HOST_CFLAGS@%$HOST_CFLAGS%g s%@STMP_FIXINC@%$STMP_FIXINC%g @@ -8586,8 +8782,12 @@ s%@dollar@%$dollar%g s%@slibdir@%$slibdir%g s%@objdir@%$objdir%g s%@subdirs@%$subdirs%g +s%@srcdir@%$srcdir%g s%@all_boot_languages@%$all_boot_languages%g s%@all_compilers@%$all_compilers%g +s%@all_gtfiles@%$all_gtfiles%g +s%@all_gtfiles_files_langs@%$all_gtfiles_files_langs%g +s%@all_gtfiles_files_files@%$all_gtfiles_files_files%g s%@all_lang_makefiles@%$all_lang_makefiles%g s%@all_languages@%$all_languages%g s%@all_stagestuff@%$all_stagestuff%g @@ -8634,6 +8834,7 @@ s%@symbolic_link@%$symbolic_link%g s%@thread_file@%$thread_file%g s%@tm_file_list@%$tm_file_list%g s%@tm_file@%$tm_file%g +s%@tm_defines@%$tm_defines%g s%@tm_p_file_list@%$tm_p_file_list%g s%@tm_p_file@%$tm_p_file%g s%@xm_file@%$xm_file%g @@ -8902,7 +9103,7 @@ esac if test "$symbolic_link" = "ln -s"; then for d in .. ${subdirs} fixinc ; do if test $d != ..; then - STARTDIR=`pwd` + STARTDIR=`${PWDCMD-pwd}` cd $d for t in stage1 stage2 stage3 stage4 include do diff --git a/contrib/gcc/cp/except.c b/contrib/gcc/cp/except.c index 5de9f4c..747cc1a 100644 --- a/contrib/gcc/cp/except.c +++ b/contrib/gcc/cp/except.c @@ -31,10 +31,10 @@ Boston, MA 02111-1307, USA. */ #include "libfuncs.h" #include "cp-tree.h" #include "flags.h" -#include "obstack.h" #include "output.h" #include "except.h" #include "toplev.h" +#include "tree-inline.h" static void push_eh_cleanup PARAMS ((tree)); static tree prepare_eh_type PARAMS ((tree)); @@ -46,15 +46,14 @@ static void push_eh_cleanup PARAMS ((tree)); static bool decl_is_java_type PARAMS ((tree decl, int err)); static void initialize_handler_parm PARAMS ((tree, tree)); static tree do_allocate_exception PARAMS ((tree)); +static tree stabilize_throw_expr PARAMS ((tree, tree *)); +static tree wrap_cleanups_r PARAMS ((tree *, int *, void *)); static int complete_ptr_ref_or_void_ptr_p PARAMS ((tree, tree)); static bool is_admissible_throw_operand PARAMS ((tree)); static int can_convert_eh PARAMS ((tree, tree)); static void check_handlers_1 PARAMS ((tree, tree)); static tree cp_protect_cleanup_actions PARAMS ((void)); -#include "decl.h" -#include "obstack.h" - /* Sets up all the global eh stuff that needs to be initialized at the start of compilation. */ @@ -118,7 +117,7 @@ prepare_eh_type (type) } /* Build the address of a typeinfo decl for use in the runtime - matching field of the exception model. */ + matching field of the exception model. */ static tree build_eh_type_type (type) @@ -175,17 +174,13 @@ static int dtor_nothrow (type) tree type; { - tree fn; - if (type == NULL_TREE) return 0; if (! TYPE_HAS_DESTRUCTOR (type)) return 1; - fn = lookup_member (type, dtor_identifier, 0, 0); - fn = TREE_VALUE (fn); - return TREE_NOTHROW (fn); + return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type)); } /* Build up a call to __cxa_end_catch, to destroy the exception object @@ -518,7 +513,7 @@ do_allocate_exception (type) #if 0 /* Call __cxa_free_exception from a cleanup. This is never invoked - directly. */ + directly, but see the comment for stabilize_throw_expr. */ static tree do_free_exception (ptr) @@ -540,6 +535,92 @@ do_free_exception (ptr) } #endif +/* Wrap all cleanups for TARGET_EXPRs in MUST_NOT_THROW_EXPR. + Called from build_throw via walk_tree_without_duplicates. */ + +static tree +wrap_cleanups_r (tp, walk_subtrees, data) + tree *tp; + int *walk_subtrees ATTRIBUTE_UNUSED; + void *data ATTRIBUTE_UNUSED; +{ + tree exp = *tp; + tree cleanup; + + /* Don't walk into types. */ + if (TYPE_P (exp)) + { + *walk_subtrees = 0; + return NULL_TREE; + } + if (TREE_CODE (exp) != TARGET_EXPR) + return NULL_TREE; + + cleanup = TARGET_EXPR_CLEANUP (exp); + if (cleanup) + { + cleanup = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (cleanup), cleanup); + TARGET_EXPR_CLEANUP (exp) = cleanup; + } + + /* Keep iterating. */ + return NULL_TREE; +} + +/* Like stabilize_expr, but specifically for a thrown expression. When + throwing a temporary class object, we want to construct it directly into + the thrown exception, so we look past the TARGET_EXPR and stabilize the + arguments of the call instead. + + The case where EXP is a call to 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. I'm going to say no, as that allows us to optimize + this case without worrying about deallocating the exception object if it + does. The alternatives would be either not optimizing this case, or + wrapping the initialization in a TRY_CATCH_EXPR to call do_free_exception + rather than in a MUST_NOT_THROW_EXPR, for this case only. */ + +static tree +stabilize_throw_expr (exp, initp) + tree exp; + tree *initp; +{ + tree init_expr; + + if (TREE_CODE (exp) == TARGET_EXPR + && TREE_CODE (TARGET_EXPR_INITIAL (exp)) == AGGR_INIT_EXPR + && flag_elide_constructors) + { + tree aggr_init = AGGR_INIT_EXPR_CHECK (TARGET_EXPR_INITIAL (exp)); + tree args = TREE_OPERAND (aggr_init, 1); + tree newargs = NULL_TREE; + tree *p = &newargs; + + init_expr = void_zero_node; + for (; args; args = TREE_CHAIN (args)) + { + tree arg = TREE_VALUE (args); + tree arg_init_expr; + + arg = stabilize_expr (arg, &arg_init_expr); + + if (TREE_SIDE_EFFECTS (arg_init_expr)) + init_expr = build (COMPOUND_EXPR, void_type_node, init_expr, + arg_init_expr); + *p = tree_cons (NULL_TREE, arg, NULL_TREE); + p = &TREE_CHAIN (*p); + } + TREE_OPERAND (aggr_init, 1) = newargs; + } + else + { + exp = stabilize_expr (exp, &init_expr); + } + + *initp = init_expr; + return exp; +} + /* Build a throw expression. */ tree @@ -585,10 +666,9 @@ build_throw (exp) { tree throw_type; tree cleanup; - tree stmt_expr; - tree compound_stmt; tree object, ptr; tree tmp; + tree temp_expr, allocate_expr; fn = get_identifier ("__cxa_throw"); if (IDENTIFIER_GLOBAL_VALUE (fn)) @@ -614,8 +694,6 @@ build_throw (exp) fn = push_throw_library_fn (fn, tmp); } - begin_init_stmts (&stmt_expr, &compound_stmt); - /* throw expression */ /* First, decay it. */ exp = decay_conversion (exp); @@ -633,37 +711,40 @@ build_throw (exp) the call to __cxa_allocate_exception first (which doesn't matter, since it can't throw). */ - my_friendly_assert (stmts_are_full_exprs_p () == 1, 19990926); - - /* Store the throw expression into a temp. This can be less - efficient than storing it into the allocated space directly, but - if we allocated the space first we would have to deal with - cleaning it up if evaluating this expression throws. */ - if (TREE_SIDE_EFFECTS (exp)) - { - tmp = create_temporary_var (TREE_TYPE (exp)); - DECL_INITIAL (tmp) = exp; - cp_finish_decl (tmp, exp, NULL_TREE, LOOKUP_ONLYCONVERTING); - exp = tmp; - } + /* 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. */ + exp = stabilize_throw_expr (exp, &temp_expr); /* Allocate the space for the exception. */ - ptr = create_temporary_var (ptr_type_node); - DECL_REGISTER (ptr) = 1; - cp_finish_decl (ptr, NULL_TREE, NULL_TREE, LOOKUP_ONLYCONVERTING); - tmp = do_allocate_exception (TREE_TYPE (exp)); - tmp = build_modify_expr (ptr, INIT_EXPR, tmp); - finish_expr_stmt (tmp); - + allocate_expr = do_allocate_exception (TREE_TYPE (exp)); + 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_indirect_ref (object, NULL); - exp = build_modify_expr (object, INIT_EXPR, exp); + /* And initialize the exception object. */ + exp = build_init (object, exp, LOOKUP_ONLYCONVERTING); if (exp == error_mark_node) - error (" in thrown expression"); + { + error (" in thrown expression"); + return error_mark_node; + } exp = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (exp), exp); - finish_expr_stmt (exp); + /* Prepend the allocation. */ + exp = build (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp); + if (temp_expr != void_zero_node) + { + /* Prepend the calculation of the throw expression. Also, force + any cleanups from the expression to be evaluated here so that + we don't have to do them during unwinding. But first wrap + 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 = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp); + } throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object))); @@ -671,9 +752,9 @@ build_throw (exp) { cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)), complete_dtor_identifier, 0); - cleanup = TREE_VALUE (cleanup); + cleanup = BASELINK_FUNCTIONS (cleanup); mark_used (cleanup); - mark_addressable (cleanup); + cxx_mark_addressable (cleanup); /* Pretend it's a normal function. */ cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup); } @@ -686,13 +767,11 @@ build_throw (exp) tmp = tree_cons (NULL_TREE, cleanup, NULL_TREE); tmp = tree_cons (NULL_TREE, throw_type, tmp); tmp = tree_cons (NULL_TREE, ptr, tmp); - tmp = build_function_call (fn, tmp); - /* ??? Indicate that this function call throws throw_type. */ + tmp = build_function_call (fn, tmp); - finish_expr_stmt (tmp); - - exp = finish_init_stmts (stmt_expr, compound_stmt); + /* Tack on the initialization stuff. */ + exp = build (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp); } else { @@ -708,6 +787,8 @@ build_throw (exp) (fn, build_function_type (void_type_node, void_list_node)); } + /* ??? Indicate that this function call allows exceptions of the type + of the enclosing catch block (if known). */ exp = build_function_call (fn, NULL_TREE); } @@ -718,7 +799,7 @@ build_throw (exp) /* Make sure TYPE is complete, pointer to complete, reference to complete, or pointer to cv void. Issue diagnostic on failure. - Return the zero on failure and non-zero on success. FROM can be + Return the zero on failure and nonzero on success. FROM can be the expr or decl from whence TYPE came, if available. */ static int diff --git a/contrib/gcc/dbxout.c b/contrib/gcc/dbxout.c index bd7f9a7..60ca664 100644 --- a/contrib/gcc/dbxout.c +++ b/contrib/gcc/dbxout.c @@ -1,6 +1,6 @@ /* Output dbx-format symbol table information from GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of GCC. @@ -155,7 +155,7 @@ static int source_label_number = 1; #endif #ifdef DEBUG_SYMS_TEXT -#define FORCE_TEXT text_section (); +#define FORCE_TEXT function_section (current_function_decl); #else #define FORCE_TEXT #endif @@ -309,6 +309,7 @@ static void print_int_cst_octal PARAMS ((tree)); static void print_octal PARAMS ((unsigned HOST_WIDE_INT, int)); static void print_wide_int PARAMS ((HOST_WIDE_INT)); static void dbxout_type_name PARAMS ((tree)); +static void dbxout_class_name_qualifiers PARAMS ((tree)); static int dbxout_symbol_location PARAMS ((tree, tree, const char *, rtx)); static void dbxout_symbol_name PARAMS ((tree, const char *, int)); static void dbxout_prepare_symbol PARAMS ((tree)); @@ -327,7 +328,7 @@ static void dbxout_begin_block PARAMS ((unsigned, unsigned)); static void dbxout_end_block PARAMS ((unsigned, unsigned)); static void dbxout_function_decl PARAMS ((tree)); -struct gcc_debug_hooks dbx_debug_hooks = +const struct gcc_debug_hooks dbx_debug_hooks = { dbxout_init, dbxout_finish, @@ -340,8 +341,8 @@ struct gcc_debug_hooks dbx_debug_hooks = debug_true_tree, /* ignore_block */ dbxout_source_line, /* source_line */ dbxout_source_line, /* begin_prologue: just output line info */ - debug_nothing_int, /* end_prologue */ - debug_nothing_void, /* end_epilogue */ + debug_nothing_int_charstar, /* end_prologue */ + debug_nothing_int_charstar, /* end_epilogue */ #ifdef DBX_FUNCTION_FIRST dbxout_begin_function, #else @@ -357,7 +358,7 @@ struct gcc_debug_hooks dbx_debug_hooks = #endif /* DBX_DEBUGGING_INFO */ #if defined (XCOFF_DEBUGGING_INFO) -struct gcc_debug_hooks xcoff_debug_hooks = +const struct gcc_debug_hooks xcoff_debug_hooks = { dbxout_init, dbxout_finish, @@ -370,7 +371,7 @@ struct gcc_debug_hooks xcoff_debug_hooks = debug_true_tree, /* ignore_block */ xcoffout_source_line, xcoffout_begin_prologue, /* begin_prologue */ - debug_nothing_int, /* end_prologue */ + debug_nothing_int_charstar, /* end_prologue */ xcoffout_end_epilogue, debug_nothing_tree, /* begin_function */ xcoffout_end_function, @@ -417,7 +418,7 @@ dbxout_init (input_file_name) const char *input_file_name; { char ltext_label_name[100]; - tree syms = getdecls (); + tree syms = (*lang_hooks.decls.getdecls) (); asmfile = asm_out_file; @@ -674,7 +675,7 @@ dbxout_global_decl (decl) && ! DECL_EXTERNAL (decl) && DECL_RTL_SET_P (decl)) /* Not necessary? */ dbxout_symbol (decl, 0); -} +} /* At the end of compilation, finish writing the symbol table. Unless you define DBX_OUTPUT_MAIN_SOURCE_FILE_END, the default is @@ -1019,7 +1020,7 @@ dbxout_type_methods (type) } if (!need_prefix) { - putc (';', asmfile); + putc (';', asmfile); CHARS (1); } } @@ -1107,7 +1108,9 @@ dbxout_type (type, full) static int anonymous_type_number = 0; if (TREE_CODE (type) == VECTOR_TYPE) - type = 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))); /* If there was an input error and we don't really have a type, avoid crashing and write something that is at least valid @@ -1279,7 +1282,7 @@ dbxout_type (type, full) write it as a subtype. */ else if (TREE_TYPE (type) != 0 && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE) - { + { /* If the size is non-standard, say what it is if we can use GDB extensions. */ @@ -1292,10 +1295,10 @@ dbxout_type (type, full) } dbxout_range_type (type); - } + } else - { + { /* If the size is non-standard, say what it is if we can use GDB extensions. */ @@ -1319,7 +1322,7 @@ dbxout_type (type, full) larger. This is because we print the bounds as signed decimal, and hence they can't span same size unsigned types. */ - if (use_gnu_debug_info_extensions + if (use_gnu_debug_info_extensions && TYPE_MIN_VALUE (type) != 0 && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST && TYPE_MAX_VALUE (type) != 0 @@ -1348,7 +1351,7 @@ dbxout_type (type, full) else /* Output other integer types as subranges of `int'. */ dbxout_range_type (type); - } + } break; @@ -1861,7 +1864,7 @@ print_wide_int (c) CHARS (digs); } - + /* 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. */ @@ -1887,6 +1890,33 @@ dbxout_type_name (type) 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. */ + +static void +dbxout_class_name_qualifiers (decl) + tree decl; +{ + 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))) + { + tree name = TYPE_NAME (context); + + 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); + } +} /* Output a .stabs for the symbol defined by DECL, which must be a ..._DECL node in the normal namespace. @@ -2007,7 +2037,7 @@ dbxout_symbol (decl, local) && !TREE_ASM_WRITTEN (TYPE_NAME (type)) /* Distinguish the implicit typedefs of C++ from explicit ones that might be found in C. */ - && DECL_ARTIFICIAL (decl) + && DECL_ARTIFICIAL (decl) /* Do not generate a tag for records of variable size, since this type can not be properly described in the DBX format, and it confuses some tools such as objdump. */ @@ -2028,9 +2058,17 @@ dbxout_symbol (decl, local) dbxout_finish_symbol (NULL_TREE); } + /* Output .stabs (or whatever) and leading double quote. */ + fprintf (asmfile, "%s\"", ASM_STABS_OP); + + if (use_gnu_debug_info_extensions) + { + /* Output leading class/struct qualifiers. */ + dbxout_class_name_qualifiers (decl); + } + /* Output typedef name. */ - fprintf (asmfile, "%s\"%s:", ASM_STABS_OP, - IDENTIFIER_POINTER (DECL_NAME (decl))); + fprintf (asmfile, "%s:", IDENTIFIER_POINTER (DECL_NAME (decl))); /* Short cut way to output a tag also. */ if ((TREE_CODE (type) == RECORD_TYPE @@ -2039,7 +2077,7 @@ dbxout_symbol (decl, local) && TYPE_NAME (type) == decl /* Distinguish the implicit typedefs of C++ from explicit ones that might be found in C. */ - && DECL_ARTIFICIAL (decl)) + && DECL_ARTIFICIAL (decl)) { if (use_gnu_debug_info_extensions && have_used_extensions) { @@ -2172,7 +2210,7 @@ dbxout_symbol (decl, local) result = dbxout_symbol_location (decl, type, 0, DECL_RTL (decl)); break; - + default: break; } @@ -2196,7 +2234,7 @@ dbxout_symbol_location (decl, type, suffix, home) /* Don't mention a variable at all if it was completely optimized into nothingness. - + If the decl was from an inline function, then its rtl is not identically the rtl that was used in this particular compilation. */ @@ -2275,7 +2313,7 @@ dbxout_symbol_location (decl, type, suffix, home) || GET_CODE (tmp) == LABEL_REF) current_sym_addr = tmp; } - + /* Ultrix `as' seems to need this. */ #ifdef DBX_STATIC_STAB_DATA_SECTION data_section (); @@ -2480,7 +2518,7 @@ dbxout_finish_symbol (sym) #endif } -/* Output definitions of all the decls in a chain. Return non-zero if +/* Output definitions of all the decls in a chain. Return nonzero if anything was output */ int @@ -2564,7 +2602,7 @@ dbxout_parms (parms) } /* It is quite tempting to use: - + dbxout_type (TREE_TYPE (parms), 0); as the next statement, rather than using DECL_ARG_TYPE(), so @@ -2577,7 +2615,7 @@ dbxout_parms (parms) 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); + dbxout_type (DECL_ARG_TYPE (parms), 0); current_sym_value = DEBUGGER_ARG_OFFSET (current_sym_value, addr); dbxout_finish_symbol (parms); } @@ -2695,13 +2733,14 @@ dbxout_parms (parms) 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; + if (GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 0)) == REG) + current_sym_value = 0; 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); @@ -2739,7 +2778,7 @@ dbxout_parms (parms) && TYPE_MODE (TREE_TYPE (parms)) != GET_MODE (DECL_RTL (parms)) && GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))) < UNITS_PER_WORD) { - current_sym_value += + current_sym_value += GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))) - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))); } @@ -2849,7 +2888,7 @@ dbxout_block (block, depth, args) int blocknum = -1; #if DBX_BLOCKS_FUNCTION_RELATIVE - const char *begin_label; + const char *begin_label; if (current_function_func_begin_label != NULL_TREE) begin_label = IDENTIFIER_POINTER (current_function_func_begin_label); else diff --git a/contrib/gcc/dwarfout.c b/contrib/gcc/dwarfout.c index 481d0c0..bbbfcfc 100644 --- a/contrib/gcc/dwarfout.c +++ b/contrib/gcc/dwarfout.c @@ -1,6 +1,6 @@ /* Output Dwarf format symbol table information from the GNU C compiler. - Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, - 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 2002, + 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Contributed by Ron Guilmette (rfg@monkeys.com) of Network Computing Devices. This file is part of GCC. @@ -43,7 +43,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA The generation of DWARF debugging information by the GNU version 2.x C compiler has now been tested rather extensively for m88k, i386, i860, and - Sparc targets. The DWARF output of the GNU C compiler appears to inter- + SPARC targets. The DWARF output of the GNU C compiler appears to inter- operate well with the standard SVR4 SDB debugger on these kinds of target systems (but of course, there are no guarantees). @@ -162,7 +162,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA is required by the current DWARF draft specification. Specifically, the current DWARF draft specification seems to require that - the type of an non-unsigned integral bit-field member of a struct or union + the type of a non-unsigned integral bit-field member of a struct or union type be represented as either a "signed" type or as a "plain" type, depending upon the exact set of keywords that were used in the type specification for the given bit-field member. It was felt (by the @@ -523,7 +523,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA are still being discussed. Also, we in the PLSIG are still discussing whether or not we need to do anything special for C++ templates. (At this time it is not yet clear whether we even need to do anything special for - these.) + these.) With regard to FORTRAN, the UI/PLSIG has defined what is believed to be a complete and sufficient set of codes and rules for adequately representing @@ -560,7 +560,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA Other possible `compacting' transformations designed to save disk space and to reduce linker & debugger I/O activity. -*/ +*/ #include "config.h" @@ -569,6 +569,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "dwarf.h" #include "tree.h" #include "flags.h" +#include "function.h" #include "rtl.h" #include "hard-reg-set.h" #include "insn-config.h" @@ -599,7 +600,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA fprintf ((FILE), "%s", reg_names[REGNO (RTX)]) #endif -/* Define a macro which returns non-zero for any tagged type which is +/* Define a macro which returns nonzero for any tagged type which is used (directly or indirectly) in the specification of either some function's return type or some formal parameter of some function. We use this macro when we are operating in "terse" mode to help us @@ -611,12 +612,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA for these nodes. For now, we have to just fake it. It it safe for us to simply return zero for all complete tagged types (which will get forced out anyway if they were used in the specification of some - formal or return type) and non-zero for all incomplete tagged types. + formal or return type) and nonzero for all incomplete tagged types. */ #define TYPE_USED_FOR_FUNCTION(tagged_type) (TYPE_SIZE (tagged_type) == 0) -/* Define a macro which returns non-zero for a TYPE_DECL which was +/* Define a macro which returns nonzero for a TYPE_DECL which was implicitly generated for a tagged type. Note that unlike the gcc front end (which generates a NULL named @@ -631,8 +632,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA && is_tagged_type (TREE_TYPE (decl)) \ && decl == TYPE_STUB_DECL (TREE_TYPE (decl)))) -extern int flag_traditional; - /* Maximum size (in bytes) of an artificially generated label. */ #define MAX_ARTIFICIAL_LABEL_BYTES 30 @@ -708,7 +707,7 @@ static unsigned pending_siblings_allocated; #define PENDING_SIBLINGS_INCREMENT 64 -/* Non-zero if we are performing our file-scope finalization pass and if +/* Nonzero if we are performing our file-scope finalization pass and if we should force out Dwarf descriptions of any and all file-scope tagged types which are still incomplete types. */ @@ -758,14 +757,6 @@ static unsigned incomplete_types; static tree fake_containing_scope; -/* The number of the current function definition that we are generating - debugging information for. These numbers range from 1 up to the maximum - number of function definitions contained within the current compilation - unit. These numbers are used to create unique labels for various things - contained within various function definitions. */ - -static unsigned current_funcdef_number = 1; - /* A pointer to the ..._DECL node which we have most recently been working on. We keep this around just in case something about it looks screwy and we want to tell the user what the source coordinates for the actual @@ -791,9 +782,9 @@ static void dwarfout_end_source_file PARAMS ((unsigned)); static void dwarfout_end_source_file_check PARAMS ((unsigned)); static void dwarfout_begin_block PARAMS ((unsigned, unsigned)); static void dwarfout_end_block PARAMS ((unsigned, unsigned)); -static void dwarfout_end_epilogue PARAMS ((void)); +static void dwarfout_end_epilogue PARAMS ((unsigned int, const char *)); static void dwarfout_source_line PARAMS ((unsigned int, const char *)); -static void dwarfout_end_prologue PARAMS ((unsigned int)); +static void dwarfout_end_prologue PARAMS ((unsigned int, const char *)); static void dwarfout_end_function PARAMS ((unsigned int)); static void dwarfout_function_decl PARAMS ((tree)); static void dwarfout_global_decl PARAMS ((tree)); @@ -944,9 +935,6 @@ static void retry_incomplete_types PARAMS ((void)); #ifndef FILE_ASM_OP #define FILE_ASM_OP "\t.file\t" #endif -#ifndef VERSION_ASM_OP -#define VERSION_ASM_OP "\t.version\t" -#endif #ifndef SET_ASM_OP #define SET_ASM_OP "\t.set\t" #endif @@ -1150,18 +1138,6 @@ static void retry_incomplete_types PARAMS ((void)); #ifndef BOUND_END_LABEL_FMT #define BOUND_END_LABEL_FMT "*.L_b%u_%u_%c_e" #endif -#ifndef DERIV_BEGIN_LABEL_FMT -#define DERIV_BEGIN_LABEL_FMT "*.L_d%u" -#endif -#ifndef DERIV_END_LABEL_FMT -#define DERIV_END_LABEL_FMT "*.L_d%u_e" -#endif -#ifndef SL_BEGIN_LABEL_FMT -#define SL_BEGIN_LABEL_FMT "*.L_sl%u" -#endif -#ifndef SL_END_LABEL_FMT -#define SL_END_LABEL_FMT "*.L_sl%u_e" -#endif #ifndef BODY_BEGIN_LABEL_FMT #define BODY_BEGIN_LABEL_FMT "*.L_b%u" #endif @@ -1289,12 +1265,12 @@ static void retry_incomplete_types PARAMS ((void)); ASM_OUTPUT_ASCII ((FILE), P, strlen (P)+1) #else #define ASM_OUTPUT_DWARF_STRING_NEWLINE(FILE,P) \ - ASM_OUTPUT_DWARF_STRING (FILE,P), ASM_OUTPUT_DWARF_STRING (FILE,"\n") + ASM_OUTPUT_DWARF_STRING (FILE,P), ASM_OUTPUT_DWARF_STRING (FILE,"\n") #endif /* The debug hooks structure. */ -struct gcc_debug_hooks dwarf_debug_hooks = +const struct gcc_debug_hooks dwarf_debug_hooks = { dwarfout_init, dwarfout_finish, @@ -1325,7 +1301,7 @@ is_pseudo_reg (rtl) rtx rtl; { return (((GET_CODE (rtl) == REG) && (REGNO (rtl) >= FIRST_PSEUDO_REGISTER)) - || ((GET_CODE (rtl) == SUBREG) + || ((GET_CODE (rtl) == SUBREG) && (REGNO (SUBREG_REG (rtl)) >= FIRST_PSEUDO_REGISTER))); } @@ -1343,13 +1319,13 @@ type_main_variant (type) if (TREE_CODE (type) == ARRAY_TYPE) { while (type != TYPE_MAIN_VARIANT (type)) - type = TYPE_MAIN_VARIANT (type); + type = TYPE_MAIN_VARIANT (type); } return type; } -/* Return non-zero if the given type node represents a tagged type. */ +/* Return nonzero if the given type node represents a tagged type. */ static inline int is_tagged_type (type) @@ -1609,7 +1585,7 @@ static tree decl_ultimate_origin (decl) tree decl; { -#ifdef ENABLE_CHECKING +#ifdef ENABLE_CHECKING if (DECL_FROM_INLINE (DECL_ORIGIN (decl))) /* Since the DECL_ABSTRACT_ORIGIN for a DECL is supposed to be the most distant ancestor, this should never happen. */ @@ -1707,7 +1683,7 @@ output_signed_leb128 (value) if (negative) value |= 0xfe000000; /* manually sign extend */ if (((value == 0) && ((byte & 0x40) == 0)) - || ((value == -1) && ((byte & 0x40) == 1))) + || ((value == -1) && ((byte & 0x40) == 1))) more = 0; else { @@ -1974,7 +1950,7 @@ write_modifier_bytes (type, decl_const, decl_volatile) write_modifier_bytes_1 (type, decl_const, decl_volatile, 0); } -/* Given a pointer to an arbitrary ..._TYPE tree node, return non-zero if the +/* Given a pointer to an arbitrary ..._TYPE tree node, return nonzero if the given input type is a Dwarf "fundamental" type. Otherwise return zero. */ static inline int @@ -2843,8 +2819,8 @@ location_or_const_value_attribute (decl) if (rtl == NULL_RTX || is_pseudo_reg (rtl)) { /* This decl represents a formal parameter which was optimized out. */ - tree declared_type = type_main_variant (TREE_TYPE (decl)); - tree passed_type = type_main_variant (DECL_ARG_TYPE (decl)); + tree declared_type = type_main_variant (TREE_TYPE (decl)); + tree passed_type = type_main_variant (DECL_ARG_TYPE (decl)); /* Note that DECL_INCOMING_RTL may be NULL in here, but we handle *all* cases where (rtl == NULL_RTX) just below. */ @@ -3330,6 +3306,13 @@ member_attribute (context) } #if 0 +#ifndef SL_BEGIN_LABEL_FMT +#define SL_BEGIN_LABEL_FMT "*.L_sl%u" +#endif +#ifndef SL_END_LABEL_FMT +#define SL_END_LABEL_FMT "*.L_sl%u_e" +#endif + static inline void string_length_attribute (upper_bound) tree upper_bound; @@ -3468,10 +3451,10 @@ pure_or_virtual_attribute (func_decl) { #if 0 /* DECL_ABSTRACT_VIRTUAL_P is C++-specific. */ if (DECL_ABSTRACT_VIRTUAL_P (func_decl)) - ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_pure_virtual); + ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_pure_virtual); else #endif - ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_virtual); + ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_virtual); ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, ""); } } @@ -3510,7 +3493,7 @@ name_and_src_coords_attributes (decl) file_index = lookup_filename (DECL_SOURCE_FILE (decl)); ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_SECTION); - src_coords_attribute (file_index, DECL_SOURCE_LINE (decl)); + src_coords_attribute (file_index, DECL_SOURCE_LINE (decl)); } #endif /* defined(DWARF_DECL_COORDINATES) */ } @@ -3591,7 +3574,7 @@ type_tag (type) if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) t = TYPE_NAME (type); - /* The g++ front end makes the TYPE_NAME of *each* tagged type point to + /* The g++ front end makes the TYPE_NAME of *each* tagged type point to a TYPE_DECL node, regardless of whether or not a `typedef' was involved. */ else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL @@ -3898,13 +3881,14 @@ output_global_subroutine_die (arg) char label[MAX_ARTIFICIAL_LABEL_BYTES]; low_pc_attribute (function_start_label (decl)); - sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number); + sprintf (label, FUNC_END_LABEL_FMT, current_function_funcdef_no); high_pc_attribute (label); if (use_gnu_debug_info_extensions) { - sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number); + sprintf (label, BODY_BEGIN_LABEL_FMT, + current_function_funcdef_no); body_begin_attribute (label); - sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number); + sprintf (label, BODY_END_LABEL_FMT, current_function_funcdef_no); body_end_attribute (label); } } @@ -4154,8 +4138,6 @@ output_compile_unit_die (arg) language_attribute (LANG_PASCAL83); else if (strcmp (language_string, "GNU Java") == 0) language_attribute (LANG_JAVA); - else if (flag_traditional) - language_attribute (LANG_C); else language_attribute (LANG_C89); low_pc_attribute (TEXT_BEGIN_LABEL); @@ -4174,7 +4156,7 @@ output_compile_unit_die (arg) sf_names_attribute (SFNAMES_BEGIN_LABEL); src_info_attribute (SRCINFO_BEGIN_LABEL); if (debug_info_level >= DINFO_LEVEL_VERBOSE) - mac_info_attribute (MACINFO_BEGIN_LABEL); + mac_info_attribute (MACINFO_BEGIN_LABEL); } } @@ -4217,7 +4199,7 @@ output_inheritance_die (arg) ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_protected); ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, ""); } -} +} static void output_structure_type_die (arg) @@ -4281,13 +4263,14 @@ output_local_subroutine_die (arg) { char label[MAX_ARTIFICIAL_LABEL_BYTES]; low_pc_attribute (function_start_label (decl)); - sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number); + sprintf (label, FUNC_END_LABEL_FMT, current_function_funcdef_no); high_pc_attribute (label); if (use_gnu_debug_info_extensions) { - sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number); + sprintf (label, BODY_BEGIN_LABEL_FMT, + current_function_funcdef_no); body_begin_attribute (label); - sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number); + sprintf (label, BODY_END_LABEL_FMT, current_function_funcdef_no); body_end_attribute (label); } } @@ -4550,7 +4533,7 @@ pend_type (type) TREE_ASM_WRITTEN (type) = 1; } -/* Return non-zero if it is legitimate to output DIEs to represent a +/* Return nonzero if it is legitimate to output DIEs to represent a given type while we are generating the list of child DIEs for some DIE (e.g. a function or lexical block DIE) associated with a given scope. @@ -4801,7 +4784,7 @@ output_type (type, containing_scope) end_sibling_chain (); break; - case ARRAY_TYPE: + case ARRAY_TYPE: if (TYPE_STRING_FLAG (type) && TREE_CODE(TREE_TYPE(type)) == CHAR_TYPE) { output_type (TREE_TYPE (type), containing_scope); @@ -5156,8 +5139,8 @@ output_decls_for_scope (stmt, depth) tree subblocks; for (subblocks = BLOCK_SUBBLOCKS (stmt); - subblocks; - subblocks = BLOCK_CHAIN (subblocks)) + subblocks; + subblocks = BLOCK_CHAIN (subblocks)) output_block (subblocks, depth + 1); } } @@ -5203,10 +5186,10 @@ output_decl (decl, containing_scope) if ((TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE) && ((DECL_NAME (decl) == 0 && TYPE_NAME (TREE_TYPE (decl)) == 0) - || (TYPE_FIELDS (TREE_TYPE (decl)) + || (TYPE_FIELDS (TREE_TYPE (decl)) && (TREE_CODE (TYPE_FIELDS (TREE_TYPE (decl))) == ERROR_MARK)))) return; - + /* If this ..._DECL node is marked to be ignored, then ignore it. */ if (DECL_IGNORED_P (decl)) @@ -5331,7 +5314,7 @@ output_decl (decl, containing_scope) for (parm = arg_decls; parm; parm = TREE_CHAIN (parm)) if (TREE_CODE (parm) == PARM_DECL) - { + { if (DECL_NAME(parm) && !strcmp(IDENTIFIER_POINTER(DECL_NAME(parm)), "__builtin_va_alist") ) @@ -5368,13 +5351,13 @@ output_decl (decl, containing_scope) /* this is the prototyped case, check for ... */ if (TREE_VALUE (tree_last (fn_arg_types)) != void_type_node) output_die (output_unspecified_parameters_die, decl); - } - else - { - /* this is unprototyped, check for undefined (just declaration) */ - if (!DECL_INITIAL (decl)) - output_die (output_unspecified_parameters_die, decl); - } + } + else + { + /* this is unprototyped, check for undefined (just declaration) */ + if (!DECL_INITIAL (decl)) + output_die (output_unspecified_parameters_die, decl); + } } /* Output Dwarf info for all of the stuff within the body of the @@ -5433,7 +5416,7 @@ output_decl (decl, containing_scope) if (debug_info_level <= DINFO_LEVEL_TERSE) if (! TYPE_DECL_IS_STUB (decl) || (! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)) && ! in_class)) - return; + return; /* In the special case of a TYPE_DECL node representing the declaration of some type tag, if the given TYPE_DECL is @@ -5474,7 +5457,7 @@ output_decl (decl, containing_scope) any variable declarations or definitions. */ if (debug_info_level <= DINFO_LEVEL_TERSE) - break; + break; /* Output any DIEs that are needed to specify the type of this data object. */ @@ -5508,7 +5491,7 @@ output_decl (decl, containing_scope) function. */ { - void (*func) PARAMS ((void *)); + void (*func) PARAMS ((void *)); register tree origin = decl_ultimate_origin (decl); if (origin != NULL && TREE_CODE (origin) == PARM_DECL) @@ -5529,7 +5512,7 @@ output_decl (decl, containing_scope) if (DECL_NAME (decl) != 0) { output_type (member_declared_type (decl), containing_scope); - output_die (output_member_die, decl); + output_die (output_member_die, decl); } break; @@ -5629,7 +5612,7 @@ dwarfout_file_scope_decl (decl, set_finalizing) these same functions should NOT be ignored however. */ if (DECL_EXTERNAL (decl) && DECL_FUNCTION_CODE (decl)) - return; + return; /* What we would really like to do here is to filter out all mere file-scope declarations of file-scope functions which are never @@ -5729,7 +5712,7 @@ dwarfout_file_scope_decl (decl, set_finalizing) ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_ARANGES_SECTION); ASM_OUTPUT_DWARF_ADDR (asm_out_file, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); - ASM_OUTPUT_DWARF_DATA4 (asm_out_file, + ASM_OUTPUT_DWARF_DATA4 (asm_out_file, (unsigned) int_size_in_bytes (TREE_TYPE (decl))); ASM_OUTPUT_POP_SECTION (asm_out_file); } @@ -5739,7 +5722,7 @@ dwarfout_file_scope_decl (decl, set_finalizing) any variable declarations or definitions. */ if (debug_info_level <= DINFO_LEVEL_TERSE) - return; + return; break; @@ -5777,7 +5760,7 @@ dwarfout_file_scope_decl (decl, set_finalizing) if (debug_info_level <= DINFO_LEVEL_TERSE) if (! TYPE_DECL_IS_STUB (decl) || ! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl))) - return; + return; break; @@ -5807,7 +5790,7 @@ dwarfout_file_scope_decl (decl, set_finalizing) if this is not a nested function or class. If this is a nested type, then the remaining pending_types will be emitted when the containing type is handled. */ - + if (! DECL_CONTEXT (decl)) { if (pending_types != 0) @@ -5815,9 +5798,6 @@ dwarfout_file_scope_decl (decl, set_finalizing) } ASM_OUTPUT_POP_SECTION (asm_out_file); - - if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl) != NULL) - current_funcdef_number++; } /* Output a marker (i.e. a label) for the beginning of the generated code @@ -5855,8 +5835,9 @@ dwarfout_end_block (line, blocknum) to their home locations). */ static void -dwarfout_end_prologue (line) +dwarfout_end_prologue (line, file) unsigned int line ATTRIBUTE_UNUSED; + const char *file ATTRIBUTE_UNUSED; { char label[MAX_ARTIFICIAL_LABEL_BYTES]; @@ -5864,7 +5845,7 @@ dwarfout_end_prologue (line) return; function_section (current_function_decl); - sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number); + sprintf (label, BODY_BEGIN_LABEL_FMT, current_function_funcdef_no); ASM_OUTPUT_LABEL (asm_out_file, label); } @@ -5880,7 +5861,7 @@ dwarfout_end_function (line) if (! use_gnu_debug_info_extensions) return; function_section (current_function_decl); - sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number); + sprintf (label, BODY_END_LABEL_FMT, current_function_funcdef_no); ASM_OUTPUT_LABEL (asm_out_file, label); } @@ -5889,14 +5870,16 @@ dwarfout_end_function (line) has been generated. */ static void -dwarfout_end_epilogue () +dwarfout_end_epilogue (line, file) + unsigned int line ATTRIBUTE_UNUSED; + const char *file ATTRIBUTE_UNUSED; { char label[MAX_ARTIFICIAL_LABEL_BYTES]; /* Output a label to mark the endpoint of the code generated for this function. */ - sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number); + sprintf (label, FUNC_END_LABEL_FMT, current_function_funcdef_no); ASM_OUTPUT_LABEL (asm_out_file, label); } @@ -5936,9 +5919,9 @@ generate_new_sfname_entry () sprintf (label, SFNAMES_ENTRY_LABEL_FMT, filename_table[0].number); ASM_OUTPUT_LABEL (asm_out_file, label); ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, - filename_table[0].name - ? filename_table[0].name - : ""); + filename_table[0].name + ? filename_table[0].name + : ""); ASM_OUTPUT_POP_SECTION (asm_out_file); } @@ -5990,7 +5973,7 @@ lookup_filename (file_name) same filename will find it as quickly as possible. */ shuffle_filename_entry (search_p); - return filename_table[0].number; + return filename_table[0].number; } /* We come here whenever we have a new filename which is not registered @@ -6068,18 +6051,18 @@ dwarfout_source_line (line, filename) ASM_OUTPUT_PUSH_SECTION (asm_out_file, LINE_SECTION); if (this_file_entry_num != prev_file_entry_num) - { - char line_entry_label[MAX_ARTIFICIAL_LABEL_BYTES]; + { + char line_entry_label[MAX_ARTIFICIAL_LABEL_BYTES]; - sprintf (line_entry_label, LINE_ENTRY_LABEL_FMT, last_line_entry_num); - ASM_OUTPUT_LABEL (asm_out_file, line_entry_label); - } + sprintf (line_entry_label, LINE_ENTRY_LABEL_FMT, last_line_entry_num); + ASM_OUTPUT_LABEL (asm_out_file, line_entry_label); + } { - const char *tail = strrchr (filename, '/'); + const char *tail = strrchr (filename, '/'); - if (tail != NULL) - filename = tail; + if (tail != NULL) + filename = tail; } dw2_asm_output_data (4, line, "%s:%u", filename, line); @@ -6088,7 +6071,7 @@ dwarfout_source_line (line, filename) ASM_OUTPUT_POP_SECTION (asm_out_file); if (this_file_entry_num != prev_file_entry_num) - generate_srcinfo_entry (last_line_entry_num, this_file_entry_num); + generate_srcinfo_entry (last_line_entry_num, this_file_entry_num); prev_file_entry_num = this_file_entry_num; } } @@ -6195,6 +6178,8 @@ static void dwarfout_init (main_input_filename) const char *main_input_filename; { + warning ("support for the DWARF1 debugging format is deprecated"); + /* Remember the name of the primary input file. */ primary_filename = main_input_filename; @@ -6281,7 +6266,7 @@ dwarfout_init (main_input_filename) /* Output a starting label and an initial (compilation directory) entry for the .debug_sfnames section. The starting label will be referenced by the initial entry in the .debug_srcinfo section. */ - + fputc ('\n', asm_out_file); ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_SFNAMES_SECTION); ASM_OUTPUT_LABEL (asm_out_file, SFNAMES_BEGIN_LABEL); @@ -6298,29 +6283,29 @@ dwarfout_init (main_input_filename) } ASM_OUTPUT_POP_SECTION (asm_out_file); } - + if (debug_info_level >= DINFO_LEVEL_VERBOSE && use_gnu_debug_info_extensions) { - /* Output a starting label for the .debug_macinfo section. This + /* Output a starting label for the .debug_macinfo section. This label will be referenced by the AT_mac_info attribute in the TAG_compile_unit DIE. */ - - fputc ('\n', asm_out_file); - ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_MACINFO_SECTION); - ASM_OUTPUT_LABEL (asm_out_file, MACINFO_BEGIN_LABEL); - ASM_OUTPUT_POP_SECTION (asm_out_file); + + fputc ('\n', asm_out_file); + ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_MACINFO_SECTION); + ASM_OUTPUT_LABEL (asm_out_file, MACINFO_BEGIN_LABEL); + ASM_OUTPUT_POP_SECTION (asm_out_file); } /* Generate the initial entry for the .line section. */ - + fputc ('\n', asm_out_file); ASM_OUTPUT_PUSH_SECTION (asm_out_file, LINE_SECTION); ASM_OUTPUT_LABEL (asm_out_file, LINE_BEGIN_LABEL); ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, LINE_END_LABEL, LINE_BEGIN_LABEL); ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_BEGIN_LABEL); ASM_OUTPUT_POP_SECTION (asm_out_file); - + if (use_gnu_debug_info_extensions) { /* Generate the initial entry for the .debug_srcinfo section. */ @@ -6339,16 +6324,16 @@ dwarfout_init (main_input_filename) #endif ASM_OUTPUT_POP_SECTION (asm_out_file); } - + /* Generate the initial entry for the .debug_pubnames section. */ - + fputc ('\n', asm_out_file); ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_PUBNAMES_SECTION); ASM_OUTPUT_DWARF_ADDR (asm_out_file, DEBUG_BEGIN_LABEL); ASM_OUTPUT_POP_SECTION (asm_out_file); - + /* Generate the initial entry for the .debug_aranges section. */ - + fputc ('\n', asm_out_file); ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_ARANGES_SECTION); ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, @@ -6474,7 +6459,7 @@ dwarfout_finish (main_input_filename) if (debug_info_level >= DINFO_LEVEL_NORMAL) { /* Output a terminating entry for the .line section. */ - + fputc ('\n', asm_out_file); ASM_OUTPUT_PUSH_SECTION (asm_out_file, LINE_SECTION); ASM_OUTPUT_LABEL (asm_out_file, LINE_LAST_ENTRY_LABEL); @@ -6483,7 +6468,7 @@ dwarfout_finish (main_input_filename) ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, TEXT_END_LABEL, TEXT_BEGIN_LABEL); ASM_OUTPUT_LABEL (asm_out_file, LINE_END_LABEL); ASM_OUTPUT_POP_SECTION (asm_out_file); - + if (use_gnu_debug_info_extensions) { /* Output a terminating entry for the .debug_srcinfo section. */ @@ -6499,7 +6484,7 @@ dwarfout_finish (main_input_filename) if (debug_info_level >= DINFO_LEVEL_VERBOSE) { /* Output terminating entries for the .debug_macinfo section. */ - + dwarfout_end_source_file (0); fputc ('\n', asm_out_file); @@ -6508,15 +6493,15 @@ dwarfout_finish (main_input_filename) ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, ""); ASM_OUTPUT_POP_SECTION (asm_out_file); } - + /* Generate the terminating entry for the .debug_pubnames section. */ - + fputc ('\n', asm_out_file); ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_PUBNAMES_SECTION); ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0); ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, ""); ASM_OUTPUT_POP_SECTION (asm_out_file); - + /* Generate the terminating entries for the .debug_aranges section. Note that we want to do this only *after* we have output the end @@ -6530,7 +6515,7 @@ dwarfout_finish (main_input_filename) entries at this late point in the assembly output, we skirt the issue simply by avoiding forward-references. */ - + fputc ('\n', asm_out_file); ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_ARANGES_SECTION); diff --git a/contrib/gcc/emit-rtl.c b/contrib/gcc/emit-rtl.c index e2bbd85..172a82d 100644 --- a/contrib/gcc/emit-rtl.c +++ b/contrib/gcc/emit-rtl.c @@ -50,7 +50,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "insn-config.h" #include "recog.h" #include "real.h" -#include "obstack.h" #include "bitmap.h" #include "basic-block.h" #include "ggc.h" @@ -87,11 +86,17 @@ static int no_line_numbers; /* Commonly used rtx's, so that we only need space for one copy. These are initialized once for the entire compilation. - All of these except perhaps the floating-point CONST_DOUBLEs - are unique; no other rtx-object will be equal to any of these. */ + All of these are unique; no other rtx-object will be equal to any + of these. */ rtx global_rtl[GR_MAX]; +/* Commonly used RTL for hard registers. These objects are not necessarily + unique, so we allocate them separately from global_rtl. They are + initialized once per compilation unit, then copied into regno_reg_rtx + at the beginning of each function. */ +static GTY(()) rtx static_regno_reg_rtx[FIRST_PSEUDO_REGISTER]; + /* We record floating-point CONST_DOUBLEs in each floating-point mode for the values of 0, 1, and 2. For the integer entries and VOIDmode, we record a copy of const[012]_rtx. */ @@ -143,30 +148,16 @@ rtx const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1]; /* A hash table storing CONST_INTs whose absolute value is greater than MAX_SAVED_CONST_INT. */ -static htab_t const_int_htab; +static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def))) + htab_t const_int_htab; /* A hash table storing memory attribute structures. */ -static htab_t mem_attrs_htab; - -/* start_sequence and gen_sequence can make a lot of rtx expressions which are - shortly thrown away. We use two mechanisms to prevent this waste: - - For sizes up to 5 elements, we keep a SEQUENCE and its associated - rtvec for use by gen_sequence. One entry for each size is - sufficient because most cases are calls to gen_sequence followed by - immediately emitting the SEQUENCE. Reuse is safe since emitting a - sequence is destructive on the insn in it anyway and hence can't be - redone. - - We do not bother to save this cached data over nested function calls. - Instead, we just reinitialize them. */ - -#define SEQUENCE_RESULT_SIZE 5 - -static rtx sequence_result[SEQUENCE_RESULT_SIZE]; +static GTY ((if_marked ("ggc_marked_p"), param_is (struct mem_attrs))) + htab_t mem_attrs_htab; -/* During RTL generation, we also keep a list of free INSN rtl codes. */ -static rtx free_insn; +/* A hash table storing all CONST_DOUBLEs. */ +static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def))) + htab_t const_double_htab; #define first_insn (cfun->emit->x_first_insn) #define last_insn (cfun->emit->x_last_insn) @@ -178,7 +169,6 @@ static rtx free_insn; static rtx make_jump_insn_raw PARAMS ((rtx)); static rtx make_call_insn_raw PARAMS ((rtx)); static rtx find_line_note PARAMS ((rtx)); -static void mark_sequence_stack PARAMS ((struct sequence_stack *)); static rtx change_address_1 PARAMS ((rtx, enum machine_mode, rtx, int)); static void unshare_all_rtl_1 PARAMS ((rtx)); @@ -188,10 +178,13 @@ static void mark_label_nuses PARAMS ((rtx)); static hashval_t const_int_htab_hash PARAMS ((const void *)); static int const_int_htab_eq PARAMS ((const void *, const void *)); +static hashval_t const_double_htab_hash PARAMS ((const void *)); +static int const_double_htab_eq PARAMS ((const void *, + const void *)); +static rtx lookup_const_double PARAMS ((rtx)); static hashval_t mem_attrs_htab_hash PARAMS ((const void *)); static int mem_attrs_htab_eq PARAMS ((const void *, const void *)); -static void mem_attrs_mark PARAMS ((const void *)); static mem_attrs *get_mem_attrs PARAMS ((HOST_WIDE_INT, tree, rtx, rtx, unsigned int, enum machine_mode)); @@ -208,10 +201,10 @@ static hashval_t const_int_htab_hash (x) const void *x; { - return (hashval_t) INTVAL ((const struct rtx_def *) x); + return (hashval_t) INTVAL ((struct rtx_def *) x); } -/* Returns non-zero if the value represented by X (which is really a +/* Returns nonzero if the value represented by X (which is really a CONST_INT) is the same as that given by Y (which is really a HOST_WIDE_INT *). */ @@ -220,7 +213,41 @@ const_int_htab_eq (x, y) const void *x; const void *y; { - return (INTVAL ((const struct rtx_def *) x) == *((const HOST_WIDE_INT *) y)); + return (INTVAL ((rtx) x) == *((const HOST_WIDE_INT *) y)); +} + +/* Returns a hash code for X (which is really a CONST_DOUBLE). */ +static hashval_t +const_double_htab_hash (x) + const void *x; +{ + rtx value = (rtx) x; + hashval_t h; + + if (GET_MODE (value) == VOIDmode) + h = CONST_DOUBLE_LOW (value) ^ CONST_DOUBLE_HIGH (value); + else + h = real_hash (CONST_DOUBLE_REAL_VALUE (value)); + return h; +} + +/* Returns nonzero if the value represented by X (really a ...) + is the same as that represented by Y (really a ...) */ +static int +const_double_htab_eq (x, y) + const void *x; + const void *y; +{ + rtx a = (rtx)x, b = (rtx)y; + + if (GET_MODE (a) != GET_MODE (b)) + return 0; + if (GET_MODE (a) == VOIDmode) + return (CONST_DOUBLE_LOW (a) == CONST_DOUBLE_LOW (b) + && CONST_DOUBLE_HIGH (a) == CONST_DOUBLE_HIGH (b)); + else + return real_identical (CONST_DOUBLE_REAL_VALUE (a), + CONST_DOUBLE_REAL_VALUE (b)); } /* Returns a hash code for X (which is a really a mem_attrs *). */ @@ -237,7 +264,7 @@ mem_attrs_htab_hash (x) ^ (size_t) p->expr); } -/* Returns non-zero if the value represented by X (which is really a +/* Returns nonzero if the value represented by X (which is really a mem_attrs *) is the same as that given by Y (which is also really a mem_attrs *). */ @@ -253,25 +280,6 @@ mem_attrs_htab_eq (x, y) && p->size == q->size && p->align == q->align); } -/* This routine is called when we determine that we need a mem_attrs entry. - It marks the associated decl and RTL as being used, if present. */ - -static void -mem_attrs_mark (x) - const void *x; -{ - mem_attrs *p = (mem_attrs *) x; - - if (p->expr) - ggc_mark_tree (p->expr); - - if (p->offset) - ggc_mark_rtx (p->offset); - - if (p->size) - ggc_mark_rtx (p->size); -} - /* Allocate a new mem_attrs structure and insert it into the hash table if one identical to it is not already in the table. We are doing this for MEM of mode MODE. */ @@ -363,32 +371,133 @@ gen_int_mode (c, mode) return GEN_INT (trunc_int_for_mode (c, mode)); } -/* CONST_DOUBLEs needs special handling because their length is known - only at run-time. */ +/* CONST_DOUBLEs might be created from pairs of integers, or from + REAL_VALUE_TYPEs. Also, their length is known only at run time, + so we cannot use gen_rtx_raw_CONST_DOUBLE. */ + +/* Determine whether REAL, a CONST_DOUBLE, already exists in the + hash table. If so, return its counterpart; otherwise add it + to the hash table and return it. */ +static rtx +lookup_const_double (real) + rtx real; +{ + void **slot = htab_find_slot (const_double_htab, real, INSERT); + if (*slot == 0) + *slot = real; + + return (rtx) *slot; +} +/* Return a CONST_DOUBLE rtx for a floating-point value specified by + VALUE in mode MODE. */ rtx -gen_rtx_CONST_DOUBLE (mode, arg0, arg1) +const_double_from_real_value (value, mode) + REAL_VALUE_TYPE value; enum machine_mode mode; - HOST_WIDE_INT arg0, arg1; { - rtx r = rtx_alloc (CONST_DOUBLE); - int i; + rtx real = rtx_alloc (CONST_DOUBLE); + PUT_MODE (real, mode); - PUT_MODE (r, mode); - X0EXP (r, 0) = NULL_RTX; - XWINT (r, 1) = arg0; - XWINT (r, 2) = arg1; + memcpy (&CONST_DOUBLE_LOW (real), &value, sizeof (REAL_VALUE_TYPE)); - for (i = GET_RTX_LENGTH (CONST_DOUBLE) - 1; i > 2; --i) - XWINT (r, i) = 0; + return lookup_const_double (real); +} + +/* Return a CONST_DOUBLE or CONST_INT for a value specified as a pair + of ints: I0 is the low-order word and I1 is the high-order word. + Do not use this routine for non-integer modes; convert to + REAL_VALUE_TYPE and use CONST_DOUBLE_FROM_REAL_VALUE. */ + +rtx +immed_double_const (i0, i1, mode) + HOST_WIDE_INT i0, i1; + enum machine_mode mode; +{ + rtx value; + unsigned int i; + + 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; + } - return r; + /* If this integer fits in one word, return a CONST_INT. */ + if ((i1 == 0 && i0 >= 0) || (i1 == ~0 && i0 < 0)) + return GEN_INT (i0); + + /* We use VOIDmode for integers. */ + value = rtx_alloc (CONST_DOUBLE); + PUT_MODE (value, VOIDmode); + + CONST_DOUBLE_LOW (value) = i0; + CONST_DOUBLE_HIGH (value) = i1; + + for (i = 2; i < (sizeof CONST_DOUBLE_FORMAT - 1); i++) + XWINT (value, i) = 0; + + return lookup_const_double (value); } rtx gen_rtx_REG (mode, regno) enum machine_mode mode; - int regno; + unsigned int regno; { /* In case the MD file explicitly references the frame pointer, have all such references point to the same frame pointer. This is @@ -406,10 +515,12 @@ gen_rtx_REG (mode, regno) if (mode == Pmode && !reload_in_progress) { - if (regno == FRAME_POINTER_REGNUM) + if (regno == FRAME_POINTER_REGNUM + && (!reload_completed || frame_pointer_needed)) return frame_pointer_rtx; #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM - if (regno == HARD_FRAME_POINTER_REGNUM) + if (regno == HARD_FRAME_POINTER_REGNUM + && (!reload_completed || frame_pointer_needed)) return hard_frame_pointer_rtx; #endif #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM && HARD_FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM @@ -422,11 +533,31 @@ gen_rtx_REG (mode, regno) #endif if (regno == PIC_OFFSET_TABLE_REGNUM && fixed_regs[PIC_OFFSET_TABLE_REGNUM]) - return pic_offset_table_rtx; + return pic_offset_table_rtx; if (regno == STACK_POINTER_REGNUM) return stack_pointer_rtx; } +#if 0 + /* If the per-function register table has been set up, try to re-use + an existing entry in that table to avoid useless generation of RTL. + + This code is disabled for now until we can fix the various backends + which depend on having non-shared hard registers in some cases. Long + term we want to re-enable this code as it can significantly cut down + on the amount of useless RTL that gets generated. + + We'll also need to fix some code that runs after reload that wants to + set ORIGINAL_REGNO. */ + + if (cfun + && cfun->emit + && regno_reg_rtx + && regno < FIRST_PSEUDO_REGISTER + && reg_raw_mode[regno] == mode) + return regno_reg_rtx[regno]; +#endif + return gen_raw_REG (mode, regno); } @@ -463,7 +594,7 @@ gen_rtx_SUBREG (mode, reg, offset) if (offset >= GET_MODE_SIZE (GET_MODE (reg))) abort (); #endif - return gen_rtx_fmt_ei (SUBREG, mode, reg, offset); + return gen_rtx_raw_SUBREG (mode, reg, offset); } /* Generate a SUBREG representing the least-significant part of REG if MODE @@ -532,7 +663,7 @@ gen_rtx VPARAMS ((enum rtx_code code, enum machine_mode mode, ...)) HOST_WIDE_INT arg0 = va_arg (p, HOST_WIDE_INT); HOST_WIDE_INT arg1 = va_arg (p, HOST_WIDE_INT); - rt_val = gen_rtx_CONST_DOUBLE (mode, arg0, arg1); + rt_val = immed_double_const (arg0, arg1, mode); } break; @@ -671,12 +802,7 @@ gen_reg_rtx (mode) which makes much better code. Besides, allocating DCmode pseudos overstrains reload on some machines like the 386. */ rtx realpart, imagpart; - int size = GET_MODE_UNIT_SIZE (mode); - enum machine_mode partmode - = mode_for_size (size * BITS_PER_UNIT, - (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT - ? MODE_FLOAT : MODE_INT), - 0); + enum machine_mode partmode = GET_MODE_INNER (mode); realpart = gen_reg_rtx (partmode); imagpart = gen_reg_rtx (partmode); @@ -693,17 +819,17 @@ gen_reg_rtx (mode) rtx *new1; tree *new2; - new = xrealloc (f->emit->regno_pointer_align, old_size * 2); + new = ggc_realloc (f->emit->regno_pointer_align, old_size * 2); memset (new + old_size, 0, old_size); f->emit->regno_pointer_align = (unsigned char *) new; - new1 = (rtx *) xrealloc (f->emit->x_regno_reg_rtx, - old_size * 2 * sizeof (rtx)); + new1 = (rtx *) ggc_realloc (f->emit->x_regno_reg_rtx, + old_size * 2 * sizeof (rtx)); memset (new1 + old_size, 0, old_size * sizeof (rtx)); regno_reg_rtx = new1; - new2 = (tree *) xrealloc (f->emit->regno_decl, - old_size * 2 * sizeof (tree)); + new2 = (tree *) ggc_realloc (f->emit->regno_decl, + old_size * 2 * sizeof (tree)); memset (new2 + old_size, 0, old_size * sizeof (tree)); f->emit->regno_decl = new2; @@ -799,7 +925,11 @@ subreg_hard_regno (x, check_mode) 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) @@ -866,8 +996,12 @@ gen_lowpart_common (mode, x) return gen_rtx_fmt_e (GET_CODE (x), mode, XEXP (x, 0)); } else if (GET_CODE (x) == SUBREG || GET_CODE (x) == REG - || GET_CODE (x) == CONCAT) + || GET_CODE (x) == CONCAT || GET_CODE (x) == CONST_VECTOR) return simplify_gen_subreg (mode, x, GET_MODE (x), offset); + else if ((GET_MODE_CLASS (mode) == MODE_VECTOR_INT + || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) + && GET_MODE (x) == VOIDmode) + return simplify_gen_subreg (mode, x, int_mode_for_mode (mode), offset); /* If X is a CONST_INT or a CONST_DOUBLE, extract the appropriate bits from the low-order part of the constant. */ else if ((GET_MODE_CLASS (mode) == MODE_INT @@ -900,94 +1034,7 @@ gen_lowpart_common (mode, x) } } -#ifndef REAL_ARITHMETIC - /* If X is an integral constant but we want it in floating-point, it - must be the case that we have a union of an integer and a floating-point - value. If the machine-parameters allow it, simulate that union here - and return the result. The two-word and single-word cases are - different. */ - - else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT - && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD) - || flag_pretend_float) - && GET_MODE_CLASS (mode) == MODE_FLOAT - && GET_MODE_SIZE (mode) == UNITS_PER_WORD - && GET_CODE (x) == CONST_INT - && sizeof (float) * HOST_BITS_PER_CHAR == HOST_BITS_PER_WIDE_INT) - { - union {HOST_WIDE_INT i; float d; } u; - - u.i = INTVAL (x); - return CONST_DOUBLE_FROM_REAL_VALUE (u.d, mode); - } - else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT - && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD) - || flag_pretend_float) - && GET_MODE_CLASS (mode) == MODE_FLOAT - && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD - && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE) - && GET_MODE (x) == VOIDmode - && (sizeof (double) * HOST_BITS_PER_CHAR - == 2 * HOST_BITS_PER_WIDE_INT)) - { - union {HOST_WIDE_INT i[2]; double d; } u; - HOST_WIDE_INT low, high; - - if (GET_CODE (x) == CONST_INT) - low = INTVAL (x), high = low >> (HOST_BITS_PER_WIDE_INT -1); - else - low = CONST_DOUBLE_LOW (x), high = CONST_DOUBLE_HIGH (x); -#ifdef HOST_WORDS_BIG_ENDIAN - u.i[0] = high, u.i[1] = low; -#else - u.i[0] = low, u.i[1] = high; -#endif - return CONST_DOUBLE_FROM_REAL_VALUE (u.d, mode); - } - - /* Similarly, if this is converting a floating-point value into a - single-word integer. Only do this is the host and target parameters are - compatible. */ - - else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT - && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD) - || flag_pretend_float) - && (GET_MODE_CLASS (mode) == MODE_INT - || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) - && GET_CODE (x) == CONST_DOUBLE - && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT - && GET_MODE_BITSIZE (mode) == BITS_PER_WORD) - return constant_subword (x, (offset / UNITS_PER_WORD), GET_MODE (x)); - - /* Similarly, if this is converting a floating-point value into a - two-word integer, we can do this one word at a time and make an - integer. Only do this is the host and target parameters are - compatible. */ - - else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT - && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD) - || flag_pretend_float) - && (GET_MODE_CLASS (mode) == MODE_INT - || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) - && GET_CODE (x) == CONST_DOUBLE - && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT - && GET_MODE_BITSIZE (mode) == 2 * BITS_PER_WORD) - { - rtx lowpart, highpart; - - lowpart = constant_subword (x, - (offset / UNITS_PER_WORD) + WORDS_BIG_ENDIAN, - GET_MODE (x)); - highpart = constant_subword (x, - (offset / UNITS_PER_WORD) + (! WORDS_BIG_ENDIAN), - GET_MODE (x)); - if (lowpart && GET_CODE (lowpart) == CONST_INT - && highpart && GET_CODE (highpart) == CONST_INT) - return immed_double_const (INTVAL (lowpart), INTVAL (highpart), mode); - } -#else /* ifndef REAL_ARITHMETIC */ - - /* When we have a FP emulator, we can handle all conversions between + /* The floating-point emulator can handle all conversions between FP and integer operands. This simplifies reload because it doesn't have to deal with constructs like (subreg:DI (const_double:SF ...)) or (subreg:DF (const_int ...)). */ @@ -997,22 +1044,21 @@ gen_lowpart_common (mode, x) else if (GET_MODE_CLASS (mode) == MODE_FLOAT && GET_MODE_BITSIZE (mode) == 32 && GET_CODE (x) == CONST_INT) - { + { REAL_VALUE_TYPE r; - HOST_WIDE_INT i; + long i = INTVAL (x); - i = INTVAL (x); - r = REAL_VALUE_FROM_TARGET_SINGLE (i); + real_from_target (&r, &i, mode); return CONST_DOUBLE_FROM_REAL_VALUE (r, mode); - } + } else if (GET_MODE_CLASS (mode) == MODE_FLOAT && GET_MODE_BITSIZE (mode) == 64 && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE) && GET_MODE (x) == VOIDmode) { REAL_VALUE_TYPE r; - HOST_WIDE_INT i[2]; HOST_WIDE_INT low, high; + long i[2]; if (GET_CODE (x) == CONST_INT) { @@ -1025,18 +1071,17 @@ gen_lowpart_common (mode, x) high = CONST_DOUBLE_HIGH (x); } -#if HOST_BITS_PER_WIDE_INT == 32 + if (HOST_BITS_PER_WIDE_INT > 32) + high = low >> 31 >> 1; + /* REAL_VALUE_TARGET_DOUBLE takes the addressing order of the target machine. */ if (WORDS_BIG_ENDIAN) i[0] = high, i[1] = low; else i[0] = low, i[1] = high; -#else - i[0] = low; -#endif - r = REAL_VALUE_FROM_TARGET_DOUBLE (i); + real_from_target (&r, i, mode); return CONST_DOUBLE_FROM_REAL_VALUE (r, mode); } else if ((GET_MODE_CLASS (mode) == MODE_INT @@ -1054,16 +1099,16 @@ gen_lowpart_common (mode, x) switch (GET_MODE_BITSIZE (GET_MODE (x))) { case 32: - REAL_VALUE_TO_TARGET_SINGLE (r, i[3 * endian]); + REAL_VALUE_TO_TARGET_SINGLE (r, i[3 * endian]); i[1] = 0; i[2] = 0; - i[3 - 3 * endian] = 0; - break; + i[3 - 3 * endian] = 0; + break; case 64: - REAL_VALUE_TO_TARGET_DOUBLE (r, i + 2 * endian); + REAL_VALUE_TO_TARGET_DOUBLE (r, i + 2 * endian); i[2 - 2 * endian] = 0; i[3 - 2 * endian] = 0; - break; + break; case 96: REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, i + endian); i[3 - 3 * endian] = 0; @@ -1089,7 +1134,6 @@ gen_lowpart_common (mode, x) mode); #endif } -#endif /* ifndef REAL_ARITHMETIC */ /* Otherwise, we can't do this. */ return 0; @@ -1232,8 +1276,8 @@ gen_highpart (mode, x) be VOIDmode constant. */ rtx gen_highpart_mode (outermode, innermode, exp) - enum machine_mode outermode, innermode; - rtx exp; + enum machine_mode outermode, innermode; + rtx exp; { if (GET_MODE (exp) != VOIDmode) { @@ -1244,6 +1288,7 @@ gen_highpart_mode (outermode, innermode, exp) return simplify_gen_subreg (outermode, exp, innermode, subreg_highpart_offset (outermode, innermode)); } + /* Return offset in bytes to get OUTERMODE low part of the value in mode INNERMODE stored in memory in target format. */ @@ -1275,7 +1320,7 @@ subreg_highpart_offset (outermode, innermode) int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode)); if (GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode)) - abort (); + abort (); if (difference > 0) { @@ -1323,7 +1368,6 @@ constant_subword (op, offset, mode) && GET_MODE_SIZE (mode) == UNITS_PER_WORD) return op; -#ifdef REAL_ARITHMETIC /* The output is some bits, the width of the target machine's word. A wider-word host can surely hold them in a CONST_INT. A narrower-word host can't. */ @@ -1402,32 +1446,10 @@ constant_subword (op, offset, mode) else abort (); } -#else /* no REAL_ARITHMETIC */ - if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT - && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD) - || flag_pretend_float) - && GET_MODE_CLASS (mode) == MODE_FLOAT - && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD - && GET_CODE (op) == CONST_DOUBLE) - { - /* The constant is stored in the host's word-ordering, - but we want to access it in the target's word-ordering. Some - compilers don't like a conditional inside macro args, so we have two - copies of the return. */ -#ifdef HOST_WORDS_BIG_ENDIAN - return GEN_INT (offset == WORDS_BIG_ENDIAN - ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op)); -#else - return GEN_INT (offset != WORDS_BIG_ENDIAN - ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op)); -#endif - } -#endif /* no REAL_ARITHMETIC */ /* Single word float is a little harder, since single- and double-word values often do not have the same high-order bits. We have already verified that we want the only defined word of the single-word value. */ -#ifdef REAL_ARITHMETIC if (GET_MODE_CLASS (mode) == MODE_FLOAT && GET_MODE_BITSIZE (mode) == 32 && GET_CODE (op) == CONST_DOUBLE) @@ -1451,40 +1473,6 @@ constant_subword (op, offset, mode) return GEN_INT (val); } -#else - if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT - && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD) - || flag_pretend_float) - && sizeof (float) * 8 == HOST_BITS_PER_WIDE_INT - && GET_MODE_CLASS (mode) == MODE_FLOAT - && GET_MODE_SIZE (mode) == UNITS_PER_WORD - && GET_CODE (op) == CONST_DOUBLE) - { - double d; - union {float f; HOST_WIDE_INT i; } u; - - REAL_VALUE_FROM_CONST_DOUBLE (d, op); - - u.f = d; - return GEN_INT (u.i); - } - if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT - && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD) - || flag_pretend_float) - && sizeof (double) * 8 == HOST_BITS_PER_WIDE_INT - && GET_MODE_CLASS (mode) == MODE_FLOAT - && GET_MODE_SIZE (mode) == UNITS_PER_WORD - && GET_CODE (op) == CONST_DOUBLE) - { - double d; - union {double d; HOST_WIDE_INT i; } u; - - REAL_VALUE_FROM_CONST_DOUBLE (d, op); - - u.d = d; - return GEN_INT (u.i); - } -#endif /* no REAL_ARITHMETIC */ /* The only remaining cases that we can handle are integers. Convert to proper endianness now since these cases need it. @@ -1680,10 +1668,10 @@ component_ref_for_mem_expr (ref) || 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); + if (TREE_CODE (inner) == PLACEHOLDER_EXPR) + inner = find_placeholder (inner, &placeholder_ptr); + else + inner = TREE_OPERAND (inner, 0); if (! DECL_P (inner)) inner = NULL_TREE; @@ -1786,7 +1774,7 @@ set_mem_attributes_minus_bitpos (ref, t, objectp, bitpos) size = (DECL_SIZE_UNIT (t) && host_integerp (DECL_SIZE_UNIT (t), 1) ? GEN_INT (tree_low_cst (DECL_SIZE_UNIT (t), 1)) : 0); - align = DECL_ALIGN (t); + align = DECL_ALIGN (t); } /* If this is a constant, we know the alignment. */ @@ -1816,11 +1804,14 @@ set_mem_attributes_minus_bitpos (ref, t, objectp, bitpos) else if (TREE_CODE (t) == ARRAY_REF) { tree off_tree = size_zero_node; + /* We can't modify t, because we use it at the end of the + function. */ + tree t2 = t; do { - tree index = TREE_OPERAND (t, 1); - tree array = TREE_OPERAND (t, 0); + 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))); @@ -1838,7 +1829,7 @@ set_mem_attributes_minus_bitpos (ref, t, objectp, bitpos) component to one. */ if (! TREE_CONSTANT (index) && contains_placeholder_p (index)) - index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, t); + index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, t2); if (! TREE_CONSTANT (unit_size) && contains_placeholder_p (unit_size)) unit_size = build (WITH_RECORD_EXPR, sizetype, @@ -1850,28 +1841,28 @@ set_mem_attributes_minus_bitpos (ref, t, objectp, bitpos) index, unit_size)), off_tree)); - t = TREE_OPERAND (t, 0); + t2 = TREE_OPERAND (t2, 0); } - while (TREE_CODE (t) == ARRAY_REF); + while (TREE_CODE (t2) == ARRAY_REF); - if (DECL_P (t)) + if (DECL_P (t2)) { - expr = t; + expr = t2; offset = NULL; if (host_integerp (off_tree, 1)) { HOST_WIDE_INT ioff = tree_low_cst (off_tree, 1); HOST_WIDE_INT aoff = (ioff & -ioff) * BITS_PER_UNIT; - align = DECL_ALIGN (t); + align = DECL_ALIGN (t2); if (aoff && aoff < align) align = aoff; offset = GEN_INT (ioff); apply_bitpos = bitpos; } } - else if (TREE_CODE (t) == COMPONENT_REF) + else if (TREE_CODE (t2) == COMPONENT_REF) { - expr = component_ref_for_mem_expr (t); + expr = component_ref_for_mem_expr (t2); if (host_integerp (off_tree, 1)) { offset = GEN_INT (tree_low_cst (off_tree, 1)); @@ -1881,10 +1872,10 @@ set_mem_attributes_minus_bitpos (ref, t, objectp, bitpos) the size we got from the type? */ } else if (flag_argument_noalias > 1 - && TREE_CODE (t) == INDIRECT_REF - && TREE_CODE (TREE_OPERAND (t, 0)) == PARM_DECL) + && TREE_CODE (t2) == INDIRECT_REF + && TREE_CODE (TREE_OPERAND (t2, 0)) == PARM_DECL) { - expr = t; + expr = t2; offset = NULL; } } @@ -1942,7 +1933,7 @@ set_mem_alias_set (mem, set) rtx mem; HOST_WIDE_INT set; { -#ifdef ENABLE_CHECKING +#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 (); @@ -2082,7 +2073,7 @@ adjust_address_1 (memref, mode, offset, validate, adjust) unsigned int memalign = MEM_ALIGN (memref); /* ??? Prefer to create garbage instead of creating shared rtl. - This may happen even if offset is non-zero -- consider + This may happen even if offset is nonzero -- consider (plus (plus reg reg) const_int) -- so do this always. */ addr = copy_rtx (addr); @@ -2160,7 +2151,7 @@ offset_address (memref, offset, pow2) new = simplify_gen_binary (PLUS, Pmode, addr, offset); - /* At this point we don't know _why_ the address is invalid. It + /* At this point we don't know _why_ the address is invalid. It could have secondary memory refereces, multiplies or anything. However, if we did go and rearrange things, we can wind up not @@ -2187,7 +2178,7 @@ offset_address (memref, offset, pow2) GET_MODE (new)); return new; } - + /* Return a memory reference like MEMREF, but with its address changed to ADDR. The caller is asserting that the actual piece of memory pointed to is the same, just the form of the address is being changed, such as @@ -2299,14 +2290,8 @@ widen_memory_access (memref, mode, offset) rtx gen_label_rtx () { - rtx label; - - label = gen_rtx_CODE_LABEL (VOIDmode, 0, NULL_RTX, - NULL_RTX, label_num++, NULL, NULL); - - LABEL_NUSES (label) = 0; - LABEL_ALTERNATE_NAME (label) = NULL; - return label; + return gen_rtx_CODE_LABEL (VOIDmode, 0, NULL_RTX, NULL_RTX, + NULL, label_num++, NULL); } /* For procedure integration. */ @@ -2362,22 +2347,6 @@ restore_emit_status (p) struct function *p ATTRIBUTE_UNUSED; { last_label_num = 0; - clear_emit_caches (); -} - -/* Clear out all parts of the state in F that can safely be discarded - after the function has been compiled, to let garbage collection - reclaim the memory. */ - -void -free_emit_status (f) - struct function *f; -{ - free (f->emit->x_regno_reg_rtx); - free (f->emit->regno_pointer_align); - free (f->emit->regno_decl); - free (f->emit); - f->emit = NULL; } /* Go through all the RTL insn bodies and copy any invalid shared @@ -2532,11 +2501,11 @@ copy_most_rtx (orig, may_share) copy = rtx_alloc (code); PUT_MODE (copy, GET_MODE (orig)); - copy->in_struct = orig->in_struct; - copy->volatil = orig->volatil; - copy->unchanging = orig->unchanging; - copy->integrated = orig->integrated; - copy->frame_related = orig->frame_related; + 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)); @@ -2669,7 +2638,7 @@ copy_rtx_if_shared (orig) /* This rtx may not be shared. If it has already been seen, replace it with a copy of itself. */ - if (x->used) + if (RTX_FLAG (x, used)) { rtx copy; @@ -2680,7 +2649,7 @@ copy_rtx_if_shared (orig) x = copy; copied = 1; } - x->used = 1; + RTX_FLAG (x, used) = 1; /* Now scan the subexpressions recursively. We can store any replaced subexpressions directly into X @@ -2759,7 +2728,7 @@ reset_used_flags (x) break; } - x->used = 0; + RTX_FLAG (x, used) = 0; format_ptr = GET_RTX_FORMAT (code); for (i = 0; i < GET_RTX_LENGTH (code); i++) @@ -2826,6 +2795,17 @@ get_insns () return first_insn; } +/* Specify a new insn as the first in the chain. */ + +void +set_first_insn (insn) + rtx insn; +{ + if (PREV_INSN (insn) != 0) + abort (); + first_insn = insn; +} + /* Return the last insn emitted in current sequence or current function. */ rtx @@ -2859,6 +2839,42 @@ get_last_insn_anywhere () return 0; } +/* Return the first nonnote insn emitted in current sequence or current + function. This routine looks inside SEQUENCEs. */ + +rtx +get_first_nonnote_insn () +{ + rtx insn = first_insn; + + while (insn) + { + insn = next_insn (insn); + if (insn == 0 || GET_CODE (insn) != NOTE) + break; + } + + return insn; +} + +/* Return the last nonnote insn emitted in current sequence or current + function. This routine looks inside SEQUENCEs. */ + +rtx +get_last_nonnote_insn () +{ + rtx insn = last_insn; + + while (insn) + { + insn = previous_insn (insn); + if (insn == 0 || GET_CODE (insn) != NOTE) + break; + } + + return insn; +} + /* Return a number larger than any instruction's uid in this function. */ int @@ -3151,8 +3167,8 @@ prev_cc0_setter (insn) /* Increment the label uses for all labels present in rtx. */ static void -mark_label_nuses(x) - rtx x; +mark_label_nuses (x) + rtx x; { enum rtx_code code; int i, j; @@ -3166,9 +3182,9 @@ mark_label_nuses(x) for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') - mark_label_nuses (XEXP (x, i)); + mark_label_nuses (XEXP (x, i)); else if (fmt[i] == 'E') - for (j = XVECLEN (x, i) - 1; j >= 0; j--) + for (j = XVECLEN (x, i) - 1; j >= 0; j--) mark_label_nuses (XVECEXP (x, i, j)); } } @@ -3177,7 +3193,7 @@ mark_label_nuses(x) /* Try splitting insns that can be split for better scheduling. PAT is the pattern which might split. TRIAL is the insn providing PAT. - LAST is non-zero if we should return the last insn of the sequence produced. + LAST is nonzero if we should return the last insn of the sequence produced. If this routine succeeds in splitting, it returns the first or last replacement insn depending on the value of LAST. Otherwise, it @@ -3194,6 +3210,8 @@ try_split (pat, trial, last) rtx tem; rtx note, seq; int probability; + rtx insn_last, insn; + int njumps = 0; if (any_condjump_p (trial) && (note = find_reg_note (trial, REG_BR_PROB, 0))) @@ -3212,145 +3230,147 @@ try_split (pat, trial, last) after = NEXT_INSN (after); } - if (seq) + if (!seq) + return trial; + + /* Avoid infinite loop if any insn of the result matches + the original pattern. */ + insn_last = seq; + while (1) + { + if (INSN_P (insn_last) + && rtx_equal_p (PATTERN (insn_last), pat)) + return trial; + if (!NEXT_INSN (insn_last)) + break; + insn_last = NEXT_INSN (insn_last); + } + + /* Mark labels. */ + for (insn = insn_last; insn ; insn = PREV_INSN (insn)) { - /* SEQ can either be a SEQUENCE or the pattern of a single insn. - The latter case will normally arise only when being done so that - it, in turn, will be split (SFmode on the 29k is an example). */ - if (GET_CODE (seq) == SEQUENCE) + if (GET_CODE (insn) == JUMP_INSN) { - int i, njumps = 0; - - /* Avoid infinite loop if any insn of the result matches - the original pattern. */ - for (i = 0; i < XVECLEN (seq, 0); i++) - if (GET_CODE (XVECEXP (seq, 0, i)) == INSN - && rtx_equal_p (PATTERN (XVECEXP (seq, 0, i)), pat)) - return trial; - - /* Mark labels. */ - for (i = XVECLEN (seq, 0) - 1; i >= 0; i--) - if (GET_CODE (XVECEXP (seq, 0, i)) == JUMP_INSN) - { - rtx insn = XVECEXP (seq, 0, i); - mark_jump_label (PATTERN (insn), - XVECEXP (seq, 0, i), 0); - njumps++; - if (probability != -1 - && any_condjump_p (insn) - && !find_reg_note (insn, REG_BR_PROB, 0)) - { - /* We can preserve the REG_BR_PROB notes only if exactly - one jump is created, otherwise the machine description - is responsible for this step using - split_branch_probability variable. */ - if (njumps != 1) - abort (); - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_BR_PROB, - GEN_INT (probability), - REG_NOTES (insn)); - } - } - - /* 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) - for (i = XVECLEN (seq, 0) - 1; i >= 0; i--) - if (GET_CODE (XVECEXP (seq, 0, i)) == CALL_INSN) - CALL_INSN_FUNCTION_USAGE (XVECEXP (seq, 0, i)) - = CALL_INSN_FUNCTION_USAGE (trial); - - /* Copy notes, particularly those related to the CFG. */ - for (note = REG_NOTES (trial); note ; note = XEXP (note, 1)) + mark_jump_label (PATTERN (insn), insn, 0); + njumps++; + if (probability != -1 + && any_condjump_p (insn) + && !find_reg_note (insn, REG_BR_PROB, 0)) { - switch (REG_NOTE_KIND (note)) - { - case REG_EH_REGION: - for (i = XVECLEN (seq, 0) - 1; i >= 0; i--) - { - rtx insn = XVECEXP (seq, 0, i); - if (GET_CODE (insn) == CALL_INSN - || (flag_non_call_exceptions - && may_trap_p (PATTERN (insn)))) - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_EH_REGION, - XEXP (note, 0), - REG_NOTES (insn)); - } - break; + /* We can preserve the REG_BR_PROB notes only if exactly + one jump is created, otherwise the machine description + is responsible for this step using + split_branch_probability variable. */ + if (njumps != 1) + abort (); + REG_NOTES (insn) + = gen_rtx_EXPR_LIST (REG_BR_PROB, + GEN_INT (probability), + REG_NOTES (insn)); + } + } + } - case REG_NORETURN: - case REG_SETJMP: - case REG_ALWAYS_RETURN: - for (i = XVECLEN (seq, 0) - 1; i >= 0; i--) - { - rtx insn = XVECEXP (seq, 0, i); - if (GET_CODE (insn) == CALL_INSN) - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note), - XEXP (note, 0), - REG_NOTES (insn)); - } - break; + /* 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) + { + for (insn = insn_last; insn ; insn = PREV_INSN (insn)) + if (GET_CODE (insn) == CALL_INSN) + { + CALL_INSN_FUNCTION_USAGE (insn) + = CALL_INSN_FUNCTION_USAGE (trial); + SIBLING_CALL_P (insn) = SIBLING_CALL_P (trial); + } + } - case REG_NON_LOCAL_GOTO: - for (i = XVECLEN (seq, 0) - 1; i >= 0; i--) - { - rtx insn = XVECEXP (seq, 0, i); - if (GET_CODE (insn) == JUMP_INSN) - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note), - XEXP (note, 0), - REG_NOTES (insn)); - } - break; + /* Copy notes, particularly those related to the CFG. */ + for (note = REG_NOTES (trial); note; note = XEXP (note, 1)) + { + switch (REG_NOTE_KIND (note)) + { + case REG_EH_REGION: + insn = insn_last; + while (insn != NULL_RTX) + { + if (GET_CODE (insn) == CALL_INSN + || (flag_non_call_exceptions + && may_trap_p (PATTERN (insn)))) + REG_NOTES (insn) + = gen_rtx_EXPR_LIST (REG_EH_REGION, + XEXP (note, 0), + REG_NOTES (insn)); + insn = PREV_INSN (insn); + } + break; - default: - break; - } + case REG_NORETURN: + case REG_SETJMP: + case REG_ALWAYS_RETURN: + insn = insn_last; + while (insn != NULL_RTX) + { + if (GET_CODE (insn) == CALL_INSN) + REG_NOTES (insn) + = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note), + XEXP (note, 0), + REG_NOTES (insn)); + insn = PREV_INSN (insn); + } + break; + + case REG_NON_LOCAL_GOTO: + insn = insn_last; + while (insn != NULL_RTX) + { + if (GET_CODE (insn) == JUMP_INSN) + REG_NOTES (insn) + = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note), + XEXP (note, 0), + REG_NOTES (insn)); + insn = PREV_INSN (insn); } + break; - /* If there are LABELS inside the split insns increment the - usage count so we don't delete the label. */ - if (GET_CODE (trial) == INSN) - for (i = XVECLEN (seq, 0) - 1; i >= 0; i--) - if (GET_CODE (XVECEXP (seq, 0, i)) == INSN) - mark_label_nuses (PATTERN (XVECEXP (seq, 0, i))); - - tem = emit_insn_after (seq, trial); - - delete_related_insns (trial); - if (has_barrier) - emit_barrier_after (tem); - - /* Recursively call try_split for each new insn created; by the - time control returns here that insn will be fully split, so - set LAST and continue from the insn after the one returned. - We can't use next_active_insn here since AFTER may be a note. - Ignore deleted insns, which can be occur if not optimizing. */ - for (tem = NEXT_INSN (before); tem != after; tem = NEXT_INSN (tem)) - if (! INSN_DELETED_P (tem) && INSN_P (tem)) - tem = try_split (PATTERN (tem), tem, 1); + default: + break; } - /* Avoid infinite loop if the result matches the original pattern. */ - else if (rtx_equal_p (seq, pat)) - return trial; - else + } + + /* If there are LABELS inside the split insns increment the + usage count so we don't delete the label. */ + if (GET_CODE (trial) == INSN) + { + insn = insn_last; + while (insn != NULL_RTX) { - PATTERN (trial) = seq; - INSN_CODE (trial) = -1; - try_split (seq, trial, last); - } + if (GET_CODE (insn) == INSN) + mark_label_nuses (PATTERN (insn)); - /* Return either the first or the last insn, depending on which was - requested. */ - return last - ? (after ? PREV_INSN (after) : last_insn) - : NEXT_INSN (before); + insn = PREV_INSN (insn); + } } - return trial; + tem = emit_insn_after_scope (seq, trial, INSN_SCOPE (trial)); + + delete_insn (trial); + if (has_barrier) + emit_barrier_after (tem); + + /* Recursively call try_split for each new insn created; by the + time control returns here that insn will be fully split, so + set LAST and continue from the insn after the one returned. + We can't use next_active_insn here since AFTER may be a note. + Ignore deleted insns, which can be occur if not optimizing. */ + for (tem = NEXT_INSN (before); tem != after; tem = NEXT_INSN (tem)) + if (! INSN_DELETED_P (tem) && INSN_P (tem)) + tem = try_split (PATTERN (tem), tem, 1); + + /* Return either the first or the last insn, depending on which was + requested. */ + return last + ? (after ? PREV_INSN (after) : last_insn) + : NEXT_INSN (before); } /* Make and return an INSN rtx, initializing all its slots. @@ -3369,6 +3389,8 @@ make_insn_raw (pattern) INSN_CODE (insn) = -1; LOG_LINKS (insn) = NULL; REG_NOTES (insn) = NULL; + INSN_SCOPE (insn) = NULL; + BLOCK_FOR_INSN (insn) = NULL; #ifdef ENABLE_RTL_CHECKING if (insn @@ -3385,7 +3407,7 @@ make_insn_raw (pattern) return insn; } -/* Like `make_insn' but make a JUMP_INSN instead of an insn. */ +/* Like `make_insn_raw' but make a JUMP_INSN instead of an insn. */ static rtx make_jump_insn_raw (pattern) @@ -3401,11 +3423,13 @@ make_jump_insn_raw (pattern) LOG_LINKS (insn) = NULL; REG_NOTES (insn) = NULL; JUMP_LABEL (insn) = NULL; + INSN_SCOPE (insn) = NULL; + BLOCK_FOR_INSN (insn) = NULL; return insn; } -/* Like `make_insn' but make a CALL_INSN instead of an insn. */ +/* Like `make_insn_raw' but make a CALL_INSN instead of an insn. */ static rtx make_call_insn_raw (pattern) @@ -3421,6 +3445,8 @@ make_call_insn_raw (pattern) LOG_LINKS (insn) = NULL; REG_NOTES (insn) = NULL; CALL_INSN_FUNCTION_USAGE (insn) = NULL; + INSN_SCOPE (insn) = NULL; + BLOCK_FOR_INSN (insn) = NULL; return insn; } @@ -3485,11 +3511,13 @@ add_insn_after (insn, after) abort (); } - if (basic_block_for_insn - && (unsigned int) INSN_UID (after) < basic_block_for_insn->num_elements + if (GET_CODE (after) != BARRIER + && GET_CODE (insn) != BARRIER && (bb = BLOCK_FOR_INSN (after))) { 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->end == after @@ -3552,11 +3580,13 @@ add_insn_before (insn, before) abort (); } - if (basic_block_for_insn - && (unsigned int) INSN_UID (before) < basic_block_for_insn->num_elements + if (GET_CODE (before) != BARRIER + && GET_CODE (insn) != BARRIER && (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 == insn @@ -3630,10 +3660,11 @@ remove_insn (insn) if (stack == 0) abort (); } - if (basic_block_for_insn - && (unsigned int) INSN_UID (insn) < basic_block_for_insn->num_elements + if (GET_CODE (insn) != BARRIER && (bb = BLOCK_FOR_INSN (insn))) { + if (INSN_P (insn)) + bb->flags |= BB_DIRTY; if (bb->head == insn) { /* Never ever delete the basic block note without deleting whole @@ -3706,19 +3737,18 @@ reorder_insns (from, to, after) reorder_insns_nobb (from, to, after); - if (basic_block_for_insn - && (unsigned int) INSN_UID (after) < basic_block_for_insn->num_elements + if (GET_CODE (after) != BARRIER && (bb = BLOCK_FOR_INSN (after))) { rtx x; - - if (basic_block_for_insn - && ((unsigned int) INSN_UID (from) - < basic_block_for_insn->num_elements) + bb->flags |= BB_DIRTY; + + if (GET_CODE (from) != BARRIER && (bb2 = BLOCK_FOR_INSN (from))) { if (bb2->end == to) bb2->end = prev; + bb2->flags |= BB_DIRTY; } if (bb->end == after) @@ -3740,7 +3770,7 @@ find_line_note (insn) for (; insn; insn = PREV_INSN (insn)) if (GET_CODE (insn) == NOTE - && NOTE_LINE_NUMBER (insn) >= 0) + && NOTE_LINE_NUMBER (insn) >= 0) break; return insn; @@ -3841,7 +3871,7 @@ remove_unnecessary_notes () 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)) + 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 @@ -3885,76 +3915,173 @@ remove_unnecessary_notes () } -/* Emit an insn of given code and pattern - at a specified place within the doubly-linked list. */ +/* Emit insn(s) of given code and pattern + at a specified place within the doubly-linked list. -/* Make an instruction with body PATTERN - and output it before the instruction BEFORE. */ + All of the emit_foo global entry points accept an object + X which is either an insn list or a PATTERN of a single + instruction. + + There are thus a few canonical ways to generate code and + emit it at a specific place in the instruction stream. For + example, consider the instruction named SPOT and the fact that + we would like to emit some instructions before SPOT. We might + do it like this: + + start_sequence (); + ... emit the new instructions ... + insns_head = get_insns (); + end_sequence (); + + emit_insn_before (insns_head, SPOT); + + It used to be common to generate SEQUENCE rtl instead, but that + is a relic of the past which no longer occurs. The reason is that + SEQUENCE rtl results in much fragmented RTL memory since the SEQUENCE + generated would almost certainly die right after it was created. */ + +/* Make X be output before the instruction BEFORE. */ rtx -emit_insn_before (pattern, before) - rtx pattern, before; +emit_insn_before (x, before) + rtx x, before; { - rtx insn = before; + rtx last = before; + rtx insn; - if (GET_CODE (pattern) == SEQUENCE) - { - int i; +#ifdef ENABLE_RTL_CHECKING + if (before == NULL_RTX) + abort (); +#endif + + if (x == NULL_RTX) + return last; - for (i = 0; i < XVECLEN (pattern, 0); i++) + switch (GET_CODE (x)) + { + case INSN: + case JUMP_INSN: + case CALL_INSN: + case CODE_LABEL: + case BARRIER: + case NOTE: + insn = x; + while (insn) { - insn = XVECEXP (pattern, 0, i); + rtx next = NEXT_INSN (insn); add_insn_before (insn, before); + last = insn; + insn = next; } - } - else - { - insn = make_insn_raw (pattern); - add_insn_before (insn, before); + break; + +#ifdef ENABLE_RTL_CHECKING + case SEQUENCE: + abort (); + break; +#endif + + default: + last = make_insn_raw (x); + add_insn_before (last, before); + break; } - return insn; + return last; } -/* Make an instruction with body PATTERN and code JUMP_INSN +/* Make an instruction with body X and code JUMP_INSN and output it before the instruction BEFORE. */ rtx -emit_jump_insn_before (pattern, before) - rtx pattern, before; +emit_jump_insn_before (x, before) + rtx x, before; { - rtx insn; + rtx insn, last = NULL_RTX; - if (GET_CODE (pattern) == SEQUENCE) - insn = emit_insn_before (pattern, before); - else +#ifdef ENABLE_RTL_CHECKING + if (before == NULL_RTX) + abort (); +#endif + + switch (GET_CODE (x)) { - insn = make_jump_insn_raw (pattern); - add_insn_before (insn, before); + case INSN: + case JUMP_INSN: + case CALL_INSN: + case CODE_LABEL: + case BARRIER: + case NOTE: + insn = x; + while (insn) + { + rtx next = NEXT_INSN (insn); + add_insn_before (insn, before); + last = insn; + insn = next; + } + break; + +#ifdef ENABLE_RTL_CHECKING + case SEQUENCE: + abort (); + break; +#endif + + default: + last = make_jump_insn_raw (x); + add_insn_before (last, before); + break; } - return insn; + return last; } -/* Make an instruction with body PATTERN and code CALL_INSN +/* Make an instruction with body X and code CALL_INSN and output it before the instruction BEFORE. */ rtx -emit_call_insn_before (pattern, before) - rtx pattern, before; +emit_call_insn_before (x, before) + rtx x, before; { - rtx insn; + rtx last = NULL_RTX, insn; - if (GET_CODE (pattern) == SEQUENCE) - insn = emit_insn_before (pattern, before); - else +#ifdef ENABLE_RTL_CHECKING + if (before == NULL_RTX) + abort (); +#endif + + switch (GET_CODE (x)) { - insn = make_call_insn_raw (pattern); - add_insn_before (insn, before); - PUT_CODE (insn, CALL_INSN); + case INSN: + case JUMP_INSN: + case CALL_INSN: + case CODE_LABEL: + case BARRIER: + case NOTE: + insn = x; + while (insn) + { + rtx next = NEXT_INSN (insn); + add_insn_before (insn, before); + last = insn; + insn = next; + } + break; + +#ifdef ENABLE_RTL_CHECKING + case SEQUENCE: + abort (); + break; +#endif + + default: + last = make_call_insn_raw (x); + add_insn_before (last, before); + break; } - return insn; + return last; } /* Make an insn of code BARRIER @@ -4000,50 +4127,106 @@ emit_note_before (subtype, before) INSN_UID (note) = cur_insn_uid++; NOTE_SOURCE_FILE (note) = 0; NOTE_LINE_NUMBER (note) = subtype; + BLOCK_FOR_INSN (note) = NULL; add_insn_before (note, before); return note; } -/* Make an insn of code INSN with body PATTERN - and output it after the insn AFTER. */ +/* Helper for emit_insn_after, handles lists of instructions + efficiently. */ -rtx -emit_insn_after (pattern, after) - rtx pattern, after; +static rtx emit_insn_after_1 PARAMS ((rtx, rtx)); + +static rtx +emit_insn_after_1 (first, after) + rtx first, after; { - rtx insn = after; + rtx last; + rtx after_after; + basic_block bb; - if (GET_CODE (pattern) == SEQUENCE) + if (GET_CODE (after) != BARRIER + && (bb = BLOCK_FOR_INSN (after))) { - int i; - - for (i = 0; i < XVECLEN (pattern, 0); i++) - { - insn = XVECEXP (pattern, 0, i); - add_insn_after (insn, after); - after = insn; - } + bb->flags |= BB_DIRTY; + for (last = first; NEXT_INSN (last); last = NEXT_INSN (last)) + if (GET_CODE (last) != BARRIER) + set_block_for_insn (last, bb); + if (GET_CODE (last) != BARRIER) + set_block_for_insn (last, bb); + if (bb->end == after) + bb->end = last; } else + for (last = first; NEXT_INSN (last); last = NEXT_INSN (last)) + continue; + + after_after = NEXT_INSN (after); + + NEXT_INSN (after) = first; + PREV_INSN (first) = after; + NEXT_INSN (last) = after_after; + if (after_after) + PREV_INSN (after_after) = last; + + if (after == last_insn) + last_insn = last; + return last; +} + +/* Make X be output after the insn AFTER. */ + +rtx +emit_insn_after (x, after) + rtx x, after; +{ + rtx last = after; + +#ifdef ENABLE_RTL_CHECKING + if (after == NULL_RTX) + abort (); +#endif + + if (x == NULL_RTX) + return last; + + switch (GET_CODE (x)) { - insn = make_insn_raw (pattern); - add_insn_after (insn, after); + case INSN: + case JUMP_INSN: + case CALL_INSN: + case CODE_LABEL: + case BARRIER: + case NOTE: + last = emit_insn_after_1 (x, after); + break; + +#ifdef ENABLE_RTL_CHECKING + case SEQUENCE: + abort (); + break; +#endif + + default: + last = make_insn_raw (x); + add_insn_after (last, after); + break; } - return insn; + return last; } /* Similar to emit_insn_after, except that line notes are to be inserted so as to act as if this insn were at FROM. */ void -emit_insn_after_with_line_notes (pattern, after, from) - rtx pattern, after, from; +emit_insn_after_with_line_notes (x, after, from) + rtx x, after, from; { rtx from_line = find_line_note (from); rtx after_line = find_line_note (after); - rtx insn = emit_insn_after (pattern, after); + rtx insn = emit_insn_after (x, after); if (from_line) emit_line_note_after (NOTE_SOURCE_FILE (from_line), @@ -4056,24 +4239,84 @@ emit_insn_after_with_line_notes (pattern, after, from) insn); } -/* Make an insn of code JUMP_INSN with body PATTERN +/* Make an insn of code JUMP_INSN with body X and output it after the insn AFTER. */ rtx -emit_jump_insn_after (pattern, after) - rtx pattern, after; +emit_jump_insn_after (x, after) + rtx x, after; { - rtx insn; + rtx last; - if (GET_CODE (pattern) == SEQUENCE) - insn = emit_insn_after (pattern, after); - else +#ifdef ENABLE_RTL_CHECKING + if (after == NULL_RTX) + abort (); +#endif + + switch (GET_CODE (x)) { - insn = make_jump_insn_raw (pattern); - add_insn_after (insn, after); + case INSN: + case JUMP_INSN: + case CALL_INSN: + case CODE_LABEL: + case BARRIER: + case NOTE: + last = emit_insn_after_1 (x, after); + break; + +#ifdef ENABLE_RTL_CHECKING + case SEQUENCE: + abort (); + break; +#endif + + default: + last = make_jump_insn_raw (x); + add_insn_after (last, after); + break; } - return insn; + return last; +} + +/* Make an instruction with body X and code CALL_INSN + and output it after the instruction AFTER. */ + +rtx +emit_call_insn_after (x, after) + rtx x, after; +{ + rtx last; + +#ifdef ENABLE_RTL_CHECKING + if (after == NULL_RTX) + abort (); +#endif + + switch (GET_CODE (x)) + { + case INSN: + case JUMP_INSN: + case CALL_INSN: + case CODE_LABEL: + case BARRIER: + case NOTE: + last = emit_insn_after_1 (x, after); + break; + +#ifdef ENABLE_RTL_CHECKING + case SEQUENCE: + abort (); + break; +#endif + + default: + last = make_call_insn_raw (x); + add_insn_after (last, after); + break; + } + + return last; } /* Make an insn of code BARRIER @@ -4120,6 +4363,7 @@ emit_note_after (subtype, after) INSN_UID (note) = cur_insn_uid++; NOTE_SOURCE_FILE (note) = 0; NOTE_LINE_NUMBER (note) = subtype; + BLOCK_FOR_INSN (note) = NULL; add_insn_after (note, after); return note; } @@ -4140,165 +4384,219 @@ emit_line_note_after (file, line, after) return 0; } - note = rtx_alloc (NOTE); + note = rtx_alloc (NOTE); INSN_UID (note) = cur_insn_uid++; NOTE_SOURCE_FILE (note) = file; NOTE_LINE_NUMBER (note) = line; + BLOCK_FOR_INSN (note) = NULL; add_insn_after (note, after); return note; } -/* Make an insn of code INSN with pattern PATTERN - and add it to the end of the doubly-linked list. - If PATTERN is a SEQUENCE, take the elements of it - and emit an insn for each element. - - Returns the last insn emitted. */ - +/* Like emit_insn_after, but set INSN_SCOPE according to SCOPE. */ rtx -emit_insn (pattern) - rtx pattern; +emit_insn_after_scope (pattern, after, scope) + rtx pattern, after; + tree scope; { - rtx insn = last_insn; + rtx last = emit_insn_after (pattern, after); - if (GET_CODE (pattern) == SEQUENCE) + after = NEXT_INSN (after); + while (1) { - int i; - - for (i = 0; i < XVECLEN (pattern, 0); i++) - { - insn = XVECEXP (pattern, 0, i); - add_insn (insn); - } + if (active_insn_p (after)) + INSN_SCOPE (after) = scope; + if (after == last) + break; + after = NEXT_INSN (after); } - else + return last; +} + +/* Like emit_jump_insn_after, but set INSN_SCOPE according to SCOPE. */ +rtx +emit_jump_insn_after_scope (pattern, after, scope) + rtx pattern, after; + tree scope; +{ + rtx last = emit_jump_insn_after (pattern, after); + + after = NEXT_INSN (after); + while (1) { - insn = make_insn_raw (pattern); - add_insn (insn); + if (active_insn_p (after)) + INSN_SCOPE (after) = scope; + if (after == last) + break; + after = NEXT_INSN (after); } - - return insn; + return last; } -/* Emit the insns in a chain starting with INSN. - Return the last insn emitted. */ - +/* Like emit_call_insn_after, but set INSN_SCOPE according to SCOPE. */ rtx -emit_insns (insn) - rtx insn; +emit_call_insn_after_scope (pattern, after, scope) + rtx pattern, after; + tree scope; { - rtx last = 0; + rtx last = emit_call_insn_after (pattern, after); - while (insn) + after = NEXT_INSN (after); + while (1) { - rtx next = NEXT_INSN (insn); - add_insn (insn); - last = insn; - insn = next; + if (active_insn_p (after)) + INSN_SCOPE (after) = scope; + if (after == last) + break; + after = NEXT_INSN (after); } - return last; } -/* Emit the insns in a chain starting with INSN and place them in front of - the insn BEFORE. Return the last insn emitted. */ - +/* Like emit_insn_before, but set INSN_SCOPE according to SCOPE. */ rtx -emit_insns_before (insn, before) - rtx insn; - rtx before; +emit_insn_before_scope (pattern, before, scope) + rtx pattern, before; + tree scope; { - rtx last = 0; + rtx first = PREV_INSN (before); + rtx last = emit_insn_before (pattern, before); - while (insn) + first = NEXT_INSN (first); + while (1) { - rtx next = NEXT_INSN (insn); - add_insn_before (insn, before); - last = insn; - insn = next; + if (active_insn_p (first)) + INSN_SCOPE (first) = scope; + if (first == last) + break; + first = NEXT_INSN (first); } - return last; } + +/* Take X and emit it at the end of the doubly-linked + INSN list. -/* Emit the insns in a chain starting with FIRST and place them in back of - the insn AFTER. Return the last insn emitted. */ + Returns the last insn emitted. */ rtx -emit_insns_after (first, after) - rtx first; - rtx after; +emit_insn (x) + rtx x; { - rtx last; - rtx after_after; - basic_block bb; - - if (!after) - abort (); + rtx last = last_insn; + rtx insn; - if (!first) - return after; + if (x == NULL_RTX) + return last; - if (basic_block_for_insn - && (unsigned int) INSN_UID (after) < basic_block_for_insn->num_elements - && (bb = BLOCK_FOR_INSN (after))) + switch (GET_CODE (x)) { - for (last = first; NEXT_INSN (last); last = NEXT_INSN (last)) - set_block_for_insn (last, bb); - set_block_for_insn (last, bb); - if (bb->end == after) - bb->end = last; - } - else - for (last = first; NEXT_INSN (last); last = NEXT_INSN (last)) - continue; + case INSN: + case JUMP_INSN: + case CALL_INSN: + case CODE_LABEL: + case BARRIER: + case NOTE: + insn = x; + while (insn) + { + rtx next = NEXT_INSN (insn); + add_insn (insn); + last = insn; + insn = next; + } + break; - after_after = NEXT_INSN (after); +#ifdef ENABLE_RTL_CHECKING + case SEQUENCE: + abort (); + break; +#endif - NEXT_INSN (after) = first; - PREV_INSN (first) = after; - NEXT_INSN (last) = after_after; - if (after_after) - PREV_INSN (after_after) = last; + default: + last = make_insn_raw (x); + add_insn (last); + break; + } - if (after == last_insn) - last_insn = last; return last; } -/* Make an insn of code JUMP_INSN with pattern PATTERN +/* Make an insn of code JUMP_INSN with pattern X and add it to the end of the doubly-linked list. */ rtx -emit_jump_insn (pattern) - rtx pattern; +emit_jump_insn (x) + rtx x; { - if (GET_CODE (pattern) == SEQUENCE) - return emit_insn (pattern); - else + rtx last = NULL_RTX, insn; + + switch (GET_CODE (x)) { - rtx insn = make_jump_insn_raw (pattern); - add_insn (insn); - return insn; + case INSN: + case JUMP_INSN: + case CALL_INSN: + case CODE_LABEL: + case BARRIER: + case NOTE: + insn = x; + while (insn) + { + rtx next = NEXT_INSN (insn); + add_insn (insn); + last = insn; + insn = next; + } + break; + +#ifdef ENABLE_RTL_CHECKING + case SEQUENCE: + abort (); + break; +#endif + + default: + last = make_jump_insn_raw (x); + add_insn (last); + break; } + + return last; } -/* Make an insn of code CALL_INSN with pattern PATTERN +/* Make an insn of code CALL_INSN with pattern X and add it to the end of the doubly-linked list. */ rtx -emit_call_insn (pattern) - rtx pattern; +emit_call_insn (x) + rtx x; { - if (GET_CODE (pattern) == SEQUENCE) - return emit_insn (pattern); - else + rtx insn; + + switch (GET_CODE (x)) { - rtx insn = make_call_insn_raw (pattern); + case INSN: + case JUMP_INSN: + case CALL_INSN: + case CODE_LABEL: + case BARRIER: + case NOTE: + insn = emit_insn (x); + break; + +#ifdef ENABLE_RTL_CHECKING + case SEQUENCE: + abort (); + break; +#endif + + default: + insn = make_call_insn_raw (x); add_insn (insn); - PUT_CODE (insn, CALL_INSN); - return insn; + break; } + + return insn; } /* Add the label LABEL to the end of the doubly-linked list. */ @@ -4381,6 +4679,7 @@ emit_note (file, line) INSN_UID (note) = cur_insn_uid++; NOTE_SOURCE_FILE (note) = file; NOTE_LINE_NUMBER (note) = line; + BLOCK_FOR_INSN (note) = NULL; add_insn (note); return note; } @@ -4515,6 +4814,9 @@ emit (x) abort (); } +/* Space for free sequence stack entries. */ +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 @@ -4528,7 +4830,13 @@ start_sequence () { struct sequence_stack *tem; - tem = (struct sequence_stack *) xmalloc (sizeof (struct sequence_stack)); + if (free_sequence_stack != NULL) + { + tem = free_sequence_stack; + free_sequence_stack = tem->next; + } + else + tem = (struct sequence_stack *) ggc_alloc (sizeof (struct sequence_stack)); tem->next = seq_stack; tem->first = first_insn; @@ -4625,12 +4933,12 @@ pop_topmost_sequence () /* After emitting to a sequence, restore previous saved state. To get the contents of the sequence just made, you must call - `gen_sequence' *before* calling here. + `get_insns' *before* calling here. If the compiler might have deferred popping arguments while generating this sequence, and this sequence will not be immediately inserted into the instruction stream, use do_pending_stack_adjust - before calling gen_sequence. That will ensure that the deferred + before calling get_insns. That will ensure that the deferred pops are inserted into this sequence, and not into some random location in the instruction stream. See INHIBIT_DEFER_POP for more information about deferred popping of arguments. */ @@ -4645,7 +4953,9 @@ end_sequence () seq_rtl_expr = tem->sequence_rtl_expr; seq_stack = tem->next; - free (tem); + memset (tem, 0, sizeof (*tem)); + tem->next = free_sequence_stack; + free_sequence_stack = tem; } /* This works like end_sequence, but records the old sequence in FIRST @@ -4657,7 +4967,7 @@ end_full_sequence (first, last) { *first = first_insn; *last = last_insn; - end_sequence(); + end_sequence (); } /* Return 1 if currently emitting into a sequence. */ @@ -4667,45 +4977,6 @@ in_sequence_p () { return seq_stack != 0; } - -/* Generate a SEQUENCE rtx containing the insns already emitted - to the current sequence. - - This is how the gen_... function from a DEFINE_EXPAND - constructs the SEQUENCE that it returns. */ - -rtx -gen_sequence () -{ - rtx result; - rtx tem; - int i; - int len; - - /* Count the insns in the chain. */ - len = 0; - for (tem = first_insn; tem; tem = NEXT_INSN (tem)) - len++; - - /* If only one insn, return it rather than a SEQUENCE. - (Now that we cache SEQUENCE expressions, it isn't worth special-casing - the case of an empty list.) - We only return the pattern of an insn if its code is INSN and it - has no notes. This ensures that no information gets lost. */ - if (len == 1 - && ! RTX_FRAME_RELATED_P (first_insn) - && GET_CODE (first_insn) == INSN - /* Don't throw away any reg notes. */ - && REG_NOTES (first_insn) == 0) - return PATTERN (first_insn); - - result = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (len)); - - for (i = 0, tem = first_insn; tem; tem = NEXT_INSN (tem), i++) - XVECEXP (result, 0, i) = tem; - - return result; -} /* Put the various virtual registers into REGNO_REG_RTX. */ @@ -4721,16 +4992,6 @@ init_virtual_regs (es) ptr[VIRTUAL_CFA_REGNUM] = virtual_cfa_rtx; } -void -clear_emit_caches () -{ - int i; - - /* Clear the start_sequence/gen_sequence cache. */ - for (i = 0; i < SEQUENCE_RESULT_SIZE; i++) - sequence_result[i] = 0; - free_insn = 0; -} /* Used by copy_insn_1 to avoid copying SCRATCHes more than once. */ static rtx copy_insn_scratch_in[MAX_RECOG_OPERANDS]; @@ -4818,14 +5079,14 @@ copy_insn_1 (orig) /* We do not copy the USED flag, which is used as a mark bit during walks over the RTL. */ - copy->used = 0; + RTX_FLAG (copy, used) = 0; /* We do not copy JUMP, CALL, or FRAME_RELATED for INSNs. */ if (GET_RTX_CLASS (code) == 'i') { - copy->jump = 0; - copy->call = 0; - copy->frame_related = 0; + RTX_FLAG (copy, jump) = 0; + RTX_FLAG (copy, call) = 0; + RTX_FLAG (copy, frame_related) = 0; } format_ptr = GET_RTX_FORMAT (GET_CODE (copy)); @@ -4913,7 +5174,7 @@ init_emit () { struct function *f = cfun; - f->emit = (struct emit_status *) xmalloc (sizeof (struct emit_status)); + f->emit = (struct emit_status *) ggc_alloc (sizeof (struct emit_status)); first_insn = NULL; last_insn = NULL; seq_rtl_expr = NULL; @@ -4925,21 +5186,26 @@ init_emit () last_label_num = 0; seq_stack = NULL; - clear_emit_caches (); - /* Init the tables that describe all the pseudo regs. */ f->emit->regno_pointer_align_length = LAST_VIRTUAL_REGISTER + 101; f->emit->regno_pointer_align - = (unsigned char *) xcalloc (f->emit->regno_pointer_align_length, - sizeof (unsigned char)); + = (unsigned char *) ggc_alloc_cleared (f->emit->regno_pointer_align_length + * sizeof (unsigned char)); regno_reg_rtx - = (rtx *) xcalloc (f->emit->regno_pointer_align_length, sizeof (rtx)); + = (rtx *) ggc_alloc_cleared (f->emit->regno_pointer_align_length + * sizeof (rtx)); f->emit->regno_decl - = (tree *) xcalloc (f->emit->regno_pointer_align_length, sizeof (tree)); + = (tree *) ggc_alloc_cleared (f->emit->regno_pointer_align_length + * sizeof (tree)); + + /* Put copies of all the hard registers into regno_reg_rtx. */ + memcpy (regno_reg_rtx, + static_regno_reg_rtx, + FIRST_PSEUDO_REGISTER * sizeof (rtx)); /* Put copies of all the virtual register rtx into regno_reg_rtx. */ init_virtual_regs (f->emit); @@ -4975,46 +5241,6 @@ init_emit () #endif } -/* Mark SS for GC. */ - -static void -mark_sequence_stack (ss) - struct sequence_stack *ss; -{ - while (ss) - { - ggc_mark_rtx (ss->first); - ggc_mark_tree (ss->sequence_rtl_expr); - ss = ss->next; - } -} - -/* Mark ES for GC. */ - -void -mark_emit_status (es) - struct emit_status *es; -{ - rtx *r; - tree *t; - int i; - - if (es == 0) - return; - - for (i = es->regno_pointer_align_length, r = es->x_regno_reg_rtx, - t = es->regno_decl; - i > 0; --i, ++r, ++t) - { - ggc_mark_rtx (*r); - ggc_mark_tree (*t); - } - - mark_sequence_stack (es->sequence_stack); - ggc_mark_tree (es->sequence_rtl_expr); - ggc_mark_rtx (es->x_first_insn); -} - /* Generate the constant 0. */ static rtx @@ -5038,10 +5264,26 @@ gen_const_vector_0 (mode) for (i = 0; i < units; ++i) RTVEC_ELT (v, i) = CONST0_RTX (inner); - tem = gen_rtx_CONST_VECTOR (mode, v); + 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. */ +rtx +gen_rtx_CONST_VECTOR (mode, v) + enum machine_mode mode; + rtvec v; +{ + rtx inner_zero = CONST0_RTX (GET_MODE_INNER (mode)); + 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); +} + /* Create some permanent unique rtl objects shared between all functions. LINE_NUMBERS is nonzero if line numbers are to be generated. */ @@ -5053,14 +5295,16 @@ init_emit_once (line_numbers) enum machine_mode mode; enum machine_mode double_mode; - /* Initialize the CONST_INT and memory attribute hash tables. */ + /* Initialize the CONST_INT, CONST_DOUBLE, and memory attribute hash + tables. */ const_int_htab = htab_create (37, const_int_htab_hash, const_int_htab_eq, NULL); - ggc_add_deletable_htab (const_int_htab, 0, 0); + + const_double_htab = htab_create (37, const_double_htab_hash, + const_double_htab_eq, NULL); mem_attrs_htab = htab_create (37, mem_attrs_htab_hash, mem_attrs_htab_eq, NULL); - ggc_add_deletable_htab (mem_attrs_htab, 0, mem_attrs_mark); no_line_numbers = ! line_numbers; @@ -5115,8 +5359,10 @@ init_emit_once (line_numbers) gen_raw_REG (Pmode, VIRTUAL_OUTGOING_ARGS_REGNUM); virtual_cfa_rtx = gen_raw_REG (Pmode, VIRTUAL_CFA_REGNUM); - /* These rtx must be roots if GC is enabled. */ - ggc_add_rtx_root (global_rtl, GR_MAX); + /* Initialize RTL for commonly used hard registers. These are + copied into regno_reg_rtx as we begin to compile each function. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + static_regno_reg_rtx[i] = gen_raw_REG (reg_raw_mode[i], i); #ifdef INIT_EXPANDERS /* This is to initialize {init|mark|free}_machine_status before the first @@ -5133,7 +5379,6 @@ init_emit_once (line_numbers) for (i = - MAX_SAVED_CONST_INT; i <= MAX_SAVED_CONST_INT; i++) const_int_rtx[i + MAX_SAVED_CONST_INT] = gen_rtx_raw_CONST_INT (VOIDmode, (HOST_WIDE_INT) i); - ggc_add_rtx_root (const_int_rtx, 2 * MAX_SAVED_CONST_INT + 1); if (STORE_FLAG_VALUE >= - MAX_SAVED_CONST_INT && STORE_FLAG_VALUE <= MAX_SAVED_CONST_INT) @@ -5141,35 +5386,20 @@ init_emit_once (line_numbers) else const_true_rtx = gen_rtx_CONST_INT (VOIDmode, STORE_FLAG_VALUE); - dconst0 = REAL_VALUE_ATOF ("0", double_mode); - dconst1 = REAL_VALUE_ATOF ("1", double_mode); - dconst2 = REAL_VALUE_ATOF ("2", double_mode); - dconstm1 = REAL_VALUE_ATOF ("-1", double_mode); + REAL_VALUE_FROM_INT (dconst0, 0, 0, double_mode); + REAL_VALUE_FROM_INT (dconst1, 1, 0, double_mode); + REAL_VALUE_FROM_INT (dconst2, 2, 0, double_mode); + REAL_VALUE_FROM_INT (dconstm1, -1, -1, double_mode); for (i = 0; i <= 2; i++) { + REAL_VALUE_TYPE *r = + (i == 0 ? &dconst0 : i == 1 ? &dconst1 : &dconst2); + for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) - { - rtx tem = rtx_alloc (CONST_DOUBLE); - union real_extract u; - - /* Zero any holes in a structure. */ - memset ((char *) &u, 0, sizeof u); - u.d = i == 0 ? dconst0 : i == 1 ? dconst1 : dconst2; - - /* Avoid trailing garbage in the rtx. */ - if (sizeof (u) < sizeof (HOST_WIDE_INT)) - CONST_DOUBLE_LOW (tem) = 0; - if (sizeof (u) < 2 * sizeof (HOST_WIDE_INT)) - CONST_DOUBLE_HIGH (tem) = 0; - - memcpy (&CONST_DOUBLE_LOW (tem), &u, sizeof u); - CONST_DOUBLE_CHAIN (tem) = NULL_RTX; - PUT_MODE (tem, mode); - - const_tiny_rtx[i][(int) mode] = tem; - } + const_tiny_rtx[i][(int) mode] = + CONST_DOUBLE_FROM_REAL_VALUE (*r, mode); const_tiny_rtx[i][(int) VOIDmode] = GEN_INT (i); @@ -5201,12 +5431,6 @@ init_emit_once (line_numbers) if (STORE_FLAG_VALUE == 1) const_tiny_rtx[1][(int) BImode] = const1_rtx; - /* For bounded pointers, `&const_tiny_rtx[0][0]' is not the same as - `(rtx *) const_tiny_rtx'. The former has bounds that only cover - `const_tiny_rtx[0]', whereas the latter has bounds that cover all. */ - ggc_add_rtx_root ((rtx *) const_tiny_rtx, sizeof const_tiny_rtx / sizeof (rtx)); - ggc_add_rtx_root (&const_true_rtx, 1); - #ifdef RETURN_ADDRESS_POINTER_REGNUM return_address_pointer_rtx = gen_raw_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM); @@ -5253,13 +5477,6 @@ init_emit_once (line_numbers) if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM) pic_offset_table_rtx = gen_raw_REG (Pmode, PIC_OFFSET_TABLE_REGNUM); - - ggc_add_rtx_root (&pic_offset_table_rtx, 1); - ggc_add_rtx_root (&struct_value_rtx, 1); - ggc_add_rtx_root (&struct_value_incoming_rtx, 1); - ggc_add_rtx_root (&static_chain_rtx, 1); - ggc_add_rtx_root (&static_chain_incoming_rtx, 1); - ggc_add_rtx_root (&return_address_pointer_rtx, 1); } /* Query and clear/ restore no_line_numbers. This is used by the @@ -5283,3 +5500,72 @@ restore_line_number_status (old_value) { no_line_numbers = old_value; } + +/* Produce exact duplicate of insn INSN after AFTER. + Care updating of libcall regions if present. */ + +rtx +emit_copy_of_insn_after (insn, after) + rtx insn, after; +{ + rtx new; + rtx note1, note2, link; + + switch (GET_CODE (insn)) + { + case INSN: + new = emit_insn_after (copy_insn (PATTERN (insn)), after); + break; + + case JUMP_INSN: + new = emit_jump_insn_after (copy_insn (PATTERN (insn)), after); + break; + + case CALL_INSN: + new = emit_call_insn_after (copy_insn (PATTERN (insn)), after); + if (CALL_INSN_FUNCTION_USAGE (insn)) + CALL_INSN_FUNCTION_USAGE (new) + = copy_insn (CALL_INSN_FUNCTION_USAGE (insn)); + SIBLING_CALL_P (new) = SIBLING_CALL_P (insn); + CONST_OR_PURE_CALL_P (new) = CONST_OR_PURE_CALL_P (insn); + break; + + default: + abort (); + } + + /* Update LABEL_NUSES. */ + mark_jump_label (PATTERN (new), new, 0); + + INSN_SCOPE (new) = INSN_SCOPE (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)) + if (REG_NOTE_KIND (link) != REG_LABEL) + { + if (GET_CODE (link) == EXPR_LIST) + REG_NOTES (new) + = copy_insn_1 (gen_rtx_EXPR_LIST (REG_NOTE_KIND (link), + XEXP (link, 0), + REG_NOTES (new))); + else + REG_NOTES (new) + = copy_insn_1 (gen_rtx_INSN_LIST (REG_NOTE_KIND (link), + XEXP (link, 0), + REG_NOTES (new))); + } + + /* Fix the libcall sequences. */ + if ((note1 = find_reg_note (new, REG_RETVAL, NULL_RTX)) != NULL) + { + rtx p = new; + while ((note2 = find_reg_note (p, REG_LIBCALL, NULL_RTX)) == NULL) + p = PREV_INSN (p); + XEXP (note1, 0) = p; + XEXP (note2, 0) = new; + } + return new; +} + +#include "gt-emit-rtl.h" diff --git a/contrib/gcc/final.c b/contrib/gcc/final.c index d86ed5e..94a0f4c 100644 --- a/contrib/gcc/final.c +++ b/contrib/gcc/final.c @@ -68,6 +68,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "target.h" #include "debug.h" #include "expr.h" +#include "profile.h" +#include "cfglayout.h" #ifdef XCOFF_DEBUGGING_INFO #include "xcoffout.h" /* Needed for external data @@ -98,6 +100,12 @@ 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 + /* Last insn processed by final_scan_insn. */ static rtx debug_insn; rtx current_output_insn; @@ -114,15 +122,12 @@ static int high_function_linenum; /* Filename of last NOTE. */ static const char *last_filename; -/* Number of instrumented arcs when profile_arc_flag is set. */ -extern int count_instrumented_edges; - extern 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. The precise value is the insn being output, to pass to error_for_asm. */ -static rtx this_is_asm_operands; +rtx this_is_asm_operands; /* Number of operands of this insn, for an `asm' with operands. */ static unsigned int insn_noperands; @@ -198,6 +203,17 @@ static char *line_note_exists; rtx current_insn_predicate; #endif +struct function_list +{ + struct function_list *next; /* next function */ + const char *name; /* function name */ + long cfg_checksum; /* function checksum */ + long count_edges; /* number of intrumented edges in this function */ +}; + +static struct function_list *functions_head = 0; +static struct function_list **functions_tail = &functions_head; + #ifdef HAVE_ATTR_length static int asm_insn_count PARAMS ((rtx)); #endif @@ -206,6 +222,7 @@ static void profile_after_prologue PARAMS ((FILE *)); static void notice_source_line PARAMS ((rtx)); static rtx walk_alter_subreg PARAMS ((rtx *)); static void output_asm_name PARAMS ((void)); +static void output_alternate_entry_point PARAMS ((FILE *, rtx)); static tree get_mem_expr_from_op PARAMS ((rtx, int *)); static void output_asm_operand_names PARAMS ((rtx *, int *, int)); static void output_operand PARAMS ((rtx, int)); @@ -237,137 +254,268 @@ init_final (filename) } /* Called at end of source file, - to output the block-profiling table for this entire compilation. */ + to output the arc-profiling table for this entire compilation. */ void end_final (filename) const char *filename; { - if (profile_arc_flag) + if (profile_arc_flag && profile_info.count_instrumented_edges) { char name[20]; - int align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT); - int size, rounded; - int long_bytes = LONG_TYPE_SIZE / BITS_PER_UNIT; - int gcov_type_bytes = GCOV_TYPE_SIZE / BITS_PER_UNIT; - int pointer_bytes = POINTER_SIZE / BITS_PER_UNIT; - unsigned int align2 = LONG_TYPE_SIZE; - - size = gcov_type_bytes * count_instrumented_edges; - rounded = size; - - rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1; - rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); - - /* ??? This _really_ ought to be done with a structure layout - and with assemble_constructor. If long_bytes != pointer_bytes - we'll be emitting unaligned data at some point. */ - if (long_bytes != pointer_bytes) - abort (); + tree string_type, string_cst; + tree structure_decl, structure_value, structure_pointer_type; + tree field_decl, decl_chain, value_chain; + tree sizeof_field_value, domain_type; - data_section (); + /* Build types. */ + string_type = build_pointer_type (char_type_node); - /* Output the main header, of 11 words: - 0: 1 if this file is initialized, else 0. - 1: address of file name (LPBX1). - 2: address of table of counts (LPBX2). - 3: number of counts in the table. - 4: always 0, for compatibility with Sun. + /* Libgcc2 bb structure. */ + structure_decl = make_node (RECORD_TYPE); + structure_pointer_type = build_pointer_type (structure_decl); - The following are GNU extensions: - - 5: address of table of start addrs of basic blocks (LPBX3). - 6: Number of bytes in this header. - 7: address of table of function names (LPBX4). - 8: address of table of line numbers (LPBX5) or 0. - 9: address of table of file names (LPBX6) or 0. - 10: space reserved for basic block profiling. */ + /* Output the main header, of 7 words: + 0: 1 if this file is initialized, else 0. + 1: address of file name (LPBX1). + 2: address of table of counts (LPBX2). + 3: number of counts in the table. + 4: always 0, libgcc2 uses this as a pointer to next ``struct bb'' - ASM_OUTPUT_ALIGN (asm_out_file, align); + The following are GNU extensions: - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 0); + 5: Number of bytes in this header. + 6: address of table of function checksums (LPBX7). */ - /* Zero word. */ - assemble_integer (const0_rtx, long_bytes, align2, 1); + /* The zero word. */ + decl_chain = + build_decl (FIELD_DECL, get_identifier ("zero_word"), + long_integer_type_node); + value_chain = build_tree_list (decl_chain, + convert (long_integer_type_node, + integer_zero_node)); /* Address of filename. */ - ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 1); - assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes, - align2, 1); + { + char *cwd, *da_filename; + int da_filename_len; + + field_decl = + build_decl (FIELD_DECL, get_identifier ("filename"), string_type); + TREE_CHAIN (field_decl) = decl_chain; + decl_chain = field_decl; + + cwd = getpwd (); + da_filename_len = strlen (filename) + strlen (cwd) + 4 + 1; + da_filename = (char *) alloca (da_filename_len); + strcpy (da_filename, cwd); + strcat (da_filename, "/"); + strcat (da_filename, filename); + strcat (da_filename, ".da"); + da_filename_len = strlen (da_filename); + string_cst = build_string (da_filename_len + 1, da_filename); + domain_type = build_index_type (build_int_2 (da_filename_len, 0)); + TREE_TYPE (string_cst) + = build_array_type (char_type_node, domain_type); + value_chain = tree_cons (field_decl, + build1 (ADDR_EXPR, string_type, string_cst), + value_chain); + } - /* Address of count table. */ - ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2); - assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes, - align2, 1); + /* Table of counts. */ + { + tree gcov_type_type = make_unsigned_type (GCOV_TYPE_SIZE); + tree gcov_type_pointer_type = build_pointer_type (gcov_type_type); + tree domain_tree + = build_index_type (build_int_2 (profile_info. + count_instrumented_edges - 1, 0)); + tree gcov_type_array_type + = build_array_type (gcov_type_type, domain_tree); + tree gcov_type_array_pointer_type + = build_pointer_type (gcov_type_array_type); + tree counts_table; + + field_decl = + build_decl (FIELD_DECL, get_identifier ("counts"), + gcov_type_pointer_type); + TREE_CHAIN (field_decl) = decl_chain; + decl_chain = field_decl; + + /* No values. */ + counts_table + = build (VAR_DECL, gcov_type_array_type, NULL_TREE, NULL_TREE); + TREE_STATIC (counts_table) = 1; + ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2); + DECL_NAME (counts_table) = get_identifier (name); + assemble_variable (counts_table, 0, 0, 0); + + value_chain = tree_cons (field_decl, + build1 (ADDR_EXPR, + gcov_type_array_pointer_type, + counts_table), value_chain); + } /* Count of the # of instrumented arcs. */ - assemble_integer (GEN_INT (count_instrumented_edges), - long_bytes, align2, 1); + field_decl + = build_decl (FIELD_DECL, get_identifier ("ncounts"), + long_integer_type_node); + TREE_CHAIN (field_decl) = decl_chain; + decl_chain = field_decl; + + value_chain = tree_cons (field_decl, + convert (long_integer_type_node, + build_int_2 (profile_info. + count_instrumented_edges, + 0)), value_chain); + /* Pointer to the next bb. */ + field_decl + = build_decl (FIELD_DECL, get_identifier ("next"), + structure_pointer_type); + TREE_CHAIN (field_decl) = decl_chain; + decl_chain = field_decl; + + value_chain = tree_cons (field_decl, null_pointer_node, value_chain); + + /* sizeof(struct bb). We'll set this after entire structure + is laid out. */ + field_decl + = build_decl (FIELD_DECL, get_identifier ("sizeof_bb"), + long_integer_type_node); + TREE_CHAIN (field_decl) = decl_chain; + decl_chain = field_decl; + + sizeof_field_value = tree_cons (field_decl, NULL, value_chain); + value_chain = sizeof_field_value; + + /* struct bb_function []. */ + { + struct function_list *item; + int num_nodes; + tree checksum_field, arc_count_field, name_field; + tree domain; + tree array_value_chain = NULL_TREE; + tree bb_fn_struct_type; + tree bb_fn_struct_array_type; + tree bb_fn_struct_array_pointer_type; + tree bb_fn_struct_pointer_type; + tree field_value, field_value_chain; - /* Zero word (link field). */ - assemble_integer (const0_rtx, pointer_bytes, align2, 1); + bb_fn_struct_type = make_node (RECORD_TYPE); - assemble_integer (const0_rtx, pointer_bytes, align2, 1); + checksum_field = build_decl (FIELD_DECL, get_identifier ("checksum"), + long_integer_type_node); - /* Byte count for extended structure. */ - assemble_integer (GEN_INT (11 * UNITS_PER_WORD), long_bytes, align2, 1); + arc_count_field + = build_decl (FIELD_DECL, get_identifier ("arc_count"), + integer_type_node); + TREE_CHAIN (checksum_field) = arc_count_field; - /* Address of function name table. */ - assemble_integer (const0_rtx, pointer_bytes, align2, 1); + name_field + = build_decl (FIELD_DECL, get_identifier ("name"), string_type); + TREE_CHAIN (arc_count_field) = name_field; - /* Address of line number and filename tables if debugging. */ - assemble_integer (const0_rtx, pointer_bytes, align2, 1); - assemble_integer (const0_rtx, pointer_bytes, align2, 1); + TYPE_FIELDS (bb_fn_struct_type) = checksum_field; - /* Space for extension ptr (link field). */ - assemble_integer (const0_rtx, UNITS_PER_WORD, align2, 1); + num_nodes = 0; - /* Output the file name changing the suffix to .d for - Sun tcov compatibility. */ - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 1); - { - char *cwd = getpwd (); - int len = strlen (filename) + strlen (cwd) + 1; - char *data_file = (char *) alloca (len + 4); - - strcpy (data_file, cwd); - strcat (data_file, "/"); - strcat (data_file, filename); - strip_off_ending (data_file, len); - strcat (data_file, ".da"); - assemble_string (data_file, strlen (data_file) + 1); + for (item = functions_head; item != 0; item = item->next) + num_nodes++; + + /* Note that the array contains a terminator, hence no - 1. */ + domain = build_index_type (build_int_2 (num_nodes, 0)); + + bb_fn_struct_pointer_type = build_pointer_type (bb_fn_struct_type); + bb_fn_struct_array_type + = build_array_type (bb_fn_struct_type, domain); + bb_fn_struct_array_pointer_type + = build_pointer_type (bb_fn_struct_array_type); + + layout_type (bb_fn_struct_type); + layout_type (bb_fn_struct_pointer_type); + layout_type (bb_fn_struct_array_type); + layout_type (bb_fn_struct_array_pointer_type); + + for (item = functions_head; item != 0; item = item->next) + { + size_t name_len; + + /* create constructor for structure. */ + field_value_chain + = build_tree_list (checksum_field, + convert (long_integer_type_node, + build_int_2 (item->cfg_checksum, 0))); + field_value_chain + = tree_cons (arc_count_field, + convert (integer_type_node, + build_int_2 (item->count_edges, 0)), + field_value_chain); + + name_len = strlen (item->name); + string_cst = build_string (name_len + 1, item->name); + domain_type = build_index_type (build_int_2 (name_len, 0)); + TREE_TYPE (string_cst) + = build_array_type (char_type_node, domain_type); + field_value_chain = tree_cons (name_field, + build1 (ADDR_EXPR, string_type, + string_cst), + field_value_chain); + + /* Add to chain. */ + array_value_chain + = tree_cons (NULL_TREE, build (CONSTRUCTOR, + bb_fn_struct_type, NULL_TREE, + nreverse (field_value_chain)), + array_value_chain); + } + + /* Add terminator. */ + field_value = build_tree_list (arc_count_field, + convert (integer_type_node, + build_int_2 (-1, 0))); + + array_value_chain = tree_cons (NULL_TREE, + build (CONSTRUCTOR, bb_fn_struct_type, + NULL_TREE, field_value), + array_value_chain); + + + /* Create constructor for array. */ + field_decl + = build_decl (FIELD_DECL, get_identifier ("function_infos"), + bb_fn_struct_pointer_type); + value_chain = tree_cons (field_decl, + build1 (ADDR_EXPR, + bb_fn_struct_array_pointer_type, + build (CONSTRUCTOR, + bb_fn_struct_array_type, + NULL_TREE, + nreverse + (array_value_chain))), + value_chain); + TREE_CHAIN (field_decl) = decl_chain; + decl_chain = field_decl; } - /* Make space for the table of counts. */ - if (size == 0) - { - /* Realign data section. */ - ASM_OUTPUT_ALIGN (asm_out_file, align); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 2); - if (size != 0) - assemble_zeros (size); - } - else - { - ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2); -#ifdef ASM_OUTPUT_SHARED_LOCAL - if (flag_shared_data) - ASM_OUTPUT_SHARED_LOCAL (asm_out_file, name, size, rounded); - else -#endif -#ifdef ASM_OUTPUT_ALIGNED_DECL_LOCAL - ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, NULL_TREE, name, - size, BIGGEST_ALIGNMENT); -#else -#ifdef ASM_OUTPUT_ALIGNED_LOCAL - ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, - BIGGEST_ALIGNMENT); -#else - ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded); -#endif -#endif - } + /* Finish structure. */ + TYPE_FIELDS (structure_decl) = nreverse (decl_chain); + layout_type (structure_decl); + + structure_value + = build (VAR_DECL, structure_decl, NULL_TREE, NULL_TREE); + DECL_INITIAL (structure_value) + = build (CONSTRUCTOR, structure_decl, NULL_TREE, + nreverse (value_chain)); + TREE_STATIC (structure_value) = 1; + ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0); + DECL_NAME (structure_value) = get_identifier (name); + + /* Size of this structure. */ + TREE_VALUE (sizeof_field_value) + = convert (long_integer_type_node, + build_int_2 (int_size_in_bytes (structure_decl), 0)); + + /* Build structure. */ + assemble_variable (structure_value, 0, 0, 0); } } @@ -438,9 +586,7 @@ dbr_sequence_length () static int *insn_lengths; -#ifdef HAVE_ATTR_length varray_type insn_addresses_; -#endif /* Max uid for which the above arrays are valid. */ static int insn_lengths_max_uid; @@ -527,7 +673,7 @@ get_attr_length (insn) case JUMP_INSN: body = PATTERN (insn); - if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) + if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) { /* Alignment is machine-dependent and should be handled by ADDR_VEC_ALIGN. */ @@ -787,8 +933,8 @@ insn_current_reference_address (branch) void compute_alignments () { - int i; int log, max_skip, max_log; + basic_block bb; if (label_align) { @@ -805,9 +951,8 @@ compute_alignments () if (! optimize || optimize_size) return; - for (i = 0; i < n_basic_blocks; i++) + FOR_EACH_BB (bb) { - basic_block bb = BASIC_BLOCK (i); rtx label = bb->head; int fallthru_frequency = 0, branch_frequency = 0, has_fallthru = 0; edge e; @@ -837,8 +982,8 @@ compute_alignments () if (!has_fallthru && (branch_frequency > BB_FREQ_MAX / 10 - || (bb->frequency > BASIC_BLOCK (i - 1)->frequency * 10 - && (BASIC_BLOCK (i - 1)->frequency + || (bb->frequency > bb->prev_bb->frequency * 10 + && (bb->prev_bb->frequency <= ENTRY_BLOCK_PTR->frequency / 2)))) { log = JUMP_ALIGN (label); @@ -849,10 +994,10 @@ compute_alignments () } } /* In case block is frequent and reached mostly by non-fallthru edge, - align it. It is most likely an first block of loop. */ + align it. It is most likely a first block of loop. */ if (has_fallthru && branch_frequency + fallthru_frequency > BB_FREQ_MAX / 10 - && branch_frequency > fallthru_frequency * 5) + && branch_frequency > fallthru_frequency * 2) { log = LOOP_ALIGN (label); if (max_log < log) @@ -974,11 +1119,7 @@ shorten_branches (first) next = NEXT_INSN (insn); /* ADDR_VECs only take room if read-only data goes into the text section. */ - if (JUMP_TABLES_IN_TEXT_SECTION -#if !defined(READONLY_DATA_SECTION) - || 1 -#endif - ) + if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION) if (next && GET_CODE (next) == JUMP_INSN) { rtx nextbody = PATTERN (next); @@ -1128,7 +1269,7 @@ shorten_branches (first) } } - INSN_ADDRESSES (uid) = insn_current_address; + INSN_ADDRESSES (uid) = insn_current_address + insn_lengths[uid]; if (GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER || GET_CODE (insn) == CODE_LABEL) @@ -1141,11 +1282,7 @@ shorten_branches (first) { /* This only takes room if read-only data goes into the text section. */ - if (JUMP_TABLES_IN_TEXT_SECTION -#if !defined(READONLY_DATA_SECTION) - || 1 -#endif - ) + if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION) insn_lengths[uid] = (XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC) * GET_MODE_SIZE (GET_MODE (body))); @@ -1346,11 +1483,7 @@ shorten_branches (first) PUT_MODE (body, CASE_VECTOR_SHORTEN_MODE (min_addr - rel_addr, max_addr - rel_addr, body)); - if (JUMP_TABLES_IN_TEXT_SECTION -#if !defined(READONLY_DATA_SECTION) - || 1 -#endif - ) + if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION) { insn_lengths[uid] = (XVECLEN (body, 1) * GET_MODE_SIZE (GET_MODE (body))); @@ -1380,7 +1513,7 @@ shorten_branches (first) insn_current_address += insn_lengths[inner_uid]; } - } + } else insn_current_address += insn_lengths[uid]; @@ -1537,7 +1670,7 @@ final_start_function (first, file, optimize) if (write_symbols) { remove_unnecessary_notes (); - reorder_blocks (); + scope_to_insns_finalize (); number_blocks (current_function_decl); /* We never actually put out begin/end notes for the top-level block in the function. But, conceptually, that block is @@ -1548,12 +1681,6 @@ final_start_function (first, file, optimize) /* First output the function prologue: code to set up the stack frame. */ (*targetm.asm_out.function_prologue) (file, get_frame_size ()); -#ifdef VMS_DEBUGGING_INFO - /* Output label after the prologue of the function. */ - if (write_symbols == VMS_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG) - vmsdbgout_after_prologue (); -#endif - /* If the machine represents the prologue as RTL, the profiling code must be emitted when NOTE_INSN_PROLOGUE_END is scanned. */ #ifdef HAVE_prologue @@ -1591,7 +1718,7 @@ profile_function (file) #ifndef NO_PROFILE_COUNTERS data_section (); ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT)); - ASM_OUTPUT_INTERNAL_LABEL (file, "LP", current_function_profile_label_no); + ASM_OUTPUT_INTERNAL_LABEL (file, "LP", current_function_funcdef_no); assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1); #endif @@ -1621,7 +1748,7 @@ profile_function (file) #endif #endif - FUNCTION_PROFILER (file, current_function_profile_label_no); + FUNCTION_PROFILER (file, current_function_funcdef_no); #if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH) if (cxt) @@ -1664,12 +1791,12 @@ final_end_function () (*targetm.asm_out.function_epilogue) (asm_out_file, get_frame_size ()); /* And debug output. */ - (*debug_hooks->end_epilogue) (); + (*debug_hooks->end_epilogue) (last_linenum, last_filename); #if defined (DWARF2_UNWIND_INFO) if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG && dwarf2out_do_frame ()) - dwarf2out_end_epilogue (); + dwarf2out_end_epilogue (last_linenum, last_filename); #endif } @@ -1763,16 +1890,12 @@ final (first, file, optimize, prescan) #ifdef HAVE_ATTR_length if ((unsigned) INSN_UID (insn) >= INSN_ADDRESSES_SIZE ()) { -#ifdef STACK_REGS - /* Irritatingly, the reg-stack pass is creating new instructions - and because of REG_DEAD note abuse it has to run after - shorten_branches. Fake address of -1 then. */ - insn_current_address = -1; -#else /* This can be triggered by bugs elsewhere in the compiler if new insns are created after init_insn_lengths is called. */ - abort (); -#endif + if (GET_CODE (insn) == NOTE) + insn_current_address = -1; + else + abort (); } else insn_current_address = INSN_ADDRESSES (INSN_UID (insn)); @@ -1781,6 +1904,23 @@ final (first, file, optimize, prescan) insn = final_scan_insn (insn, file, optimize, prescan, 0); } + /* Store function names for edge-profiling. */ + /* ??? Probably should re-use the existing struct function. */ + + if (cfun->arc_profile) + { + struct function_list *new_item = xmalloc (sizeof (struct function_list)); + + *functions_tail = new_item; + functions_tail = &new_item->next; + + new_item->next = 0; + new_item->name = xstrdup (IDENTIFIER_POINTER + (DECL_ASSEMBLER_NAME (current_function_decl))); + new_item->cfg_checksum = profile_info.current_function_cfg_checksum; + new_item->count_edges = profile_info.count_edges_instrumented_now; + } + free (line_note_exists); line_note_exists = NULL; } @@ -1807,6 +1947,39 @@ get_insn_template (code, insn) } } +/* Emit the appropriate declaration for an alternate-entry-point + symbol represented by INSN, to FILE. INSN is a CODE_LABEL with + LABEL_KIND != LABEL_NORMAL. + + The case fall-through in this function is intentional. */ +static void +output_alternate_entry_point (file, insn) + FILE *file; + rtx insn; +{ + const char *name = LABEL_NAME (insn); + + switch (LABEL_KIND (insn)) + { + case LABEL_WEAK_ENTRY: +#ifdef ASM_WEAKEN_LABEL + ASM_WEAKEN_LABEL (file, name); +#endif + case LABEL_GLOBAL_ENTRY: + (*targetm.asm_out.globalize_label) (file, name); + case LABEL_STATIC_ENTRY: +#ifdef ASM_OUTPUT_TYPE_DIRECTIVE + ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function"); +#endif + ASM_OUTPUT_LABEL (file, name); + break; + + case LABEL_NORMAL: + default: + abort (); + } +} + /* The final scan for one insn, INSN. Args are same as in `final', except that INSN is the insn being scanned. @@ -1850,9 +2023,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) case NOTE_INSN_LOOP_VTOP: case NOTE_INSN_FUNCTION_END: case NOTE_INSN_REPEATED_LINE_NUMBER: - case NOTE_INSN_RANGE_BEG: - case NOTE_INSN_RANGE_END: - case NOTE_INSN_LIVE: case NOTE_INSN_EXPECTED_VALUE: break; @@ -1886,7 +2056,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) case NOTE_INSN_FUNCTION_BEG: app_disable (); - (*debug_hooks->end_prologue) (last_linenum); + (*debug_hooks->end_prologue) (last_linenum, last_filename); break; case NOTE_INSN_BLOCK_BEG: @@ -2016,8 +2186,12 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN ASM_OUTPUT_MAX_SKIP_ALIGN (file, align, max_skip); #else +#ifdef ASM_OUTPUT_ALIGN_WITH_NOP + ASM_OUTPUT_ALIGN_WITH_NOP (file, align); +#else ASM_OUTPUT_ALIGN (file, align); #endif +#endif } } #ifdef HAVE_cc0 @@ -2100,17 +2274,14 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), NEXT_INSN (insn)); #else - if (LABEL_ALTERNATE_NAME (insn)) - ASM_OUTPUT_ALTERNATE_LABEL_NAME (file, insn); - else - ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn)); + ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn)); #endif #endif break; } } - if (LABEL_ALTERNATE_NAME (insn)) - ASM_OUTPUT_ALTERNATE_LABEL_NAME (file, insn); + if (LABEL_ALT_ENTRY_P (insn)) + output_alternate_entry_point (file, insn); else ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn)); break; @@ -2539,13 +2710,13 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) insn_code_number = recog_memoized (insn); cleanup_subreg_operands (insn); - /* Dump the insn in the assembly for debugging. */ - if (flag_dump_rtl_in_asm) - { - print_rtx_head = ASM_COMMENT_START; - print_rtl_single (asm_out_file, insn); - print_rtx_head = ""; - } + /* Dump the insn in the assembly for debugging. */ + if (flag_dump_rtl_in_asm) + { + print_rtx_head = ASM_COMMENT_START; + print_rtl_single (asm_out_file, insn); + print_rtx_head = ""; + } if (! constrain_operands_cached (1)) fatal_insn_not_found (insn); @@ -2755,7 +2926,7 @@ alter_subreg (xp) ORIGINAL_REGNO (x) = ORIGINAL_REGNO (y); /* This field has a different meaning for REGs and SUBREGs. Make sure to clear it! */ - x->used = 0; + RTX_FLAG (x, used) = 0; } else abort (); @@ -2970,7 +3141,7 @@ output_operand_lossage VPARAMS ((const char *msgid, ...)) pfx_str = this_is_asm_operands ? _("invalid `asm': ") : "output_operand: "; asprintf (&fmt_string, "%s%s", pfx_str, _(msgid)); vasprintf (&new_message, fmt_string, ap); - + if (this_is_asm_operands) error_for_asm (this_is_asm_operands, "%s", new_message); else @@ -3768,7 +3939,6 @@ split_double (value, first, second) } else { -#ifdef REAL_ARITHMETIC REAL_VALUE_TYPE r; long l[2]; REAL_VALUE_FROM_CONST_DOUBLE (r, value); @@ -3797,30 +3967,6 @@ split_double (value, first, second) *first = GEN_INT ((HOST_WIDE_INT) l[0]); *second = GEN_INT ((HOST_WIDE_INT) l[1]); -#else - if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT - || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD) - && ! flag_pretend_float) - abort (); - - if ( -#ifdef HOST_WORDS_BIG_ENDIAN - WORDS_BIG_ENDIAN -#else - ! WORDS_BIG_ENDIAN -#endif - ) - { - /* Host and target agree => no need to swap. */ - *first = GEN_INT (CONST_DOUBLE_LOW (value)); - *second = GEN_INT (CONST_DOUBLE_HIGH (value)); - } - else - { - *second = GEN_INT (CONST_DOUBLE_LOW (value)); - *first = GEN_INT (CONST_DOUBLE_HIGH (value)); - } -#endif /* no REAL_ARITHMETIC */ } } @@ -3865,7 +4011,7 @@ leaf_function_p () return 1; } -/* Return 1 if branch is an forward branch. +/* Return 1 if branch is a forward branch. Uses insn_shuid array, so it works only in the final pass. May be used by output templates to customary add branch prediction hints. */ diff --git a/contrib/gcc/flags.h b/contrib/gcc/flags.h index 85e0792..0a8979d 100644 --- a/contrib/gcc/flags.h +++ b/contrib/gcc/flags.h @@ -1,5 +1,5 @@ /* Compilation switch flag definitions for GCC. - Copyright (C) 1987, 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000 + Copyright (C) 1987, 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc. This file is part of GCC. @@ -126,10 +126,20 @@ extern int warn_unknown_pragmas; extern int warn_shadow; -/* Warn if a switch on an enum fails to have a case for every enum value. */ +/* Warn if a switch on an enum, that does not have a default case, + fails to have a case for every enum value. */ extern int warn_switch; +/* Warn if a switch does not have a default case. */ + +extern int 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 int 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. */ @@ -174,6 +184,11 @@ extern int warn_disabled_optimization; extern int warn_deprecated_decl; +/* Nonzero means warn about constructs which might not be strict + aliasing safe. */ + +extern int warn_strict_aliasing; + /* Nonzero if generating code to do profiling. */ extern int profile_flag; @@ -194,6 +209,10 @@ extern int flag_branch_probabilities; 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; @@ -345,6 +364,10 @@ extern int flag_errno_math; 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. */ @@ -408,7 +431,7 @@ extern int flag_schedule_insns_after_reload; /* The following flags have effect only for scheduling before register allocation: - flag_schedule_interblock means schedule insns accross basic blocks. + 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. @@ -439,19 +462,13 @@ extern int flag_delayed_branch; extern int flag_dump_unnumbered; -/* Nonzero means pretend it is OK to examine bits of target floats, - even if that isn't true. The resulting code will have incorrect constants, - but the same series of instructions that the native compiler would make. */ - -extern int flag_pretend_float; - /* Nonzero means change certain warnings into errors. Usually these are warnings about failure to conform to some standard. */ extern int flag_pedantic_errors; -/* Nonzero means generate position-independent code. - This is not fully implemented yet. */ +/* Nonzero means generate position-independent code. 1 vs 2 for a + target-dependent "small" or "large" mode. */ extern int flag_pic; @@ -546,19 +563,10 @@ extern int flag_peephole2; /* Try to guess branch probablities. */ extern int flag_guess_branch_prob; -/* -fbounded-pointers causes gcc to compile pointers as composite - objects occupying three words: the pointer value, the base address - of the referent object, and the address immediately beyond the end - of the referent object. The base and extent allow us to perform - runtime bounds checking. -fbounded-pointers implies -fcheck-bounds. */ -extern int flag_bounded_pointers; - /* -fcheck-bounds causes gcc to generate array bounds checks. - For C, C++: defaults to value of flag_bounded_pointers. - For ObjC: defaults to off. + For C, C++ and ObjC: defaults off. For Java: defaults to on. - For Fortran: defaults to off. - For CHILL: defaults to off. */ + For Fortran: defaults to off. */ extern int flag_bounds_check; /* This will attempt to merge constant section constants, if 1 only @@ -638,11 +646,48 @@ extern int flag_gcse_sm; extern int flag_eliminate_dwarf2_dups; -/* Non-zero means to collect statistics which might be expensive +/* 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; + +/* A string that's used when a random name is required. NULL means + to make it really random. */ + +extern const char *flag_random_seed; + +/* 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 + 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) \ + (MODE_HAS_NANS (MODE) && !flag_finite_math_only) + +/* Like HONOR_NANs, but true if we honor signaling NaNs (or sNaNs). */ +#define HONOR_SNANS(MODE) (flag_signaling_nans && HONOR_NANS (MODE)) + +/* As for HONOR_NANS, but true if the mode can represent infinity and + the treatment of infinite values is important. */ +#define HONOR_INFINITIES(MODE) \ + (MODE_HAS_INFINITIES (MODE) && !flag_finite_math_only) + +/* Like HONOR_NANS, but true if the given mode distinguishes between + postive and negative zero, and the sign of zero is important. */ +#define HONOR_SIGNED_ZEROS(MODE) \ + (MODE_HAS_SIGNED_ZEROS (MODE) && !flag_unsafe_math_optimizations) + +/* Like HONOR_NANS, but true if given mode supports sign-dependent rounding, + and the rounding mode is important. */ +#define HONOR_SIGN_DEPENDENT_ROUNDING(MODE) \ + (MODE_HAS_SIGN_DEPENDENT_ROUNDING (MODE) && !flag_unsafe_math_optimizations) + #endif /* ! GCC_FLAGS_H */ diff --git a/contrib/gcc/function.c b/contrib/gcc/function.c index f733076..daa2cab 100644 --- a/contrib/gcc/function.c +++ b/contrib/gcc/function.c @@ -53,9 +53,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "recog.h" #include "output.h" #include "basic-block.h" -#include "obstack.h" #include "toplev.h" -#include "hash.h" +#include "hashtab.h" #include "ggc.h" #include "tm_p.h" #include "integrate.h" @@ -75,7 +74,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA must define both, or neither. */ #ifndef NAME__MAIN #define NAME__MAIN "__main" -#define SYMBOL__MAIN __main #endif /* Round a value to the lowest integer less than it that is a multiple of @@ -124,24 +122,12 @@ int current_function_uses_only_leaf_regs; post-instantiation libcalls. */ int virtuals_instantiated; -/* Assign unique numbers to labels generated for profiling. */ -static int profile_label_no; +/* Assign unique numbers to labels generated for profiling, debugging, etc. */ +static int funcdef_no; /* These variables hold pointers to functions to create and destroy target specific, per-function data structures. */ -void (*init_machine_status) PARAMS ((struct function *)); -void (*free_machine_status) PARAMS ((struct function *)); -/* This variable holds a pointer to a function to register any - data items in the target specific, per-function data structure - that will need garbage collection. */ -void (*mark_machine_status) PARAMS ((struct function *)); - -/* Likewise, but for language-specific data. */ -void (*init_lang_status) PARAMS ((struct function *)); -void (*save_lang_status) PARAMS ((struct function *)); -void (*restore_lang_status) PARAMS ((struct function *)); -void (*mark_lang_status) PARAMS ((struct function *)); -void (*free_lang_status) PARAMS ((struct function *)); +struct machine_function * (*init_machine_status) PARAMS ((void)); /* The FUNCTION_DECL for an inline function currently being expanded. */ tree inline_function_decl; @@ -150,12 +136,12 @@ tree inline_function_decl; struct function *cfun = 0; /* These arrays record the INSN_UIDs of the prologue and epilogue insns. */ -static varray_type prologue; -static varray_type epilogue; +static GTY(()) varray_type prologue; +static GTY(()) varray_type epilogue; /* Array of INSN_UIDs to hold the INSN_UIDs for each sibcall epilogue in this function. */ -static varray_type sibcall_epilogue; +static GTY(()) varray_type sibcall_epilogue; /* In order to evaluate some expressions, such as function calls returning structures in memory, we need to temporarily allocate stack locations. @@ -175,7 +161,7 @@ static varray_type sibcall_epilogue; level where they are defined. They are marked a "kept" so that free_temp_slots will not free them. */ -struct temp_slot +struct temp_slot GTY(()) { /* Points to next temporary slot. */ struct temp_slot *next; @@ -195,13 +181,13 @@ struct temp_slot tree type; /* The value of `sequence_rtl_expr' when this temporary is allocated. */ tree rtl_expr; - /* Non-zero if this temporary is currently in use. */ + /* Nonzero if this temporary is currently in use. */ char in_use; - /* Non-zero if this temporary has its address taken. */ + /* Nonzero if this temporary has its address taken. */ char addr_taken; /* Nesting level at which this slot is being used. */ int level; - /* Non-zero if this should survive a call to free_temp_slots. */ + /* Nonzero if this should survive a call to free_temp_slots. */ int keep; /* The offset of the slot from the frame_pointer, including extra space for alignment. This info is for combine_temp_slots. */ @@ -216,7 +202,7 @@ struct temp_slot maintain this list in case two operands of an insn were required to match; in that case we must ensure we use the same replacement. */ -struct fixup_replacement +struct fixup_replacement GTY(()) { rtx old; rtx new; @@ -225,9 +211,9 @@ struct fixup_replacement struct insns_for_mem_entry { - /* The KEY in HE will be a MEM. */ - struct hash_entry he; - /* These are the INSNS which reference the MEM. */ + /* A MEM. */ + rtx key; + /* These are the INSNs which reference the MEM. */ rtx insns; }; @@ -239,25 +225,25 @@ static struct temp_slot *find_temp_slot_from_address PARAMS ((rtx)); static void put_reg_into_stack PARAMS ((struct function *, rtx, tree, enum machine_mode, enum machine_mode, int, unsigned int, int, - struct hash_table *)); + htab_t)); static void schedule_fixup_var_refs PARAMS ((struct function *, rtx, tree, enum machine_mode, - struct hash_table *)); + htab_t)); static void fixup_var_refs PARAMS ((rtx, enum machine_mode, int, rtx, - struct hash_table *)); + htab_t)); static struct fixup_replacement *find_fixup_replacement PARAMS ((struct fixup_replacement **, rtx)); static void fixup_var_refs_insns PARAMS ((rtx, rtx, enum machine_mode, int, int, rtx)); static void fixup_var_refs_insns_with_hash - PARAMS ((struct hash_table *, rtx, + PARAMS ((htab_t, rtx, enum machine_mode, int, rtx)); static void fixup_var_refs_insn PARAMS ((rtx, rtx, enum machine_mode, int, int, rtx)); static void fixup_var_refs_1 PARAMS ((rtx, enum machine_mode, rtx *, rtx, struct fixup_replacement **, rtx)); static rtx fixup_memory_subreg PARAMS ((rtx, rtx, enum machine_mode, int)); -static rtx walk_fixup_memory_subreg PARAMS ((rtx, rtx, enum machine_mode, +static rtx walk_fixup_memory_subreg PARAMS ((rtx, rtx, enum machine_mode, int)); static rtx fixup_stack_1 PARAMS ((rtx, rtx)); static void optimize_bit_field PARAMS ((rtx, rtx, rtx *)); @@ -269,10 +255,8 @@ static int instantiate_virtual_regs_1 PARAMS ((rtx *, rtx, int)); static void delete_handlers PARAMS ((void)); static void pad_to_arg_alignment PARAMS ((struct args_size *, int, struct args_size *)); -#ifndef ARGS_GROW_DOWNWARD static void pad_below PARAMS ((struct args_size *, enum machine_mode, tree)); -#endif static rtx round_trampoline_addr PARAMS ((rtx)); static rtx adjust_trampoline_addr PARAMS ((rtx)); static tree *identify_blocks_1 PARAMS ((rtx, tree *, tree *, tree *)); @@ -290,29 +274,25 @@ static int contains PARAMS ((rtx, varray_type)); #ifdef HAVE_return static void emit_return_into_block PARAMS ((basic_block, rtx)); #endif -static void put_addressof_into_stack PARAMS ((rtx, struct hash_table *)); +static void put_addressof_into_stack PARAMS ((rtx, htab_t)); static bool purge_addressof_1 PARAMS ((rtx *, rtx, int, int, - struct hash_table *)); + htab_t)); static void purge_single_hard_subreg_set PARAMS ((rtx)); #if defined(HAVE_epilogue) && defined(INCOMING_RETURN_ADDR_RTX) static rtx keep_stack_depressed PARAMS ((rtx)); #endif static int is_addressof PARAMS ((rtx *, void *)); -static struct hash_entry *insns_for_mem_newfunc PARAMS ((struct hash_entry *, - struct hash_table *, - hash_table_key)); -static unsigned long insns_for_mem_hash PARAMS ((hash_table_key)); -static bool insns_for_mem_comp PARAMS ((hash_table_key, hash_table_key)); +static hashval_t insns_for_mem_hash PARAMS ((const void *)); +static int insns_for_mem_comp PARAMS ((const void *, const void *)); static int insns_for_mem_walk PARAMS ((rtx *, void *)); -static void compute_insns_for_mem PARAMS ((rtx, rtx, struct hash_table *)); -static void mark_function_status PARAMS ((struct function *)); -static void maybe_mark_struct_function PARAMS ((void *)); +static void compute_insns_for_mem PARAMS ((rtx, rtx, htab_t)); static void prepare_function_start PARAMS ((void)); static void do_clobber_return_reg PARAMS ((rtx, void *)); static void do_use_return_reg PARAMS ((rtx, void *)); +static void instantiate_virtual_regs_lossage PARAMS ((rtx)); /* Pointer to chain of `struct function' for containing functions. */ -static struct function *outer_function_chain; +static GTY(()) struct function *outer_function_chain; /* Given a function decl for a containing function, return the `struct function' for it. */ @@ -332,7 +312,7 @@ find_function_data (decl) /* Save the current context for compilation of a nested function. This is called from language-specific code. The caller should use - the save_lang_status callback to save any language-specific state, + the enter_nested langhook to save any language-specific state, since this function knows only about language-independent variables. */ @@ -361,8 +341,7 @@ push_function_context_to (context) outer_function_chain = p; p->fixup_var_refs_queue = 0; - if (save_lang_status) - (*save_lang_status) (p); + (*lang_hooks.function.enter_nested) (p); cfun = 0; } @@ -391,8 +370,7 @@ pop_function_context_from (context) restore_emit_status (p); - if (restore_lang_status) - (*restore_lang_status) (p); + (*lang_hooks.function.leave_nested) (p); /* Finish doing put_var_into_stack for any of our variables which became addressable during the nested function. If only one entry has to be @@ -445,9 +423,8 @@ free_after_parsing (f) /* f->varasm is used by code generation. */ /* f->eh->eh_return_stub_label is used by code generation. */ - if (free_lang_status) - (*free_lang_status) (f); - free_stmt_status (f); + (*lang_hooks.function.final) (f); + f->stmt = NULL; } /* Clear out all parts of the state in F that can safely be discarded @@ -458,16 +435,11 @@ void free_after_compilation (f) struct function *f; { - free_eh_status (f); - free_expr_status (f); - free_emit_status (f); - free_varasm_status (f); - - if (free_machine_status) - (*free_machine_status) (f); - - if (f->x_parm_reg_stack_loc) - free (f->x_parm_reg_stack_loc); + f->eh = NULL; + f->expr = NULL; + f->emit = NULL; + f->varasm = NULL; + f->machine = NULL; f->x_temp_slots = NULL; f->arg_offset_rtx = NULL; @@ -479,6 +451,8 @@ free_after_compilation (f) f->x_nonlocal_goto_stack_level = NULL; f->x_cleanup_label = NULL; f->x_return_label = NULL; + f->computed_goto_common_label = NULL; + f->computed_goto_common_reg = NULL; f->x_save_expr_regs = NULL; f->x_stack_slot_list = NULL; f->x_rtl_expr_chain = NULL; @@ -560,7 +534,7 @@ assign_stack_local_1 (mode, size, align, function) /* Allow the target to (possibly) increase the alignment of this stack slot. */ - type = type_for_mode (mode, 0); + type = (*lang_hooks.types.type_for_mode) (mode, 0); if (type) alignment = LOCAL_ALIGNMENT (type, alignment); @@ -680,7 +654,7 @@ assign_stack_temp_for_type (mode, size, keep, type) align = GET_MODE_ALIGNMENT (mode); if (! type) - type = type_for_mode (mode, 0); + type = (*lang_hooks.types.type_for_mode) (mode, 0); if (type) align = LOCAL_ALIGNMENT (type, align); @@ -902,7 +876,7 @@ assign_temp (type_or_decl, keep, memory_required, dont_promote) /* The size of the temporary may be too large to fit into an integer. */ /* ??? Not sure this should happen except for user silliness, so limit - this to things that aren't compiler-generated temporaries. The + this to things that aren't compiler-generated temporaries. The rest of the time we'll abort in assign_stack_temp_for_type. */ if (decl && size == -1 && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST) @@ -1350,12 +1324,16 @@ init_temp_slots () target_temp_slot_level = 0; } -/* Retroactively move an auto variable from a register to a stack slot. - This is done when an address-reference to the variable is seen. */ +/* Retroactively move an auto variable from a register to a stack + slot. This is done when an address-reference to the variable is + seen. If RESCAN is true, all previously emitted instructions are + examined and modified to handle the fact that DECL is now + addressable. */ void -put_var_into_stack (decl) +put_var_into_stack (decl, rescan) tree decl; + int rescan; { rtx reg; enum machine_mode promoted_mode, decl_mode; @@ -1369,8 +1347,8 @@ put_var_into_stack (decl) context = decl_function_context (decl); /* Get the current rtl used for this object and its original mode. */ - reg = (TREE_CODE (decl) == SAVE_EXPR - ? SAVE_EXPR_RTL (decl) + reg = (TREE_CODE (decl) == SAVE_EXPR + ? SAVE_EXPR_RTL (decl) : DECL_RTL_IF_SET (decl)); /* No need to do anything if decl has no rtx yet @@ -1430,7 +1408,7 @@ put_var_into_stack (decl) to put things in the stack for the sake of setjmp, try to keep it in a register until we know we actually need the address. */ if (can_use_addressof) - gen_mem_addressof (reg, decl); + gen_mem_addressof (reg, decl, rescan); else put_reg_into_stack (function, reg, TREE_TYPE (decl), promoted_mode, decl_mode, volatilep, 0, usedp, 0); @@ -1443,7 +1421,7 @@ put_var_into_stack (decl) to the whole CONCAT, lest we do double fixups for the latter references. */ enum machine_mode part_mode = GET_MODE (XEXP (reg, 0)); - tree part_type = type_for_mode (part_mode, 0); + tree part_type = (*lang_hooks.types.type_for_mode) (part_mode, 0); rtx lopart = XEXP (reg, 0); rtx hipart = XEXP (reg, 1); #ifdef FRAME_GROWS_DOWNWARD @@ -1477,7 +1455,7 @@ put_var_into_stack (decl) /* Prevent sharing of rtl that might lose. */ if (GET_CODE (XEXP (reg, 0)) == PLUS) XEXP (reg, 0) = copy_rtx (XEXP (reg, 0)); - if (usedp) + if (usedp && rescan) { schedule_fixup_var_refs (function, reg, TREE_TYPE (decl), promoted_mode, 0); @@ -1506,7 +1484,7 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p, int volatile_p; unsigned int original_regno; int used_p; - struct hash_table *ht; + htab_t ht; { struct function *func = function ? function : cfun; rtx new = 0; @@ -1554,7 +1532,7 @@ schedule_fixup_var_refs (function, reg, type, promoted_mode, ht) rtx reg; tree type; enum machine_mode promoted_mode; - struct hash_table *ht; + htab_t ht; { int unsigned_p = type ? TREE_UNSIGNED (type) : 0; @@ -1580,7 +1558,7 @@ fixup_var_refs (var, promoted_mode, unsignedp, may_share, ht) rtx var; enum machine_mode promoted_mode; int unsignedp; - struct hash_table *ht; + htab_t ht; rtx may_share; { tree pending; @@ -1716,17 +1694,18 @@ fixup_var_refs_insns (insn, var, promoted_mode, unsignedp, toplevel, may_share) static void fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp, may_share) - struct hash_table *ht; + htab_t ht; rtx var; enum machine_mode promoted_mode; int unsignedp; rtx may_share; { - struct insns_for_mem_entry *ime - = (struct insns_for_mem_entry *) hash_lookup (ht, var, - /*create=*/0, /*copy=*/0); + struct insns_for_mem_entry tmp; + struct insns_for_mem_entry *ime; rtx insn_list; + tmp.key = var; + ime = (struct insns_for_mem_entry *) htab_find (ht, &tmp); for (insn_list = ime->insns; insn_list != 0; insn_list = XEXP (insn_list, 1)) if (INSN_P (XEXP (insn_list, 0))) fixup_var_refs_insn (XEXP (insn_list, 0), var, promoted_mode, @@ -1872,7 +1851,7 @@ fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel, no_share) /* OLD might be a (subreg (mem)). */ if (GET_CODE (replacements->old) == SUBREG) replacements->old - = fixup_memory_subreg (replacements->old, insn, + = fixup_memory_subreg (replacements->old, insn, promoted_mode, 0); else replacements->old @@ -1890,7 +1869,7 @@ fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel, no_share) start_sequence (); convert_move (replacements->new, replacements->old, unsignedp); - seq = gen_sequence (); + seq = get_insns (); end_sequence (); } else @@ -1972,7 +1951,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share) start_sequence (); new_insn = emit_insn (gen_rtx_SET (VOIDmode, y, sub)); - seq = gen_sequence (); + seq = get_insns (); end_sequence (); if (recog_memoized (new_insn) < 0) @@ -1983,7 +1962,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share) sub = force_operand (sub, y); if (sub != y) emit_insn (gen_move_insn (y, sub)); - seq = gen_sequence (); + seq = get_insns (); end_sequence (); } @@ -2200,7 +2179,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share) return; } - replacement->new = *loc = fixup_memory_subreg (x, insn, + replacement->new = *loc = fixup_memory_subreg (x, insn, promoted_mode, 0); INSN_CODE (insn) = -1; @@ -2408,12 +2387,12 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share) copy SET_SRC (x) to SET_DEST (x) in some way. So we generate the move and see whether it requires more than one insn. If it does, we emit those insns and - delete INSN. Otherwise, we an just replace the pattern + delete INSN. Otherwise, we can just replace the pattern of INSN; we have already verified above that INSN has no other function that to do X. */ pat = gen_move_insn (SET_DEST (x), SET_SRC (x)); - if (GET_CODE (pat) == SEQUENCE) + if (NEXT_INSN (pat) != NULL_RTX) { last = emit_insn_before (pat, insn); @@ -2431,7 +2410,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share) delete_insn (last); } else - PATTERN (insn) = pat; + PATTERN (insn) = PATTERN (pat); return; } @@ -2448,7 +2427,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share) rtx pat, last; if (GET_CODE (SET_DEST (x)) == SUBREG) - SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn, + SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn, promoted_mode, 0); else SET_DEST (x) = fixup_stack_1 (SET_DEST (x), insn); @@ -2457,7 +2436,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share) return; pat = gen_move_insn (SET_DEST (x), SET_SRC (x)); - if (GET_CODE (pat) == SEQUENCE) + if (NEXT_INSN (pat) != NULL_RTX) { last = emit_insn_before (pat, insn); @@ -2475,7 +2454,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share) delete_insn (last); } else - PATTERN (insn) = pat; + PATTERN (insn) = PATTERN (pat); return; } @@ -2502,7 +2481,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share) /* Convert (SUBREG (MEM)) to a MEM in a changed mode. */ if (GET_CODE (fixeddest) == SUBREG) { - fixeddest = fixup_memory_subreg (fixeddest, insn, + fixeddest = fixup_memory_subreg (fixeddest, insn, promoted_mode, 0); temp_mode = GET_MODE (fixeddest); } @@ -2547,7 +2526,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share) /* Previously, X had the form (SUBREG:m1 (REG:PROMOTED_MODE ...)). The REG was placed on the stack, so X now has the form (SUBREG:m1 - (MEM:m2 ...)). + (MEM:m2 ...)). Return an rtx (MEM:m1 newaddr) which is equivalent. If any insns must be emitted to compute NEWADDR, put them before INSN. @@ -2566,7 +2545,7 @@ fixup_memory_subreg (x, insn, promoted_mode, uncritical) rtx mem = SUBREG_REG (x); rtx addr = XEXP (mem, 0); enum machine_mode mode = GET_MODE (x); - rtx result; + rtx result, seq; /* Paradoxical SUBREGs are usually invalid during RTL generation. */ if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (mem)) && ! uncritical) @@ -2576,7 +2555,7 @@ fixup_memory_subreg (x, insn, promoted_mode, uncritical) if (BYTES_BIG_ENDIAN) /* If the PROMOTED_MODE is wider than the mode of the MEM, adjust the offset so that it points to the right location within the - MEM. */ + MEM. */ offset -= (GET_MODE_SIZE (promoted_mode) - GET_MODE_SIZE (GET_MODE (mem))); if (!flag_force_addr @@ -2586,8 +2565,10 @@ fixup_memory_subreg (x, insn, promoted_mode, uncritical) start_sequence (); result = adjust_address (mem, mode, offset); - emit_insn_before (gen_sequence (), insn); + seq = get_insns (); end_sequence (); + + emit_insn_before (seq, insn); return result; } @@ -2596,7 +2577,7 @@ fixup_memory_subreg (x, insn, promoted_mode, uncritical) If X itself is a (SUBREG (MEM ...) ...), return the replacement expression. Otherwise return X, with its contents possibly altered. - INSN, PROMOTED_MODE and UNCRITICAL are as for + INSN, PROMOTED_MODE and UNCRITICAL are as for fixup_memory_subreg. */ static rtx @@ -2624,14 +2605,14 @@ walk_fixup_memory_subreg (x, insn, promoted_mode, uncritical) for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') - XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn, + XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn, promoted_mode, uncritical); else if (fmt[i] == 'E') { int j; for (j = 0; j < XVECLEN (x, i); j++) XVECEXP (x, i, j) - = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn, + = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn, promoted_mode, uncritical); } } @@ -2677,7 +2658,7 @@ fixup_stack_1 (x, insn) start_sequence (); temp = copy_to_reg (ad); - seq = gen_sequence (); + seq = get_insns (); end_sequence (); emit_insn_before (seq, insn); return replace_equiv_address (x, temp); @@ -2788,7 +2769,7 @@ optimize_bit_field (body, insn, equiv_mem) memref = adjust_address (memref, mode, offset); insns = get_insns (); end_sequence (); - emit_insns_before (insns, insn); + emit_insn_before (insns, insn); /* Store this memory reference where we found the bit field reference. */ @@ -2856,7 +2837,7 @@ optimize_bit_field (body, insn, equiv_mem) special; just let the optimization be suppressed. */ if (apply_change_group () && seq) - emit_insns_before (seq, insn); + emit_insn_before (seq, insn); } } } @@ -2914,15 +2895,19 @@ static int cfa_offset; #define ARG_POINTER_CFA_OFFSET(FNDECL) FIRST_PARM_OFFSET (FNDECL) #endif -/* Build up a (MEM (ADDRESSOF (REG))) rtx for a register REG that just had its - address taken. DECL is the decl or SAVE_EXPR for the object stored in the - register, for later use if we do need to force REG into the stack. REG is - overwritten by the MEM like in put_reg_into_stack. */ +/* Build up a (MEM (ADDRESSOF (REG))) rtx for a register REG that just + had its address taken. DECL is the decl or SAVE_EXPR for the + object stored in the register, for later use if we do need to force + REG into the stack. REG is overwritten by the MEM like in + put_reg_into_stack. RESCAN is true if previously emitted + instructions must be rescanned and modified now that the REG has + been transformed. */ rtx -gen_mem_addressof (reg, decl) +gen_mem_addressof (reg, decl, rescan) rtx reg; tree decl; + int rescan; { rtx r = gen_rtx_ADDRESSOF (Pmode, gen_reg_rtx (GET_MODE (reg)), REGNO (reg), decl); @@ -2960,10 +2945,11 @@ gen_mem_addressof (reg, decl) if (DECL_P (decl) && decl_rtl == reg) SET_DECL_RTL (decl, reg); - if (TREE_USED (decl) || (DECL_P (decl) && DECL_INITIAL (decl) != 0)) + if (rescan + && (TREE_USED (decl) || (DECL_P (decl) && DECL_INITIAL (decl) != 0))) fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type), reg, 0); } - else + else if (rescan) fixup_var_refs (reg, GET_MODE (reg), 0, reg, 0); return reg; @@ -2988,7 +2974,7 @@ flush_addressof (decl) static void put_addressof_into_stack (r, ht) rtx r; - struct hash_table *ht; + htab_t ht; { tree decl, type; int volatile_p, used_p; @@ -3040,7 +3026,7 @@ purge_addressof_1 (loc, insn, force, store, ht) rtx *loc; rtx insn; int force, store; - struct hash_table *ht; + htab_t ht; { rtx x; RTX_CODE code; @@ -3072,7 +3058,7 @@ purge_addressof_1 (loc, insn, force, store, ht) if (GET_CODE (XEXP (x, 0)) != MEM) put_addressof_into_stack (x, ht); - + /* We must create a copy of the rtx because it was created by overwriting a REG rtx which is always shared. */ sub = copy_rtx (XEXP (XEXP (x, 0), 0)); @@ -3086,7 +3072,7 @@ purge_addressof_1 (loc, insn, force, store, ht) && ! validate_replace_rtx (x, sub, insn)) abort (); - insns = gen_sequence (); + insns = get_insns (); end_sequence (); emit_insn_before (insns, insn); return true; @@ -3174,10 +3160,16 @@ purge_addressof_1 (loc, insn, force, store, ht) size_x = GET_MODE_BITSIZE (GET_MODE (x)); size_sub = GET_MODE_BITSIZE (GET_MODE (sub)); + /* Do not frob unchanging MEMs. If a later reference forces the + pseudo to the stack, we can wind up with multiple writes to + an unchanging memory, which is invalid. */ + if (RTX_UNCHANGING_P (x) && size_x != size_sub) + ; + /* Don't even consider working with paradoxical subregs, or the moral equivalent seen here. */ - if (size_x <= size_sub - && int_mode_for_mode (GET_MODE (sub)) != BLKmode) + else if (size_x <= size_sub + && int_mode_for_mode (GET_MODE (sub)) != BLKmode) { /* Do a bitfield insertion to mirror what would happen in memory. */ @@ -3197,7 +3189,7 @@ purge_addressof_1 (loc, insn, force, store, ht) end_sequence (); goto give_up; } - seq = gen_sequence (); + seq = get_insns (); end_sequence (); emit_insn_before (seq, insn); compute_insns_for_mem (p ? NEXT_INSN (p) : get_insns (), @@ -3211,7 +3203,7 @@ purge_addressof_1 (loc, insn, force, store, ht) might have created. */ unshare_all_rtl_again (get_insns ()); - seq = gen_sequence (); + seq = get_insns (); end_sequence (); p = emit_insn_after (seq, insn); if (NEXT_INSN (insn)) @@ -3236,7 +3228,7 @@ purge_addressof_1 (loc, insn, force, store, ht) goto give_up; } - seq = gen_sequence (); + seq = get_insns (); end_sequence (); emit_insn_before (seq, insn); compute_insns_for_mem (p ? NEXT_INSN (p) : get_insns (), @@ -3297,50 +3289,34 @@ purge_addressof_1 (loc, insn, force, store, ht) return result; } -/* Return a new hash table entry in HT. */ - -static struct hash_entry * -insns_for_mem_newfunc (he, ht, k) - struct hash_entry *he; - struct hash_table *ht; - hash_table_key k ATTRIBUTE_UNUSED; -{ - struct insns_for_mem_entry *ifmhe; - if (he) - return he; - - ifmhe = ((struct insns_for_mem_entry *) - hash_allocate (ht, sizeof (struct insns_for_mem_entry))); - ifmhe->insns = NULL_RTX; - - return &ifmhe->he; -} - /* Return a hash value for K, a REG. */ -static unsigned long +static hashval_t insns_for_mem_hash (k) - hash_table_key k; + const void * k; { - /* K is really a RTX. Just use the address as the hash value. */ - return (unsigned long) k; + /* Use the address of the key for the hash value. */ + struct insns_for_mem_entry *m = (struct insns_for_mem_entry *) k; + return htab_hash_pointer (m->key); } -/* Return non-zero if K1 and K2 (two REGs) are the same. */ +/* Return nonzero if K1 and K2 (two REGs) are the same. */ -static bool +static int insns_for_mem_comp (k1, k2) - hash_table_key k1; - hash_table_key k2; + const void * k1; + const void * k2; { - return k1 == k2; + struct insns_for_mem_entry *m1 = (struct insns_for_mem_entry *) k1; + struct insns_for_mem_entry *m2 = (struct insns_for_mem_entry *) k2; + return m1->key == m2->key; } struct insns_for_mem_walk_info { /* The hash table that we are using to record which INSNs use which MEMs. */ - struct hash_table *ht; + htab_t ht; /* The INSN we are currently processing. */ rtx insn; @@ -3362,18 +3338,26 @@ insns_for_mem_walk (r, data) { struct insns_for_mem_walk_info *ifmwi = (struct insns_for_mem_walk_info *) data; + struct insns_for_mem_entry tmp; + tmp.insns = NULL_RTX; if (ifmwi->pass == 0 && *r && GET_CODE (*r) == ADDRESSOF && GET_CODE (XEXP (*r, 0)) == REG) - hash_lookup (ifmwi->ht, XEXP (*r, 0), /*create=*/1, /*copy=*/0); + { + PTR *e; + tmp.key = XEXP (*r, 0); + e = htab_find_slot (ifmwi->ht, &tmp, INSERT); + if (*e == NULL) + { + *e = ggc_alloc (sizeof (tmp)); + memcpy (*e, &tmp, sizeof (tmp)); + } + } else if (ifmwi->pass == 1 && *r && GET_CODE (*r) == REG) { - /* Lookup this MEM in the hashtable, creating it if necessary. */ - struct insns_for_mem_entry *ifme - = (struct insns_for_mem_entry *) hash_lookup (ifmwi->ht, - *r, - /*create=*/0, - /*copy=*/0); + struct insns_for_mem_entry *ifme; + tmp.key = *r; + ifme = (struct insns_for_mem_entry *) htab_find (ifmwi->ht, &tmp); /* If we have not already recorded this INSN, do so now. Since we process the INSNs in order, we know that if we have @@ -3393,7 +3377,7 @@ static void compute_insns_for_mem (insns, last_insn, ht) rtx insns; rtx last_insn; - struct hash_table *ht; + htab_t ht; { rtx insn; struct insns_for_mem_walk_info ifmwi; @@ -3428,7 +3412,7 @@ purge_addressof (insns) rtx insns; { rtx insn; - struct hash_table ht; + htab_t ht; /* When we actually purge ADDRESSOFs, we turn REGs into MEMs. That requires a fixup pass over the instruction stream to correct @@ -3437,23 +3421,20 @@ purge_addressof (insns) mentioned in very many instructions. So, we speed up the process by pre-calculating which REGs occur in which INSNs; that allows us to perform the fixup passes much more quickly. */ - hash_table_init (&ht, - insns_for_mem_newfunc, - insns_for_mem_hash, - insns_for_mem_comp); - compute_insns_for_mem (insns, NULL_RTX, &ht); + ht = htab_create_ggc (1000, insns_for_mem_hash, insns_for_mem_comp, NULL); + compute_insns_for_mem (insns, NULL_RTX, ht); for (insn = insns; insn; insn = NEXT_INSN (insn)) if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == CALL_INSN) { if (! purge_addressof_1 (&PATTERN (insn), insn, - asm_noperands (PATTERN (insn)) > 0, 0, &ht)) + asm_noperands (PATTERN (insn)) > 0, 0, ht)) /* If we could not replace the ADDRESSOFs in the insn, something is wrong. */ abort (); - if (! purge_addressof_1 (®_NOTES (insn), NULL_RTX, 0, 0, &ht)) + if (! purge_addressof_1 (®_NOTES (insn), NULL_RTX, 0, 0, ht)) { /* If we could not replace the ADDRESSOFs in the insn's notes, we can just remove the offending notes instead. */ @@ -3474,7 +3455,6 @@ purge_addressof (insns) } /* Clean up. */ - hash_table_free (&ht); purge_bitfield_addressof_replacements = 0; purge_addressof_replacements = 0; @@ -3514,7 +3494,7 @@ purge_single_hard_subreg_set (pattern) reg = SUBREG_REG (reg); } - + if (GET_CODE (reg) == REG && REGNO (reg) < FIRST_PSEUDO_REGISTER) { reg = gen_rtx_REG (mode, REGNO (reg) + offset); @@ -3543,7 +3523,7 @@ purge_hard_subreg_sets (insn) case SET: if (GET_CODE (SET_DEST (pattern)) == SUBREG) purge_single_hard_subreg_set (pattern); - break; + break; case PARALLEL: { int j; @@ -3597,11 +3577,19 @@ instantiate_virtual_regs (fndecl, insns) || GET_CODE (insn) == CALL_INSN) { instantiate_virtual_regs_1 (&PATTERN (insn), insn, 1); + if (INSN_DELETED_P (insn)) + continue; instantiate_virtual_regs_1 (®_NOTES (insn), NULL_RTX, 0); /* Instantiate any virtual registers in CALL_INSN_FUNCTION_USAGE. */ if (GET_CODE (insn) == CALL_INSN) instantiate_virtual_regs_1 (&CALL_INSN_FUNCTION_USAGE (insn), NULL_RTX, 0); + + /* Past this point all ASM statements should match. Verify that + to avoid failures later in the compilation process. */ + if (asm_noperands (PATTERN (insn)) >= 0 + && ! check_asm_operands (PATTERN (insn))) + instantiate_virtual_regs_lossage (insn); } /* Instantiate the stack slots for the parm registers, for later use in @@ -3664,7 +3652,7 @@ instantiate_decls_1 (let, valid_only) for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t)) if (DECL_RTL_SET_P (t)) - instantiate_decl (DECL_RTL (t), + instantiate_decl (DECL_RTL (t), int_size_in_bytes (TREE_TYPE (t)), valid_only); @@ -3676,7 +3664,7 @@ instantiate_decls_1 (let, valid_only) /* Subroutine of the preceding procedures: Given RTL representing a decl and the size of the object, do any instantiation required. - If VALID_ONLY is non-zero, it means that the RTL should only be + If VALID_ONLY is nonzero, it means that the RTL should only be changed if the new address is valid. */ static void @@ -3769,6 +3757,22 @@ instantiate_new_reg (x, poffset) return new; } + +/* Called when instantiate_virtual_regs has failed to update the instruction. + Usually this means that non-matching instruction has been emit, however for + asm statements it may be the problem in the constraints. */ +static void +instantiate_virtual_regs_lossage (insn) + rtx insn; +{ + if (asm_noperands (PATTERN (insn)) >= 0) + { + error_for_asm (insn, "impossible constraint in `asm'"); + delete_insn (insn); + } + else + abort (); +} /* Given a pointer to a piece of rtx and an optional pointer to the containing object, instantiate any virtual registers present in it. @@ -3805,6 +3809,10 @@ instantiate_virtual_regs_1 (loc, object, extra_insns) if (x == 0) return 1; + /* We may have detected and deleted invalid asm statements. */ + if (object && INSN_P (object) && INSN_DELETED_P (object)) + return 1; + code = GET_CODE (x); /* Check for some special cases. */ @@ -3842,7 +3850,10 @@ instantiate_virtual_regs_1 (loc, object, extra_insns) /* The only valid sources here are PLUS or REG. Just do the simplest possible thing to handle them. */ if (GET_CODE (src) != REG && GET_CODE (src) != PLUS) - abort (); + { + instantiate_virtual_regs_lossage (object); + return 1; + } start_sequence (); if (GET_CODE (src) != REG) @@ -3853,12 +3864,12 @@ instantiate_virtual_regs_1 (loc, object, extra_insns) seq = get_insns (); end_sequence (); - emit_insns_before (seq, object); + emit_insn_before (seq, object); SET_DEST (x) = new; if (! validate_change (object, &SET_SRC (x), temp, 0) || ! extra_insns) - abort (); + instantiate_virtual_regs_lossage (object); return 1; } @@ -3965,10 +3976,13 @@ instantiate_virtual_regs_1 (loc, object, extra_insns) seq = get_insns (); end_sequence (); - emit_insns_before (seq, object); + emit_insn_before (seq, object); if (! validate_change (object, loc, temp, 0) && ! validate_replace_rtx (x, temp, object)) - abort (); + { + instantiate_virtual_regs_lossage (object); + return 1; + } } } @@ -4119,10 +4133,10 @@ instantiate_virtual_regs_1 (loc, object, extra_insns) seq = get_insns (); end_sequence (); - emit_insns_before (seq, object); + emit_insn_before (seq, object); if (! validate_change (object, loc, temp, 0) && ! validate_replace_rtx (x, temp, object)) - abort (); + instantiate_virtual_regs_lossage (object); } } @@ -4322,17 +4336,6 @@ assign_parms (fndecl) rtx conversion_insns = 0; struct args_size alignment_pad; - /* Nonzero if the last arg is named `__builtin_va_alist', - which is used on some machines for old-fashioned non-ANSI varargs.h; - this should be stuck onto the stack as if it had arrived there. */ - int hide_last_arg - = (current_function_varargs - && fnargs - && (parm = tree_last (fnargs)) != 0 - && DECL_NAME (parm) - && (! strcmp (IDENTIFIER_POINTER (DECL_NAME (parm)), - "__builtin_va_alist"))); - /* Nonzero if function takes extra anonymous args. This means the last named arg must be on the stack right before the anonymous ones. */ @@ -4376,7 +4379,7 @@ assign_parms (fndecl) } max_parm_reg = LAST_VIRTUAL_REGISTER + 1; - parm_reg_stack_loc = (rtx *) xcalloc (max_parm_reg, sizeof (rtx)); + parm_reg_stack_loc = (rtx *) ggc_alloc_cleared (max_parm_reg * sizeof (rtx)); #ifdef INIT_CUMULATIVE_INCOMING_ARGS INIT_CUMULATIVE_INCOMING_ARGS (args_so_far, fntype, NULL_RTX); @@ -4401,7 +4404,7 @@ assign_parms (fndecl) /* Set LAST_NAMED if this is last named arg before last anonymous args. */ - if (stdarg || current_function_varargs) + if (stdarg) { tree tem; @@ -4429,11 +4432,6 @@ assign_parms (fndecl) continue; } - /* For varargs.h function, save info about regs and stack space - used by the individual args, not including the va_alist arg. */ - if (hide_last_arg && last_named) - current_function_args_info = args_so_far; - /* Find mode of arg as it is passed, and mode of arg as it should be during execution of this function. */ passed_mode = TYPE_MODE (passed_type); @@ -4474,6 +4472,15 @@ assign_parms (fndecl) passed_pointer = 1; passed_mode = nominal_mode = Pmode; } + /* See if the frontend wants to pass this by invisible reference. */ + else if (passed_type != nominal_type + && POINTER_TYPE_P (passed_type) + && TREE_TYPE (passed_type) == nominal_type) + { + nominal_type = passed_type; + passed_pointer = 1; + passed_mode = nominal_mode = Pmode; + } promoted_mode = passed_mode; @@ -4581,6 +4588,12 @@ assign_parms (fndecl) if (nregs > 0) { +#if defined (REG_PARM_STACK_SPACE) && !defined (MAYBE_REG_PARM_STACK_SPACE) + /* When REG_PARM_STACK_SPACE is nonzero, stack space for + split parameters was allocated by our caller, so we + won't be pushing it in the prolog. */ + if (REG_PARM_STACK_SPACE (fndecl) == 0) +#endif current_function_pretend_args_size = (((nregs * UNITS_PER_WORD) + (PARM_BOUNDARY / BITS_PER_UNIT) - 1) / (PARM_BOUNDARY / BITS_PER_UNIT) @@ -4615,8 +4628,8 @@ assign_parms (fndecl) to indicate there is no preallocated stack slot for the parm. */ if (entry_parm == stack_parm - || (GET_CODE (entry_parm) == PARALLEL - && XEXP (XVECEXP (entry_parm, 0, 0), 0) == NULL_RTX) + || (GET_CODE (entry_parm) == PARALLEL + && XEXP (XVECEXP (entry_parm, 0, 0), 0) == NULL_RTX) #if defined (REG_PARM_STACK_SPACE) && ! defined (MAYBE_REG_PARM_STACK_SPACE) /* On some machines, even if a parm value arrives in a register there is still an (uninitialized) stack slot allocated for it. @@ -4770,7 +4783,7 @@ assign_parms (fndecl) if (passed_pointer) { rtx x = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (passed_type)), - parmreg); + parmreg); set_mem_attributes (x, parm, 1); SET_DECL_RTL (parm, x); } @@ -4779,7 +4792,7 @@ assign_parms (fndecl) SET_DECL_RTL (parm, parmreg); maybe_set_unchanging (DECL_RTL (parm), parm); } - + /* Copy the value into the register. */ if (nominal_mode != passed_mode || promoted_nominal_mode != promoted_mode) @@ -4822,7 +4835,7 @@ assign_parms (fndecl) /* The argument is already sign/zero extended, so note it into the subreg. */ SUBREG_PROMOTED_VAR_P (tempreg) = 1; - SUBREG_PROMOTED_UNSIGNED_P (tempreg) = unsignedp; + SUBREG_PROMOTED_UNSIGNED_SET (tempreg, unsignedp); } /* TREE_USED gets set erroneously during expand_assignment. */ @@ -4861,7 +4874,7 @@ assign_parms (fndecl) push_to_sequence (conversion_insns); emit_move_insn (tempreg, DECL_RTL (parm)); SET_DECL_RTL (parm, - convert_to_mode (GET_MODE (parmreg), + convert_to_mode (GET_MODE (parmreg), tempreg, unsigned_p)); emit_move_insn (parmreg, DECL_RTL (parm)); @@ -4940,7 +4953,7 @@ assign_parms (fndecl) but it's also rare and we need max_parm_reg to be precisely correct. */ max_parm_reg = regno + 1; - new = (rtx *) xrealloc (parm_reg_stack_loc, + new = (rtx *) ggc_realloc (parm_reg_stack_loc, max_parm_reg * sizeof (rtx)); memset ((char *) (new + old_max_parm_reg), 0, (max_parm_reg - old_max_parm_reg) * sizeof (rtx)); @@ -5031,7 +5044,7 @@ assign_parms (fndecl) stack. So, we go back to that sequence, just so that the fixups will happen. */ push_to_sequence (conversion_insns); - put_var_into_stack (parm); + put_var_into_stack (parm, /*rescan=*/true); conversion_insns = get_insns (); end_sequence (); } @@ -5116,7 +5129,7 @@ assign_parms (fndecl) /* Output all parameter conversion instructions (possibly including calls) now that all parameters have been copied out of hard registers. */ - emit_insns (conversion_insns); + emit_insn (conversion_insns); last_parm_insn = get_last_insn (); @@ -5157,8 +5170,7 @@ assign_parms (fndecl) /* For stdarg.h function, save info about regs and stack space used by the named args. */ - if (!hide_last_arg) - current_function_args_info = args_so_far; + current_function_args_info = args_so_far; /* Set the rtx used for the function return value. Put this in its own variable so any optimizers that need this information don't have @@ -5248,7 +5260,7 @@ promoted_input_arg (regno, pmode, punsignedp) The starting offset and size for this parm are returned in *OFFSET_PTR and *ARG_SIZE_PTR, respectively. - IN_REGS is non-zero if the argument will be passed in registers. It will + IN_REGS is nonzero if the argument will be passed in registers. It will never be set if REG_PARM_STACK_SPACE is not defined. FNDECL is the function in which the argument was defined. @@ -5286,6 +5298,9 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl, = type ? size_in_bytes (type) : size_int (GET_MODE_SIZE (passed_mode)); enum direction where_pad = FUNCTION_ARG_PADDING (passed_mode, type); int boundary = FUNCTION_ARG_BOUNDARY (passed_mode, type); +#ifdef ARGS_GROW_DOWNWARD + tree s2 = sizetree; +#endif #ifdef REG_PARM_STACK_SPACE /* If we have found a stack parm before we reach the end of the @@ -5331,13 +5346,20 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl, offset_ptr->constant = -initial_offset_ptr->constant; offset_ptr->var = 0; } + if (where_pad != none && (!host_integerp (sizetree, 1) || (tree_low_cst (sizetree, 1) * BITS_PER_UNIT) % PARM_BOUNDARY)) - sizetree = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT); - SUB_PARM_SIZE (*offset_ptr, sizetree); - if (where_pad != downward) + s2 = round_up (s2, PARM_BOUNDARY / BITS_PER_UNIT); + SUB_PARM_SIZE (*offset_ptr, s2); + + if (!in_regs +#ifdef REG_PARM_STACK_SPACE + || REG_PARM_STACK_SPACE (fndecl) > 0 +#endif + ) pad_to_arg_alignment (offset_ptr, boundary, alignment_pad); + if (initial_offset_ptr->var) arg_size_ptr->var = size_binop (MINUS_EXPR, size_binop (MINUS_EXPR, @@ -5349,6 +5371,13 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl, arg_size_ptr->constant = (-initial_offset_ptr->constant - offset_ptr->constant); + /* Pad_below needs the pre-rounded size to know how much to pad below. + We only pad parameters which are not in registers as they have their + padding done elsewhere. */ + if (where_pad == downward + && !in_regs) + pad_below (offset_ptr, passed_mode, sizetree); + #else /* !ARGS_GROW_DOWNWARD */ if (!in_regs #ifdef REG_PARM_STACK_SPACE @@ -5416,8 +5445,8 @@ pad_to_arg_alignment (offset_ptr, boundary, alignment_pad) (ARGS_SIZE_TREE (*offset_ptr), boundary / BITS_PER_UNIT); offset_ptr->constant = 0; /*?*/ - if (boundary > PARM_BOUNDARY && boundary > STACK_BOUNDARY) - alignment_pad->var = size_binop (MINUS_EXPR, offset_ptr->var, + if (boundary > PARM_BOUNDARY && boundary > STACK_BOUNDARY) + alignment_pad->var = size_binop (MINUS_EXPR, offset_ptr->var, save_var); } else @@ -5434,7 +5463,6 @@ pad_to_arg_alignment (offset_ptr, boundary, alignment_pad) } } -#ifndef ARGS_GROW_DOWNWARD static void pad_below (offset_ptr, passed_mode, sizetree) struct args_size *offset_ptr; @@ -5462,7 +5490,6 @@ pad_below (offset_ptr, passed_mode, sizetree) } } } -#endif /* Walk the tree of blocks describing the binding levels within a function and warn about uninitialized variables. @@ -5477,7 +5504,7 @@ uninitialized_vars_warning (block) for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl)) { if (warn_uninitialized - && TREE_CODE (decl) == VAR_DECL + && TREE_CODE (decl) == VAR_DECL /* These warnings are unreliable for and aggregates because assigning the fields one by one can fail to convince flow.c that the entire aggregate was initialized. @@ -5497,7 +5524,7 @@ uninitialized_vars_warning (block) warning_with_decl (decl, "`%s' might be used uninitialized in this function"); if (extra_warnings - && TREE_CODE (decl) == VAR_DECL + && TREE_CODE (decl) == VAR_DECL && DECL_RTL (decl) != 0 && GET_CODE (DECL_RTL (decl)) == REG && regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl)))) @@ -5553,7 +5580,7 @@ setjmp_protect (block) || #endif ! DECL_REGISTER (decl))) - put_var_into_stack (decl); + put_var_into_stack (decl, /*rescan=*/true); for (sub = BLOCK_SUBBLOCKS (block); sub; sub = TREE_CHAIN (sub)) setjmp_protect (sub); } @@ -5580,7 +5607,7 @@ setjmp_protect_args () || #endif ! DECL_REGISTER (decl))) - put_var_into_stack (decl); + put_var_into_stack (decl, /*rescan=*/true); } /* Return the context-pointer register corresponding to DECL, @@ -5739,12 +5766,8 @@ trampoline_address (function) #else /* If rounding needed, allocate extra space to ensure we have TRAMPOLINE_SIZE bytes left after rounding up. */ -#ifdef TRAMPOLINE_ALIGNMENT #define TRAMPOLINE_REAL_SIZE \ (TRAMPOLINE_SIZE + (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT) - 1) -#else -#define TRAMPOLINE_REAL_SIZE (TRAMPOLINE_SIZE) -#endif tramp = assign_stack_local_1 (BLKmode, TRAMPOLINE_REAL_SIZE, 0, fp ? fp : cfun); #endif @@ -5779,7 +5802,6 @@ static rtx round_trampoline_addr (tramp) rtx tramp; { -#ifdef TRAMPOLINE_ALIGNMENT /* Round address up to desired boundary. */ rtx temp = gen_reg_rtx (Pmode); rtx addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1); @@ -5789,7 +5811,7 @@ round_trampoline_addr (tramp) temp, 0, OPTAB_LIB_WIDEN); tramp = expand_simple_binop (Pmode, AND, temp, mask, temp, 0, OPTAB_LIB_WIDEN); -#endif + return tramp; } @@ -5942,8 +5964,6 @@ reorder_blocks () /* Remove deleted blocks from the block fragment chains. */ reorder_fix_fragments (block); - - VARRAY_FREE (block_stack); } /* Helper function for reorder_blocks. Reset TREE_ASM_WRITTEN. */ @@ -6031,7 +6051,7 @@ reorder_blocks_1 (insns, current_block, p_block_stack) static void reorder_fix_fragments (block) - tree block; + tree block; { while (block) { @@ -6043,7 +6063,7 @@ reorder_fix_fragments (block) if (! TREE_ASM_WRITTEN (dup_origin)) { new_origin = BLOCK_FRAGMENT_CHAIN (dup_origin); - + /* Find the first of the remaining fragments. There must be at least one -- the current block. */ while (! TREE_ASM_WRITTEN (new_origin)) @@ -6312,8 +6332,7 @@ prepare_function_start () /* Indicate we have no need of a frame pointer yet. */ frame_pointer_needed = 0; - /* By default assume not varargs or stdarg. */ - current_function_varargs = 0; + /* By default assume not stdarg. */ current_function_stdarg = 0; /* We haven't made any trampolines for this function yet. */ @@ -6324,10 +6343,19 @@ prepare_function_start () current_function_outgoing_args_size = 0; - if (init_lang_status) - (*init_lang_status) (cfun); + current_function_funcdef_no = funcdef_no++; + + cfun->arc_profile = profile_arc_flag || flag_test_coverage; + + cfun->arc_profile = profile_arc_flag || flag_test_coverage; + + cfun->function_frequency = FUNCTION_FREQUENCY_NORMAL; + + cfun->max_jumptable_ents = 0; + + (*lang_hooks.function.init) (cfun); if (init_machine_status) - (*init_machine_status) (cfun); + cfun->machine = (*init_machine_status) (); } /* Initialize the rtl expansion mechanism so that we can do simple things @@ -6351,7 +6379,7 @@ init_function_start (subr, filename, line) { prepare_function_start (); - current_function_name = (*decl_printable_name) (subr, 2); + current_function_name = (*lang_hooks.decl_printable_name) (subr, 2); cfun->decl = subr; /* Nonzero if this is a nested function that uses a static chain. */ @@ -6406,15 +6434,6 @@ init_function_for_compilation () VARRAY_GROW (sibcall_epilogue, 0); } -/* Indicate that the current function uses extra args - not explicitly mentioned in the argument list in any fashion. */ - -void -mark_varargs () -{ - current_function_varargs = 1; -} - /* Expand a call to __main at the beginning of a possible main function. */ #if defined(INIT_SECTION_ASM_OP) && !defined(INVOKE__main) @@ -6444,11 +6463,11 @@ expand_main_function () #endif if (tmp != stack_pointer_rtx) emit_move_insn (stack_pointer_rtx, tmp); - + /* Enlist allocate_dynamic_stack_space to pick up the pieces. */ tmp = force_reg (Pmode, const0_rtx); allocate_dynamic_stack_space (tmp, NULL_RTX, BIGGEST_ALIGNMENT); - seq = gen_sequence (); + seq = get_insns (); end_sequence (); for (tmp = get_last_insn (); tmp; tmp = PREV_INSN (tmp)) @@ -6467,8 +6486,6 @@ expand_main_function () #endif } -extern struct obstack permanent_obstack; - /* The PENDING_SIZES represent the sizes of variable-sized types. Create RTL for the various sizes now (using temporary variables), so that we can refer to the sizes from the RTL we are generating @@ -6597,18 +6614,17 @@ expand_function_start (subr, parms_have_cleanups) subr, 1); /* Structures that are returned in registers are not aggregate_value_p, - so we may see a PARALLEL. Don't play pseudo games with this. */ - if (! REG_P (hard_reg)) - SET_DECL_RTL (DECL_RESULT (subr), hard_reg); + so we may see a PARALLEL or a REG. */ + if (REG_P (hard_reg)) + SET_DECL_RTL (DECL_RESULT (subr), gen_reg_rtx (GET_MODE (hard_reg))); + else if (GET_CODE (hard_reg) == PARALLEL) + SET_DECL_RTL (DECL_RESULT (subr), gen_group_rtx (hard_reg)); else - { - /* Create the pseudo. */ - SET_DECL_RTL (DECL_RESULT (subr), gen_reg_rtx (GET_MODE (hard_reg))); + abort (); - /* Needed because we may need to move this to memory - in case it's a named return value whose address is taken. */ - DECL_REGISTER (DECL_RESULT (subr)) = 1; - } + /* Set DECL_REGISTER flag so that expand_function_end will copy the + result to the real return register(s). */ + DECL_REGISTER (DECL_RESULT (subr)) = 1; } /* Initialize rtx for parameters and local variables. @@ -6620,8 +6636,8 @@ expand_function_start (subr, parms_have_cleanups) avoid conflicts with the parameter passing registers. */ if (SMALL_REGISTER_CLASSES && current_function_needs_context) - if (GET_CODE (static_chain_incoming_rtx) != REG) - emit_move_insn (last_ptr, static_chain_incoming_rtx); + if (GET_CODE (static_chain_incoming_rtx) != REG) + emit_move_insn (last_ptr, static_chain_incoming_rtx); /* The following was moved from init_function_start. The move is supposed to make sdb output more accurate. */ @@ -6696,9 +6712,8 @@ expand_function_start (subr, parms_have_cleanups) if (current_function_profile) { - current_function_profile_label_no = profile_label_no++; #ifdef PROFILE_HOOK - PROFILE_HOOK (current_function_profile_label_no); + PROFILE_HOOK (current_function_funcdef_no); #endif } @@ -6798,6 +6813,8 @@ use_return_register () diddle_return_value (do_use_return_reg, NULL); } +static GTY(()) rtx initial_trampoline; + /* Generate RTL for the end of the current function. FILENAME and LINE are the current position in the source file. @@ -6813,10 +6830,6 @@ expand_function_end (filename, line, end_bindings) tree link; rtx clobber_after; -#ifdef TRAMPOLINE_TEMPLATE - static rtx initial_trampoline; -#endif - finish_expr_for_function (); /* If arg_pointer_save_area was referenced only from a nested @@ -6855,8 +6868,6 @@ expand_function_end (filename, line, end_bindings) initial_trampoline = gen_rtx_MEM (BLKmode, assemble_trampoline_template ()); set_mem_align (initial_trampoline, TRAMPOLINE_ALIGNMENT); - - ggc_add_rtx_root (&initial_trampoline, 1); } #endif @@ -6866,14 +6877,14 @@ expand_function_end (filename, line, end_bindings) #ifdef TRAMPOLINE_TEMPLATE blktramp = replace_equiv_address (initial_trampoline, tramp); emit_block_move (blktramp, initial_trampoline, - GEN_INT (TRAMPOLINE_SIZE)); + GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL); #endif INITIALIZE_TRAMPOLINE (tramp, XEXP (DECL_RTL (function), 0), context); seq = get_insns (); end_sequence (); /* Put those insns at entry to the containing function (this one). */ - emit_insns_before (seq, tail_recursion_reentry); + emit_insn_before (seq, tail_recursion_reentry); } /* If we are doing stack checking and this function makes calls, @@ -6891,7 +6902,7 @@ expand_function_end (filename, line, end_bindings) GEN_INT (STACK_CHECK_MAX_FRAME_SIZE)); seq = get_insns (); end_sequence (); - emit_insns_before (seq, tail_recursion_reentry); + emit_insn_before (seq, tail_recursion_reentry); break; } } @@ -7021,13 +7032,13 @@ expand_function_end (filename, line, end_bindings) /* If this is a BLKmode structure being returned in registers, then use the mode computed in expand_return. Note that if - decl_rtl is memory, then its mode may have been changed, + decl_rtl is memory, then its mode may have been changed, but that current_function_return_rtx has not. */ if (GET_MODE (real_decl_rtl) == BLKmode) PUT_MODE (real_decl_rtl, GET_MODE (decl_rtl)); /* If a named return value dumped decl_return to memory, then - we may need to re-do the PROMOTE_MODE signed/unsigned + we may need to re-do the PROMOTE_MODE signed/unsigned extension. */ if (GET_MODE (real_decl_rtl) != GET_MODE (decl_rtl)) { @@ -7041,8 +7052,16 @@ expand_function_end (filename, line, end_bindings) convert_move (real_decl_rtl, decl_rtl, unsignedp); } else if (GET_CODE (real_decl_rtl) == PARALLEL) - emit_group_load (real_decl_rtl, decl_rtl, - int_size_in_bytes (TREE_TYPE (decl_result))); + { + /* If expand_function_start has created a PARALLEL for decl_rtl, + move the result to the real return registers. Otherwise, do + a group load from decl_rtl for a named return. */ + if (GET_CODE (decl_rtl) == PARALLEL) + emit_group_move (real_decl_rtl, decl_rtl); + else + emit_group_load (real_decl_rtl, decl_rtl, + int_size_in_bytes (TREE_TYPE (decl_result))); + } else emit_move_insn (real_decl_rtl, decl_rtl); } @@ -7094,14 +7113,14 @@ expand_function_end (filename, line, end_bindings) /* Emit the actual code to clobber return register. */ { rtx seq, after; - + start_sequence (); clobber_return_register (); - seq = gen_sequence (); + seq = get_insns (); end_sequence (); after = emit_insn_after (seq, clobber_after); - + if (clobber_after != after) cfun->x_clobber_return_insn = after; } @@ -7138,12 +7157,12 @@ get_arg_pointer_save_area (f) { rtx seq; - /* Save the arg pointer at the beginning of the function. The + /* Save the arg pointer at the beginning of the function. The generated stack slot may not be a valid memory address, so we have to check it and fix it if necessary. */ start_sequence (); emit_move_insn (validize_mem (ret), virtual_incoming_args_rtx); - seq = gen_sequence (); + seq = get_insns (); end_sequence (); push_topmost_sequence (); @@ -7154,35 +7173,38 @@ get_arg_pointer_save_area (f) return ret; } -/* Extend a vector that records the INSN_UIDs of INSNS (either a - sequence or a single insn). */ +/* Extend a vector that records the INSN_UIDs of INSNS + (a list of one or more insns). */ static void record_insns (insns, vecp) rtx insns; varray_type *vecp; { - if (GET_CODE (insns) == SEQUENCE) - { - int len = XVECLEN (insns, 0); - int i = VARRAY_SIZE (*vecp); + int i, len; + rtx tmp; - VARRAY_GROW (*vecp, i + len); - while (--len >= 0) - { - VARRAY_INT (*vecp, i) = INSN_UID (XVECEXP (insns, 0, len)); - ++i; - } + tmp = insns; + len = 0; + while (tmp != NULL_RTX) + { + len++; + tmp = NEXT_INSN (tmp); } - else + + i = VARRAY_SIZE (*vecp); + VARRAY_GROW (*vecp, i + len); + tmp = insns; + while (tmp != NULL_RTX) { - int i = VARRAY_SIZE (*vecp); - VARRAY_GROW (*vecp, i + 1); - VARRAY_INT (*vecp, i) = INSN_UID (insns); + VARRAY_INT (*vecp, i) = INSN_UID (tmp); + i++; + tmp = NEXT_INSN (tmp); } } -/* Determine how many INSN_UIDs in VEC are part of INSN. */ +/* Determine how many INSN_UIDs in VEC are part of INSN. Because we can + be running after reorg, SEQUENCE rtl is possible. */ static int contains (insn, vec) @@ -7294,20 +7316,21 @@ struct epi_info static void handle_epilogue_set PARAMS ((rtx, struct epi_info *)); static void emit_equiv_load PARAMS ((struct epi_info *)); -/* Modify SEQ, a SEQUENCE that is part of the epilogue, to no modifications - to the stack pointer. Return the new sequence. */ +/* Modify INSN, a list of one or more insns that is part of the epilogue, to + no modifications to the stack pointer. Return the new list of insns. */ static rtx -keep_stack_depressed (seq) - rtx seq; +keep_stack_depressed (insns) + rtx insns; { - int i, j; + int j; struct epi_info info; + rtx insn, next; /* If the epilogue is just a single instruction, it ust be OK as is. */ - if (GET_CODE (seq) != SEQUENCE) - return seq; + if (NEXT_INSN (insns) == NULL_RTX) + return insns; /* Otherwise, start a sequence, initialize the information we have, and process all the insns we were given. */ @@ -7317,13 +7340,16 @@ keep_stack_depressed (seq) info.sp_offset = 0; info.equiv_reg_src = 0; - for (i = 0; i < XVECLEN (seq, 0); i++) + insn = insns; + next = NULL_RTX; + while (insn != NULL_RTX) { - rtx insn = XVECEXP (seq, 0, i); + next = NEXT_INSN (insn); if (!INSN_P (insn)) { add_insn (insn); + insn = next; continue; } @@ -7359,6 +7385,7 @@ keep_stack_depressed (seq) { emit_equiv_load (&info); add_insn (insn); + insn = next; continue; } else if (GET_CODE (retaddr) == MEM @@ -7459,16 +7486,18 @@ keep_stack_depressed (seq) info.sp_equiv_reg = info.new_sp_equiv_reg; info.sp_offset = info.new_sp_offset; + + insn = next; } - seq = gen_sequence (); + insns = get_insns (); end_sequence (); - return seq; + return insns; } /* SET is a SET from an insn in the epilogue. P is a pointer to the epi_info structure that contains information about what we've seen so far. We - process this SET by either updating that data or by emitting one or + process this SET by either updating that data or by emitting one or more insns. */ static void @@ -7578,12 +7607,10 @@ thread_prologue_and_epilogue_insns (f) emit_insn (seq); /* Retain a map of the prologue insns. */ - if (GET_CODE (seq) != SEQUENCE) - seq = get_insns (); record_insns (seq, &prologue); prologue_end = emit_note (NULL, NOTE_INSN_PROLOGUE_END); - seq = gen_sequence (); + seq = get_insns (); end_sequence (); /* Can't deal with multiple successors of the entry block @@ -7674,19 +7701,8 @@ thread_prologue_and_epilogue_insns (f) that with a conditional return instruction. */ else if (condjump_p (jump)) { - rtx ret, *loc; - - ret = SET_SRC (PATTERN (jump)); - if (GET_CODE (XEXP (ret, 1)) == LABEL_REF) - loc = &XEXP (ret, 1); - else - loc = &XEXP (ret, 2); - ret = gen_rtx_RETURN (VOIDmode); - - if (! validate_change (jump, loc, ret, 0)) + if (! redirect_jump (jump, 0, 0)) continue; - if (JUMP_LABEL (jump)) - LABEL_NUSES (JUMP_LABEL (jump))--; /* If this block has only one successor, it both jumps and falls through to the fallthru block, so we can't @@ -7742,11 +7758,9 @@ thread_prologue_and_epilogue_insns (f) emit_jump_insn (seq); /* Retain a map of the epilogue insns. */ - if (GET_CODE (seq) != SEQUENCE) - seq = get_insns (); record_insns (seq, &epilogue); - seq = gen_sequence (); + seq = get_insns (); end_sequence (); insert_insn_on_edge (seq, e); @@ -7772,16 +7786,17 @@ epilogue_done: continue; start_sequence (); - seq = gen_sibcall_epilogue (); + emit_insn (gen_sibcall_epilogue ()); + seq = get_insns (); end_sequence (); + /* Retain a map of the epilogue insns. Used in life analysis to + avoid getting rid of sibcall epilogue insns. Do this before we + actually emit the sequence. */ + record_insns (seq, &sibcall_epilogue); + i = PREV_INSN (insn); newinsn = emit_insn_before (seq, insn); - - /* Retain a map of the epilogue insns. Used in life analysis to - avoid getting rid of sibcall epilogue insns. */ - record_insns (GET_CODE (seq) == SEQUENCE - ? seq : newinsn, &sibcall_epilogue); } #endif @@ -7797,7 +7812,7 @@ epilogue_done: note before the end of the first basic block, if there isn't one already there. - ??? This behaviour is completely broken when dealing with + ??? This behavior is completely broken when dealing with multiple entry functions. We simply place the note always into first basic block and let alternate entry points to be missed. @@ -7818,7 +7833,7 @@ epilogue_done: } /* Find the last line number note in the first block. */ - for (insn = BASIC_BLOCK (0)->end; + for (insn = ENTRY_BLOCK_PTR->next_bb->end; insn != prologue_end && insn; insn = PREV_INSN (insn)) if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0) @@ -7891,7 +7906,7 @@ reposition_prologue_and_epilogue_notes (f) break; } } - + if (last) { rtx next; @@ -7956,122 +7971,14 @@ reposition_prologue_and_epilogue_notes (f) #endif /* HAVE_prologue or HAVE_epilogue */ } -/* Mark P for GC. */ - -static void -mark_function_status (p) - struct function *p; -{ - struct var_refs_queue *q; - struct temp_slot *t; - int i; - rtx *r; - - if (p == 0) - return; - - ggc_mark_rtx (p->arg_offset_rtx); - - if (p->x_parm_reg_stack_loc) - for (i = p->x_max_parm_reg, r = p->x_parm_reg_stack_loc; - i > 0; --i, ++r) - ggc_mark_rtx (*r); - - ggc_mark_rtx (p->return_rtx); - ggc_mark_rtx (p->x_cleanup_label); - ggc_mark_rtx (p->x_return_label); - ggc_mark_rtx (p->x_save_expr_regs); - ggc_mark_rtx (p->x_stack_slot_list); - ggc_mark_rtx (p->x_parm_birth_insn); - ggc_mark_rtx (p->x_tail_recursion_label); - ggc_mark_rtx (p->x_tail_recursion_reentry); - ggc_mark_rtx (p->internal_arg_pointer); - ggc_mark_rtx (p->x_arg_pointer_save_area); - ggc_mark_tree (p->x_rtl_expr_chain); - ggc_mark_rtx (p->x_last_parm_insn); - ggc_mark_tree (p->x_context_display); - ggc_mark_tree (p->x_trampoline_list); - ggc_mark_rtx (p->epilogue_delay_list); - ggc_mark_rtx (p->x_clobber_return_insn); - - for (t = p->x_temp_slots; t != 0; t = t->next) - { - ggc_mark (t); - ggc_mark_rtx (t->slot); - ggc_mark_rtx (t->address); - ggc_mark_tree (t->rtl_expr); - ggc_mark_tree (t->type); - } - - for (q = p->fixup_var_refs_queue; q != 0; q = q->next) - { - ggc_mark (q); - ggc_mark_rtx (q->modified); - } - - ggc_mark_rtx (p->x_nonlocal_goto_handler_slots); - ggc_mark_rtx (p->x_nonlocal_goto_handler_labels); - ggc_mark_rtx (p->x_nonlocal_goto_stack_level); - ggc_mark_tree (p->x_nonlocal_labels); - - mark_hard_reg_initial_vals (p); -} - -/* Mark the struct function pointed to by *ARG for GC, if it is not - NULL. This is used to mark the current function and the outer - function chain. */ - -static void -maybe_mark_struct_function (arg) - void *arg; -{ - struct function *f = *(struct function **) arg; - - if (f == 0) - return; - - ggc_mark_struct_function (f); -} - -/* Mark a struct function * for GC. This is called from ggc-common.c. */ - -void -ggc_mark_struct_function (f) - struct function *f; -{ - ggc_mark (f); - ggc_mark_tree (f->decl); - - mark_function_status (f); - mark_eh_status (f->eh); - mark_stmt_status (f->stmt); - mark_expr_status (f->expr); - mark_emit_status (f->emit); - mark_varasm_status (f->varasm); - - if (mark_machine_status) - (*mark_machine_status) (f); - if (mark_lang_status) - (*mark_lang_status) (f); - - if (f->original_arg_vector) - ggc_mark_rtvec ((rtvec) f->original_arg_vector); - if (f->original_decl_initial) - ggc_mark_tree (f->original_decl_initial); - if (f->outer) - ggc_mark_struct_function (f->outer); -} - /* Called once, at initialization, to initialize function.c. */ void init_function_once () { - ggc_add_root (&cfun, 1, sizeof cfun, maybe_mark_struct_function); - ggc_add_root (&outer_function_chain, 1, sizeof outer_function_chain, - maybe_mark_struct_function); - VARRAY_INT_INIT (prologue, 0, "prologue"); VARRAY_INT_INIT (epilogue, 0, "epilogue"); VARRAY_INT_INIT (sibcall_epilogue, 0, "sibcall_epilogue"); } + +#include "gt-function.h" diff --git a/contrib/gcc/ginclude/stdarg.h b/contrib/gcc/ginclude/stdarg.h index 9f6215d..e451c31 100644 --- a/contrib/gcc/ginclude/stdarg.h +++ b/contrib/gcc/ginclude/stdarg.h @@ -47,18 +47,13 @@ typedef __builtin_va_list __gnuc_va_list; if this invocation was from the user program. */ #ifdef _STDARG_H -/* Note that the type used in va_arg is supposed to match the - actual type **after default promotions**. - Thus, va_arg (..., short) is not valid. */ - -#define va_start(v,l) __builtin_stdarg_start((v),l) -#define va_end __builtin_va_end -#define va_arg __builtin_va_arg +#define va_start(v,l) __builtin_va_start(v,l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v,l) __builtin_va_arg(v,l) #if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L -#define va_copy(d,s) __builtin_va_copy((d),(s)) +#define va_copy(d,s) __builtin_va_copy(d,s) #endif -#define __va_copy(d,s) __builtin_va_copy((d),(s)) - +#define __va_copy(d,s) __builtin_va_copy(d,s) /* Define va_list, if desired, from __gnuc_va_list. */ /* We deliberately do not define va_list when called from diff --git a/contrib/gcc/ginclude/varargs.h b/contrib/gcc/ginclude/varargs.h index 098094c..4b9803e 100644 --- a/contrib/gcc/ginclude/varargs.h +++ b/contrib/gcc/ginclude/varargs.h @@ -1,144 +1,7 @@ -/* Copyright (C) 1989, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC 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 GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, 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 - the resulting executable to be covered by the GNU General Public - License. This exception does not however invalidate any other - reasons why the executable file might be covered by the GNU General - Public License. */ - #ifndef _VARARGS_H #define _VARARGS_H -#ifdef __NeXT__ - -/* On Next, erase any vestiges of stdarg.h. */ - -#ifdef _ANSI_STDARG_H_ -#define _VA_LIST_ -#endif -#define _ANSI_STDARG_H_ - -#undef va_alist -#undef va_dcl -#undef va_list -#undef va_start -#undef va_end -#undef va_arg -#endif /* __NeXT__ */ - -/* These macros implement traditional (non-ANSI) varargs - for GNU C. */ - -#define va_alist __builtin_va_alist - -/* ??? We don't process attributes correctly in K&R argument context. */ -typedef int __builtin_va_alist_t __attribute__((__mode__(__word__))); - -/* ??? It would be nice to get rid of the ellipsis here. It causes - current_function_varargs to be set in cc1. */ -#define va_dcl __builtin_va_alist_t __builtin_va_alist; ... - -/* Define __gnuc_va_list, just as in stdarg.h. */ - -#ifndef __GNUC_VA_LIST -#define __GNUC_VA_LIST -typedef __builtin_va_list __gnuc_va_list; -#endif - -#define va_start(v) __builtin_varargs_start((v)) -#define va_end __builtin_va_end -#define va_arg __builtin_va_arg -#define __va_copy(d,s) __builtin_va_copy((d),(s)) - -/* Define va_list from __gnuc_va_list. */ +#error "GCC no longer implements <varargs.h>." +#error "Revise your code to use <stdarg.h>." -#ifdef _HIDDEN_VA_LIST /* On OSF1, this means varargs.h is "half-loaded". */ -#undef _VA_LIST -#endif - -#if defined(__svr4__) || (defined(_SCO_DS) && !defined(__VA_LIST)) -/* SVR4.2 uses _VA_LIST for an internal alias for va_list, - so we must avoid testing it and setting it here. - SVR4 uses _VA_LIST as a flag in stdarg.h, but we should - have no conflict with that. */ -#ifndef _VA_LIST_ -#define _VA_LIST_ -#ifdef __i860__ -#ifndef _VA_LIST -#define _VA_LIST va_list -#endif -#endif /* __i860__ */ -typedef __gnuc_va_list va_list; -#ifdef _SCO_DS -#define __VA_LIST -#endif -#endif /* _VA_LIST_ */ - -#else /* not __svr4__ || _SCO_DS */ - -/* The macro _VA_LIST_ is the same thing used by this file in Ultrix. - But on BSD NET2 we must not test or define or undef it. - (Note that the comments in NET 2's ansi.h - are incorrect for _VA_LIST_--see stdio.h!) */ -/* Michael Eriksson <mer@sics.se> at Thu Sep 30 11:00:57 1993: - Sequent defines _VA_LIST_ in <machine/machtypes.h> to be the type to - use for va_list (``typedef _VA_LIST_ va_list'') */ -#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT) -/* The macro _VA_LIST_DEFINED is used in Windows NT 3.5 */ -#ifndef _VA_LIST_DEFINED -/* The macro _VA_LIST is used in SCO Unix 3.2. */ -#ifndef _VA_LIST -/* The macro _VA_LIST_T_H is used in the Bull dpx2 */ -#ifndef _VA_LIST_T_H -/* The macro __va_list__ is used by BeOS. */ -#ifndef __va_list__ -typedef __gnuc_va_list va_list; -#endif /* not __va_list__ */ -#endif /* not _VA_LIST_T_H */ -#endif /* not _VA_LIST */ -#endif /* not _VA_LIST_DEFINED */ -#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__)) -#define _VA_LIST_ -#endif -#ifndef _VA_LIST -#define _VA_LIST #endif -#ifndef _VA_LIST_DEFINED -#define _VA_LIST_DEFINED -#endif -#ifndef _VA_LIST_T_H -#define _VA_LIST_T_H -#endif -#ifndef __va_list__ -#define __va_list__ -#endif - -#endif /* not _VA_LIST_, except on certain systems */ - -#endif /* not __svr4__ */ - -/* The next BSD release (if there is one) wants this symbol to be - undefined instead of _VA_LIST_. */ -#ifdef _BSD_VA_LIST -#undef _BSD_VA_LIST -#endif - -#endif /* _VARARGS_H */ diff --git a/contrib/gcc/libgcc2.c b/contrib/gcc/libgcc2.c index dd5eee7..dea803d 100644 --- a/contrib/gcc/libgcc2.c +++ b/contrib/gcc/libgcc2.c @@ -43,10 +43,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "libgcc2.h" -#if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3) -#if defined (L_divdi3) || defined (L_moddi3) -static inline +#ifdef DECLARE_LIBRARY_RENAMES + DECLARE_LIBRARY_RENAMES #endif + +#if defined (L_negdi2) DWtype __negdi2 (DWtype u) { @@ -149,9 +150,9 @@ __mulvsi3 (Wtype a, Wtype b) Wtype __negvsi2 (Wtype a) { - Wtype w; + Wtype w; - w = -a; + w = -a; if (a >= 0 ? w > 0 : w < 0) abort (); @@ -164,14 +165,14 @@ __negvsi2 (Wtype a) DWtype __negvdi2 (DWtype a) { - DWtype w; + DWtype w; - w = -a; + w = -a; if (a >= 0 ? w > 0 : w < 0) abort (); - return w; + return w; } #endif @@ -179,16 +180,16 @@ __negvdi2 (DWtype a) Wtype __absvsi2 (Wtype a) { - Wtype w = a; + Wtype w = a; - if (a < 0) + if (a < 0) #ifdef L_negvsi2 - w = __negvsi2 (a); + w = __negvsi2 (a); #else - w = -a; + w = -a; - if (w < 0) - abort (); + if (w < 0) + abort (); #endif return w; @@ -199,19 +200,19 @@ __absvsi2 (Wtype a) DWtype __absvdi2 (DWtype a) { - DWtype w = a; + DWtype w = a; - if (a < 0) + if (a < 0) #ifdef L_negvsi2 - w = __negvsi2 (a); + w = __negvsi2 (a); #else - w = -a; + w = -a; - if (w < 0) - abort (); + if (w < 0) + abort (); #endif - return w; + return w; } #endif @@ -219,7 +220,7 @@ __absvdi2 (DWtype a) DWtype __mulvdi3 (DWtype u, DWtype v) { - DWtype w; + DWtype w; w = u * v; @@ -365,8 +366,19 @@ __muldi3 (DWtype u, DWtype v) } #endif +#if (defined (L_udivdi3) || defined (L_divdi3) || \ + defined (L_umoddi3) || defined (L_moddi3)) +#if defined (sdiv_qrnnd) +#define L_udiv_w_sdiv +#endif +#endif + #ifdef L_udiv_w_sdiv #if defined (sdiv_qrnnd) +#if (defined (L_udivdi3) || defined (L_divdi3) || \ + defined (L_umoddi3) || defined (L_moddi3)) +static inline __attribute__ ((__always_inline__)) +#endif UWtype __udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d) { @@ -499,7 +511,7 @@ const UQItype __clz_tab[] = #if (defined (L_udivdi3) || defined (L_divdi3) || \ defined (L_umoddi3) || defined (L_moddi3)) -static inline +static inline __attribute__ ((__always_inline__)) #endif UDWtype __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp) @@ -732,14 +744,14 @@ __divdi3 (DWtype u, DWtype v) if (uu.s.high < 0) c = ~c, - uu.ll = __negdi2 (uu.ll); + uu.ll = -uu.ll; if (vv.s.high < 0) c = ~c, - vv.ll = __negdi2 (vv.ll); + vv.ll = -vv.ll; w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0); if (c) - w = __negdi2 (w); + w = -w; return w; } @@ -758,13 +770,13 @@ __moddi3 (DWtype u, DWtype v) if (uu.s.high < 0) c = ~c, - uu.ll = __negdi2 (uu.ll); + uu.ll = -uu.ll; if (vv.s.high < 0) - vv.ll = __negdi2 (vv.ll); + vv.ll = -vv.ll; (void) __udivmoddi4 (uu.ll, vv.ll, &w); if (c) - w = __negdi2 (w); + w = -w; return w; } @@ -1063,35 +1075,10 @@ __floatdidf (DWtype u) #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) -#define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT) - -/* Define codes for all the float formats that we know of. Note - that this is copied from real.h. */ - -#define UNKNOWN_FLOAT_FORMAT 0 -#define IEEE_FLOAT_FORMAT 1 -#define VAX_FLOAT_FORMAT 2 -#define IBM_FLOAT_FORMAT 3 - -/* Default to IEEE float if not specified. Nearly all machines use it. */ -#ifndef HOST_FLOAT_FORMAT -#define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT -#endif -#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT -#define DF_SIZE 53 -#define SF_SIZE 24 -#endif - -#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT -#define DF_SIZE 56 -#define SF_SIZE 24 -#endif - -#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT -#define DF_SIZE 56 -#define SF_SIZE 24 -#endif +#define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT) +#define DF_SIZE DBL_MANT_DIG +#define SF_SIZE FLT_MANT_DIG SFtype __floatdisf (DWtype u) @@ -1264,14 +1251,13 @@ __eprintf (const char *string, const char *expression, #ifdef L_bb -#if LONG_TYPE_SIZE == GCOV_TYPE_SIZE -typedef long gcov_type; -#else -typedef long long gcov_type; -#endif - +struct bb_function_info { + long checksum; + int arc_count; + const char *name; +}; -/* Structure emitted by -a */ +/* Structure emitted by --profile-arcs */ struct bb { long zero_word; @@ -1279,26 +1265,19 @@ struct bb gcov_type *counts; long ncounts; struct bb *next; - const unsigned long *addresses; /* Older GCC's did not emit these fields. */ - long nwords; - const char **functions; - const long *line_nums; - const char **filenames; - char *flags; + long sizeof_bb; + struct bb_function_info *function_infos; }; #ifndef inhibit_libc -/* Simple minded basic block profiling output dumper for - systems that don't provide tcov support. At present, - it requires atexit and stdio. */ +/* Arc profile dumper. Requires atexit and stdio. */ #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ #include <stdio.h> -#include "gbl-ctors.h" #include "gcov-io.h" #include <string.h> #ifdef TARGET_HAS_F_SETLKW @@ -1306,162 +1285,272 @@ struct bb #include <errno.h> #endif +/* Chain of per-object file bb structures. */ static struct bb *bb_head; +/* Dump the coverage counts. We merge with existing counts when + possible, to avoid growing the .da files ad infinitum. */ + void __bb_exit_func (void) { - FILE *da_file; - int i; struct bb *ptr; + int i; + gcov_type program_sum = 0; + gcov_type program_max = 0; + long program_arcs = 0; + gcov_type merged_sum = 0; + gcov_type merged_max = 0; + long merged_arcs = 0; + +#if defined (TARGET_HAS_F_SETLKW) + struct flock s_flock; - if (bb_head == 0) - return; - - i = strlen (bb_head->filename) - 3; - + s_flock.l_type = F_WRLCK; + s_flock.l_whence = SEEK_SET; + s_flock.l_start = 0; + s_flock.l_len = 0; /* Until EOF. */ + s_flock.l_pid = getpid (); +#endif - for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next) + /* Non-merged stats for this program. */ + for (ptr = bb_head; ptr; ptr = ptr->next) { - int firstchar; - - /* Make sure the output file exists - - but don't clobber exiting data. */ - if ((da_file = fopen (ptr->filename, "a")) != 0) - fclose (da_file); + for (i = 0; i < ptr->ncounts; i++) + { + program_sum += ptr->counts[i]; - /* Need to re-open in order to be able to write from the start. */ + if (ptr->counts[i] > program_max) + program_max = ptr->counts[i]; + } + program_arcs += ptr->ncounts; + } + + for (ptr = bb_head; ptr; ptr = ptr->next) + { + FILE *da_file; + gcov_type object_max = 0; + gcov_type object_sum = 0; + long object_functions = 0; + int merging = 0; + int error = 0; + struct bb_function_info *fn_info; + gcov_type *count_ptr; + + /* Open for modification */ da_file = fopen (ptr->filename, "r+b"); - /* Some old systems might not allow the 'b' mode modifier. - Therefore, try to open without it. This can lead to a race - condition so that when you delete and re-create the file, the - file might be opened in text mode, but then, you shouldn't - delete the file in the first place. */ - if (da_file == 0) - da_file = fopen (ptr->filename, "r+"); - if (da_file == 0) + + if (da_file) + merging = 1; + else + { + /* Try for appending */ + da_file = fopen (ptr->filename, "ab"); + /* Some old systems might not allow the 'b' mode modifier. + Therefore, try to open without it. This can lead to a + race condition so that when you delete and re-create the + file, the file might be opened in text mode, but then, + you shouldn't delete the file in the first place. */ + if (!da_file) + da_file = fopen (ptr->filename, "a"); + } + + if (!da_file) { fprintf (stderr, "arc profiling: Can't open output file %s.\n", ptr->filename); + ptr->filename = 0; continue; } +#if defined (TARGET_HAS_F_SETLKW) /* After a fork, another process might try to read and/or write the same file simultanously. So if we can, lock the file to avoid race conditions. */ -#if defined (TARGET_HAS_F_SETLKW) - { - struct flock s_flock; - - s_flock.l_type = F_WRLCK; - s_flock.l_whence = SEEK_SET; - s_flock.l_start = 0; - s_flock.l_len = 1; - s_flock.l_pid = getpid (); - - while (fcntl (fileno (da_file), F_SETLKW, &s_flock) - && errno == EINTR); - } + while (fcntl (fileno (da_file), F_SETLKW, &s_flock) + && errno == EINTR) + continue; #endif + for (fn_info = ptr->function_infos; fn_info->arc_count != -1; fn_info++) + object_functions++; - /* If the file is not empty, and the number of counts in it is the - same, then merge them in. */ - firstchar = fgetc (da_file); - if (firstchar == EOF) + if (merging) { - if (ferror (da_file)) + /* Merge data from file. */ + long tmp_long; + gcov_type tmp_gcov; + + if (/* magic */ + (__read_long (&tmp_long, da_file, 4) || tmp_long != -123l) + /* functions in object file. */ + || (__read_long (&tmp_long, da_file, 4) + || tmp_long != object_functions) + /* extension block, skipped */ + || (__read_long (&tmp_long, da_file, 4) + || fseek (da_file, tmp_long, SEEK_CUR))) { - fprintf (stderr, "arc profiling: Can't read output file "); - perror (ptr->filename); - } - } - else - { - long n_counts = 0; - - if (ungetc (firstchar, da_file) == EOF) - rewind (da_file); - if (__read_long (&n_counts, da_file, 8) != 0) - { - fprintf (stderr, "arc profiling: Can't read output file %s.\n", + read_error:; + fprintf (stderr, "arc profiling: Error merging output file %s.\n", ptr->filename); - continue; + clearerr (da_file); } - - if (n_counts == ptr->ncounts) + else { - int i; - - for (i = 0; i < n_counts; i++) + /* Merge execution counts for each function. */ + count_ptr = ptr->counts; + + for (fn_info = ptr->function_infos; fn_info->arc_count != -1; + fn_info++) { - gcov_type v = 0; - - if (__read_gcov_type (&v, da_file, 8) != 0) - { - fprintf (stderr, - "arc profiling: Can't read output file %s.\n", - ptr->filename); - break; - } - ptr->counts[i] += v; + if (/* function name delim */ + (__read_long (&tmp_long, da_file, 4) + || tmp_long != -1) + /* function name length */ + || (__read_long (&tmp_long, da_file, 4) + || tmp_long != (long) strlen (fn_info->name)) + /* skip string */ + || fseek (da_file, ((tmp_long + 1) + 3) & ~3, SEEK_CUR) + /* function name delim */ + || (__read_long (&tmp_long, da_file, 4) + || tmp_long != -1)) + goto read_error; + + if (/* function checksum */ + (__read_long (&tmp_long, da_file, 4) + || tmp_long != fn_info->checksum) + /* arc count */ + || (__read_long (&tmp_long, da_file, 4) + || tmp_long != fn_info->arc_count)) + goto read_error; + + for (i = fn_info->arc_count; i > 0; i--, count_ptr++) + if (__read_gcov_type (&tmp_gcov, da_file, 8)) + goto read_error; + else + *count_ptr += tmp_gcov; } } - + fseek (da_file, 0, SEEK_SET); } - - rewind (da_file); - - /* ??? Should first write a header to the file. Preferably, a 4 byte - magic number, 4 bytes containing the time the program was - compiled, 4 bytes containing the last modification time of the - source file, and 4 bytes indicating the compiler options used. - - That way we can easily verify that the proper source/executable/ - data file combination is being used from gcov. */ - - if (__write_gcov_type (ptr->ncounts, da_file, 8) != 0) + + /* Calculate the per-object statistics. */ + for (i = 0; i < ptr->ncounts; i++) { + object_sum += ptr->counts[i]; + if (ptr->counts[i] > object_max) + object_max = ptr->counts[i]; + } + merged_sum += object_sum; + if (merged_max < object_max) + merged_max = object_max; + merged_arcs += ptr->ncounts; + + /* Write out the data. */ + if (/* magic */ + __write_long (-123, da_file, 4) + /* number of functions in object file. */ + || __write_long (object_functions, da_file, 4) + /* length of extra data in bytes. */ + || __write_long ((4 + 8 + 8) + (4 + 8 + 8), da_file, 4) + + /* whole program statistics. If merging write per-object + now, rewrite later */ + /* number of instrumented arcs. */ + || __write_long (merging ? ptr->ncounts : program_arcs, da_file, 4) + /* sum of counters. */ + || __write_gcov_type (merging ? object_sum : program_sum, da_file, 8) + /* maximal counter. */ + || __write_gcov_type (merging ? object_max : program_max, da_file, 8) + + /* per-object statistics. */ + /* number of counters. */ + || __write_long (ptr->ncounts, da_file, 4) + /* sum of counters. */ + || __write_gcov_type (object_sum, da_file, 8) + /* maximal counter. */ + || __write_gcov_type (object_max, da_file, 8)) + { + write_error:; fprintf (stderr, "arc profiling: Error writing output file %s.\n", ptr->filename); + error = 1; } else { - int j; - gcov_type *count_ptr = ptr->counts; - int ret = 0; - for (j = ptr->ncounts; j > 0; j--) + /* Write execution counts for each function. */ + count_ptr = ptr->counts; + + for (fn_info = ptr->function_infos; fn_info->arc_count != -1; + fn_info++) { - if (__write_gcov_type (*count_ptr, da_file, 8) != 0) - { - ret = 1; - break; - } - count_ptr++; + if (__write_gcov_string (fn_info->name, + strlen (fn_info->name), da_file, -1) + || __write_long (fn_info->checksum, da_file, 4) + || __write_long (fn_info->arc_count, da_file, 4)) + goto write_error; + + for (i = fn_info->arc_count; i > 0; i--, count_ptr++) + if (__write_gcov_type (*count_ptr, da_file, 8)) + goto write_error; /* RIP Edsger Dijkstra */ } - if (ret) - fprintf (stderr, "arc profiling: Error writing output file %s.\n", - ptr->filename); } - if (fclose (da_file) == EOF) - fprintf (stderr, "arc profiling: Error closing output file %s.\n", - ptr->filename); + if (fclose (da_file)) + { + fprintf (stderr, "arc profiling: Error closing output file %s.\n", + ptr->filename); + error = 1; + } + if (error || !merging) + ptr->filename = 0; } - return; + /* Upate whole program statistics. */ + for (ptr = bb_head; ptr; ptr = ptr->next) + if (ptr->filename) + { + FILE *da_file; + + da_file = fopen (ptr->filename, "r+b"); + if (!da_file) + { + fprintf (stderr, "arc profiling: Cannot reopen %s.\n", + ptr->filename); + continue; + } + +#if defined (TARGET_HAS_F_SETLKW) + while (fcntl (fileno (da_file), F_SETLKW, &s_flock) + && errno == EINTR) + continue; +#endif + + if (fseek (da_file, 4 * 3, SEEK_SET) + /* number of instrumented arcs. */ + || __write_long (merged_arcs, da_file, 4) + /* sum of counters. */ + || __write_gcov_type (merged_sum, da_file, 8) + /* maximal counter. */ + || __write_gcov_type (merged_max, da_file, 8)) + fprintf (stderr, "arc profiling: Error updating program header %s.\n", + ptr->filename); + if (fclose (da_file)) + fprintf (stderr, "arc profiling: Error reclosing %s\n", + ptr->filename); + } } +/* Add a new object file onto the bb chain. Invoked automatically + when running an object file's global ctors. */ + void __bb_init_func (struct bb *blocks) { - /* User is supposed to check whether the first word is non-0, - but just in case.... */ - if (blocks->zero_word) return; - /* Initialize destructor. */ + /* Initialize destructor and per-thread data. */ if (!bb_head) atexit (__bb_exit_func); @@ -1474,6 +1563,7 @@ __bb_init_func (struct bb *blocks) /* Called before fork or exec - write out profile information gathered so far and reset it to zero. This avoids duplication or loss of the profile information gathered so far. */ + void __bb_fork_func (void) { @@ -1656,102 +1746,6 @@ mprotect (char *addr, int len, int prot) TRANSFER_FROM_TRAMPOLINE #endif -#if defined (NeXT) && defined (__MACH__) - -/* Make stack executable so we can call trampolines on stack. - This is called from INITIALIZE_TRAMPOLINE in next.h. */ -#ifdef NeXTStep21 - #include <mach.h> -#else - #include <mach/mach.h> -#endif - -void -__enable_execute_stack (char *addr) -{ - kern_return_t r; - char *eaddr = addr + TRAMPOLINE_SIZE; - vm_address_t a = (vm_address_t) addr; - - /* turn on execute access on stack */ - r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL); - if (r != KERN_SUCCESS) - { - mach_error("vm_protect VM_PROT_ALL", r); - exit(1); - } - - /* We inline the i-cache invalidation for speed */ - -#ifdef CLEAR_INSN_CACHE - CLEAR_INSN_CACHE (addr, eaddr); -#else - __clear_cache ((int) addr, (int) eaddr); -#endif -} - -#endif /* defined (NeXT) && defined (__MACH__) */ - -#ifdef __convex__ - -/* Make stack executable so we can call trampolines on stack. - This is called from INITIALIZE_TRAMPOLINE in convex.h. */ - -#include <sys/mman.h> -#include <sys/vmparam.h> -#include <machine/machparam.h> - -void -__enable_execute_stack (void) -{ - int fp; - static unsigned lowest = USRSTACK; - unsigned current = (unsigned) &fp & -NBPG; - - if (lowest > current) - { - unsigned len = lowest - current; - mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE); - lowest = current; - } - - /* Clear instruction cache in case an old trampoline is in it. */ - asm ("pich"); -} -#endif /* __convex__ */ - -#ifdef __sysV88__ - -/* Modified from the convex -code above. */ - -#include <sys/param.h> -#include <errno.h> -#include <sys/m88kbcs.h> - -void -__enable_execute_stack (void) -{ - int save_errno; - static unsigned long lowest = USRSTACK; - unsigned long current = (unsigned long) &save_errno & -NBPC; - - /* Ignore errno being set. memctl sets errno to EINVAL whenever the - address is seen as 'negative'. That is the case with the stack. */ - - save_errno=errno; - if (lowest > current) - { - unsigned len=lowest-current; - memctl(current,len,MCT_TEXT); - lowest = current; - } - else - memctl(current,NBPC,MCT_TEXT); - errno=save_errno; -} - -#endif /* __sysV88__ */ - #ifdef __sysV68__ #include <sys/signal.h> @@ -1796,57 +1790,6 @@ __clear_insn_cache (void) } #endif /* __sysV68__ */ - -#ifdef __pyr__ - -#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ -#include <stdio.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/vmmac.h> - -/* Modified from the convex -code above. - mremap promises to clear the i-cache. */ - -void -__enable_execute_stack (void) -{ - int fp; - if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ, - PROT_READ|PROT_WRITE|PROT_EXEC)) - { - perror ("mprotect in __enable_execute_stack"); - fflush (stderr); - abort (); - } -} -#endif /* __pyr__ */ - -#if defined (sony_news) && defined (SYSTYPE_BSD) - -#include <stdio.h> -#include <sys/types.h> -#include <sys/param.h> -#include <syscall.h> -#include <machine/sysnews.h> - -/* cacheflush function for NEWS-OS 4.2. - This function is called from trampoline-initialize code - defined in config/mips/mips.h. */ - -void -cacheflush (char *beg, int size, int flag) -{ - if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE)) - { - perror ("cache_flush"); - fflush (stderr); - abort (); - } -} - -#endif /* sony_news */ #endif /* L_trampoline */ #ifndef __CYGWIN__ diff --git a/contrib/gcc/print-tree.c b/contrib/gcc/print-tree.c index f535373..05ca52b 100644 --- a/contrib/gcc/print-tree.c +++ b/contrib/gcc/print-tree.c @@ -23,6 +23,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "config.h" #include "system.h" #include "tree.h" +#include "real.h" #include "ggc.h" #include "langhooks.h" @@ -47,8 +48,7 @@ void debug_tree (node) tree node; { - table = (struct bucket **) permalloc (HASH_SIZE * sizeof (struct bucket *)); - memset ((char *) table, 0, HASH_SIZE * sizeof (struct bucket *)); + table = (struct bucket **) xcalloc (HASH_SIZE, sizeof (struct bucket *)); print_node (stderr, "", node, 0); table = 0; fprintf (stderr, "\n"); @@ -124,7 +124,6 @@ print_node_brief (file, prefix, node, indent) if (TREE_OVERFLOW (node)) fprintf (file, " overflow"); -#if !defined(REAL_IS_NOT_DOUBLE) || defined(REAL_ARITHMETIC) d = TREE_REAL_CST (node); if (REAL_VALUE_ISINF (d)) fprintf (file, " Inf"); @@ -132,21 +131,10 @@ print_node_brief (file, prefix, node, indent) fprintf (file, " Nan"); else { - char string[100]; - - REAL_VALUE_TO_DECIMAL (d, "%e", string); + char string[60]; + real_to_decimal (string, &d, sizeof (string), 0, 1); fprintf (file, " %s", string); } -#else - { - int i; - unsigned char *p = (unsigned char *) &TREE_REAL_CST (node); - fprintf (file, " 0x"); - for (i = 0; i < sizeof TREE_REAL_CST (node); i++) - fprintf (file, "%02x", *p++); - fprintf (file, ""); - } -#endif } fprintf (file, ">"); @@ -223,7 +211,7 @@ print_node (file, prefix, node, indent) } /* Add this node to the table. */ - b = (struct bucket *) permalloc (sizeof (struct bucket)); + b = (struct bucket *) xmalloc (sizeof (struct bucket)); b->node = node; b->next = table[hash]; table[hash] = b; @@ -340,7 +328,9 @@ print_node (file, prefix, node, indent) if (TREE_CODE (node) == TYPE_DECL && TYPE_DECL_SUPPRESS_DEBUG (node)) fputs (" suppress-debug", file); - if (TREE_CODE (node) == FUNCTION_DECL && DECL_INLINE (node)) + if (TREE_CODE (node) == FUNCTION_DECL && DID_INLINE_FUNC (node)) + fputs (" autoinline", file); + else if (TREE_CODE (node) == FUNCTION_DECL && DECL_INLINE (node)) fputs (" inline", file); if (TREE_CODE (node) == FUNCTION_DECL && DECL_BUILT_IN (node)) fputs (" built-in", file); @@ -363,6 +353,8 @@ print_node (file, prefix, node, indent) 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) == PARM_DECL && DECL_TRANSPARENT_UNION (node)) fputs (" transparent-union", file); @@ -395,7 +387,7 @@ print_node (file, prefix, node, indent) 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); @@ -426,7 +418,7 @@ print_node (file, prefix, node, indent) if (DECL_POINTER_ALIAS_SET_KNOWN_P (node)) { fprintf (file, " alias set "); - fprintf (file, HOST_WIDE_INT_PRINT_DEC, + fprintf (file, HOST_WIDE_INT_PRINT_DEC, DECL_POINTER_ALIAS_SET (node)); } @@ -517,6 +509,9 @@ print_node (file, prefix, node, indent) if (TYPE_PACKED (node)) fputs (" packed", file); + if (TYPE_RESTRICT (node)) + fputs (" restrict", file); + if (TYPE_LANG_FLAG_0 (node)) fputs (" type_0", file); if (TYPE_LANG_FLAG_1 (node)) @@ -644,7 +639,7 @@ print_node (file, prefix, node, indent) if (TREE_CODE (node) == EXPR_WITH_FILE_LOCATION) { indent_to (file, indent+4); - fprintf (file, "%s:%d:%d", + 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)); @@ -683,7 +678,6 @@ print_node (file, prefix, node, indent) if (TREE_OVERFLOW (node)) fprintf (file, " overflow"); -#if !defined(REAL_IS_NOT_DOUBLE) || defined(REAL_ARITHMETIC) d = TREE_REAL_CST (node); if (REAL_VALUE_ISINF (d)) fprintf (file, " Inf"); @@ -691,21 +685,10 @@ print_node (file, prefix, node, indent) fprintf (file, " Nan"); else { - char string[100]; - - REAL_VALUE_TO_DECIMAL (d, "%e", string); + char string[64]; + real_to_decimal (string, &d, sizeof (string), 0, 1); fprintf (file, " %s", string); } -#else - { - int i; - unsigned char *p = (unsigned char *) &TREE_REAL_CST (node); - fprintf (file, " 0x"); - for (i = 0; i < sizeof TREE_REAL_CST (node); i++) - fprintf (file, "%02x", *p++); - fprintf (file, ""); - } -#endif } break; @@ -731,7 +714,20 @@ print_node (file, prefix, node, indent) break; case STRING_CST: - fprintf (file, " \"%s\"", TREE_STRING_POINTER (node)); + { + const char *p = TREE_STRING_POINTER (node); + int i = TREE_STRING_LENGTH (node); + fputs (" \"", file); + while (--i >= 0) + { + char ch = *p++; + if (ch >= ' ' && ch < 127) + putc (ch, file); + else + fprintf(file, "\\%03o", ch & 0xFF); + } + fputc ('\"', file); + } /* Print the chain at second level. */ if (indent == 4) print_node (file, "chain", TREE_CHAIN (node), indent + 4); diff --git a/contrib/gcc/recog.c b/contrib/gcc/recog.c index 41193db..bd42a5b 100644 --- a/contrib/gcc/recog.c +++ b/contrib/gcc/recog.c @@ -161,7 +161,7 @@ check_asm_operands (x) c = constraints[c[0] - '0']; if (! asm_operand_ok (operands[i], c)) - return 0; + return 0; } return 1; @@ -191,7 +191,7 @@ static int num_changes = 0; an INSN, CALL_INSN, or JUMP_INSN, the insn will be re-recognized with the change in place. - IN_GROUP is non-zero if this is part of a group of changes that must be + IN_GROUP is nonzero if this is part of a group of changes that must be performed as a group. In that case, the changes will be stored. The function `apply_change_group' will validate and apply the changes. @@ -227,11 +227,11 @@ validate_change (object, loc, new, in_group) else changes_allocated *= 2; - changes = - (change_t*) xrealloc (changes, - sizeof (change_t) * changes_allocated); + changes = + (change_t*) xrealloc (changes, + sizeof (change_t) * changes_allocated); } - + changes[num_changes].object = object; changes[num_changes].loc = loc; changes[num_changes].old = old; @@ -272,7 +272,7 @@ insn_invalid_p (insn) ? &num_clobbers : 0); int is_asm = icode < 0 && asm_noperands (PATTERN (insn)) >= 0; - + /* If this is an asm and the operand aren't legal, then fail. Likewise if this is not an asm and the insn wasn't recognized. */ if ((is_asm && ! check_asm_operands (PATTERN (insn))) @@ -308,6 +308,13 @@ insn_invalid_p (insn) return 0; } +/* Return number of changes made and not validated yet. */ +int +num_changes_pending () +{ + return num_changes; +} + /* Apply a group of changes previously issued with `validate_change'. Return 1 if all changes are valid, zero otherwise. */ @@ -362,7 +369,7 @@ apply_change_group () int j; newpat - = gen_rtx_PARALLEL (VOIDmode, + = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (XVECLEN (pat, 0) - 1)); for (j = 0; j < XVECLEN (newpat, 0); j++) XVECEXP (newpat, 0, j) = XVECEXP (pat, 0, j); @@ -392,6 +399,14 @@ apply_change_group () if (i == num_changes) { + 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; return 1; } @@ -663,11 +678,10 @@ validate_replace_src_1 (x, data) } /* Try replacing every occurrence of FROM in INSN with TO, avoiding - SET_DESTs. After all changes have been made, validate by seeing if - INSN is still valid. */ + SET_DESTs. */ -int -validate_replace_src (from, to, insn) +void +validate_replace_src_group (from, to, insn) rtx from, to, insn; { struct validate_replace_src_data d; @@ -676,6 +690,15 @@ validate_replace_src (from, to, insn) d.to = to; d.insn = insn; note_uses (&PATTERN (insn), validate_replace_src_1, &d); +} + +/* Same as validate_repalace_src_group, but validate by seeing if + INSN is still valid. */ +int +validate_replace_src (from, to, insn) + rtx from, to, insn; +{ + validate_replace_src_group (from, to, insn); return apply_change_group (); } @@ -778,7 +801,7 @@ find_single_use_1 (dest, loc) case MEM: case SUBREG: return find_single_use_1 (dest, &XEXP (x, 0)); - + default: break; } @@ -833,7 +856,7 @@ find_single_use_1 (dest, loc) sequel. If so, return a pointer to the innermost rtx expression in which it is used. - If PLOC is non-zero, *PLOC is set to the insn containing the single use. + If PLOC is nonzero, *PLOC is set to the insn containing the single use. This routine will return usually zero either before flow is called (because there will be no LOG_LINKS notes) or after reload (because the REG_DEAD @@ -931,6 +954,7 @@ general_operand (op, mode) return 0; if (GET_CODE (op) == CONST_INT + && mode != VOIDmode && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) return 0; @@ -962,15 +986,15 @@ general_operand (op, mode) /* Avoid memories with nonzero SUBREG_BYTE, as offsetting the memory may result in incorrect reference. We should simplify all valid subregs of MEM anyway. But allow this after reload because we - might be called from cleanup_subreg_operands. + might be called from cleanup_subreg_operands. ??? This is a kludge. */ if (!reload_completed && SUBREG_BYTE (op) != 0 && GET_CODE (sub) == MEM) - return 0; + return 0; /* FLOAT_MODE subregs can't be paradoxical. Combine will occasionally - create such rtl, and we must reject it. */ + create such rtl, and we must reject it. */ if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT && GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub))) return 0; @@ -1059,13 +1083,10 @@ register_operand (op, mode) if (! reload_completed && GET_CODE (sub) == MEM) return general_operand (op, mode); -#ifdef CLASS_CANNOT_CHANGE_MODE +#ifdef CANNOT_CHANGE_MODE_CLASS if (GET_CODE (sub) == REG && REGNO (sub) < FIRST_PSEUDO_REGISTER - && (TEST_HARD_REG_BIT - (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE], - REGNO (sub))) - && CLASS_CANNOT_CHANGE_MODE_P (mode, GET_MODE (sub)) + && REG_CANNOT_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub), mode) && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT) return 0; @@ -1136,6 +1157,7 @@ immediate_operand (op, mode) return 0; if (GET_CODE (op) == CONST_INT + && mode != VOIDmode && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) return 0; @@ -1218,6 +1240,7 @@ nonmemory_operand (op, mode) return 0; if (GET_CODE (op) == CONST_INT + && mode != VOIDmode && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) return 0; @@ -1334,7 +1357,7 @@ memory_address_p (mode, addr) { if (GET_CODE (addr) == ADDRESSOF) return 1; - + GO_IF_LEGITIMATE_ADDRESS (mode, addr, win); return 0; @@ -1588,7 +1611,7 @@ decode_asm_operands (body, operands, operand_locs, constraints, modes) { if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER) break; /* Past last SET */ - + if (operands) operands[i] = SET_DEST (XVECEXP (body, 0, i)); if (operand_locs) @@ -1640,7 +1663,7 @@ decode_asm_operands (body, operands, operand_locs, constraints, modes) return template; } -/* Check if an asm_operand matches it's constraints. +/* Check if an asm_operand matches it's constraints. Return > 0 if ok, = 0 if bad, < 0 if inconclusive. */ int @@ -1708,7 +1731,7 @@ asm_operand_ok (op, constraint) if (GET_CODE (op) == MEM && (1 || GET_CODE (XEXP (op, 0)) == PRE_DEC - || GET_CODE (XEXP (op, 0)) == POST_DEC)) + || GET_CODE (XEXP (op, 0)) == POST_DEC)) return 1; break; @@ -1716,23 +1739,15 @@ asm_operand_ok (op, constraint) if (GET_CODE (op) == MEM && (1 || GET_CODE (XEXP (op, 0)) == PRE_INC - || GET_CODE (XEXP (op, 0)) == POST_INC)) + || GET_CODE (XEXP (op, 0)) == POST_INC)) return 1; break; case 'E': -#ifndef REAL_ARITHMETIC - /* Match any floating double constant, but only if - we can examine the bits of it reliably. */ - if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT - || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD) - && GET_MODE (op) != VOIDmode && ! flag_pretend_float) - break; -#endif - /* FALLTHRU */ - case 'F': - if (GET_CODE (op) == CONST_DOUBLE) + if (GET_CODE (op) == CONST_DOUBLE + || (GET_CODE (op) == CONST_VECTOR + && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT)) return 1; break; @@ -1833,6 +1848,18 @@ asm_operand_ok (op, constraint) #ifdef EXTRA_CONSTRAINT if (EXTRA_CONSTRAINT (op, c)) return 1; + if (EXTRA_MEMORY_CONSTRAINT (c)) + { + /* Every memory operand can be reloaded to fit. */ + if (memory_operand (op, VOIDmode)) + return 1; + } + if (EXTRA_ADDRESS_CONSTRAINT (c)) + { + /* Every address operand can be reloaded to fit. */ + if (address_operand (op, VOIDmode)) + return 1; + } #endif break; } @@ -2230,7 +2257,7 @@ preprocess_constraints () break; case '&': op_alt[j].earlyclobber = 1; - break; + break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': @@ -2272,6 +2299,19 @@ preprocess_constraints () break; default: + if (EXTRA_MEMORY_CONSTRAINT (c)) + { + op_alt[j].memory_ok = 1; + break; + } + if (EXTRA_ADDRESS_CONSTRAINT (c)) + { + op_alt[j].is_address = 1; + op_alt[j].class = reg_class_subunion[(int) op_alt[j].class] + [(int) MODE_BASE_REG_CLASS (VOIDmode)]; + break; + } + op_alt[j].class = reg_class_subunion[(int) op_alt[j].class][(int) REG_CLASS_FROM_LETTER ((unsigned char) c)]; break; } @@ -2279,7 +2319,7 @@ preprocess_constraints () } } } - + /* Check the operands of an insn against the insn's operand constraints and return 1 if they are valid. The information about the insn's operands, constraints, operand modes @@ -2298,7 +2338,7 @@ preprocess_constraints () This is used in final, just before printing the assembler code and by the routines that determine an insn's attribute. - If STRICT is a positive non-zero value, it means that we have been + If STRICT is a positive nonzero value, it means that we have been called after reload has been completed. In that case, we must do all checks strictly. If it is zero, it means that we have been called before reload has completed. In that case, we first try to see if we can @@ -2499,20 +2539,10 @@ constrain_operands (strict) break; case 'E': -#ifndef REAL_ARITHMETIC - /* Match any CONST_DOUBLE, but only if - we can examine the bits of it reliably. */ - if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT - || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD) - && GET_MODE (op) != VOIDmode && ! flag_pretend_float) - break; -#endif - if (GET_CODE (op) == CONST_DOUBLE) - win = 1; - break; - case 'F': - if (GET_CODE (op) == CONST_DOUBLE) + if (GET_CODE (op) == CONST_DOUBLE + || (GET_CODE (op) == CONST_VECTOR + && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT)) win = 1; break; @@ -2595,6 +2625,28 @@ constrain_operands (strict) #ifdef EXTRA_CONSTRAINT else if (EXTRA_CONSTRAINT (op, c)) win = 1; + + if (EXTRA_MEMORY_CONSTRAINT (c)) + { + /* Every memory operand can be reloaded to fit. */ + if (strict < 0 && GET_CODE (op) == MEM) + win = 1; + + /* Before reload, accept what reload can turn into mem. */ + if (strict < 0 && CONSTANT_P (op)) + win = 1; + + /* During reload, accept a pseudo */ + if (reload_in_progress && GET_CODE (op) == REG + && REGNO (op) >= FIRST_PSEUDO_REGISTER) + win = 1; + } + if (EXTRA_ADDRESS_CONSTRAINT (c)) + { + /* Every address operand can be reloaded to fit. */ + if (strict < 0) + win = 1; + } #endif break; } @@ -2711,11 +2763,7 @@ split_insn (insn) allocation, and there are unlikely to be very many nops then anyways. */ if (reload_completed) - { - PUT_CODE (insn, NOTE); - NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; - NOTE_SOURCE_FILE (insn) = 0; - } + delete_insn_and_edges (insn); } else { @@ -2731,7 +2779,7 @@ split_insn (insn) NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; /* ??? Coddle to md files that generate subregs in post- - reload splitters instead of computing the proper + reload splitters instead of computing the proper hard register. */ if (reload_completed && first != last) { @@ -2757,25 +2805,26 @@ split_all_insns (upd_life) int upd_life; { sbitmap blocks; - int changed; - int i; + bool changed; + basic_block bb; - blocks = sbitmap_alloc (n_basic_blocks); + blocks = sbitmap_alloc (last_basic_block); sbitmap_zero (blocks); - changed = 0; + changed = false; - for (i = n_basic_blocks - 1; i >= 0; --i) + FOR_EACH_BB_REVERSE (bb) { - basic_block bb = BASIC_BLOCK (i); rtx insn, next; + bool finish = false; - for (insn = bb->head; insn ; insn = next) + for (insn = bb->head; !finish ; insn = next) { rtx last; /* Can't use `next_real_insn' because that might go across CODE_LABELS and short-out basic blocks. */ next = NEXT_INSN (insn); + finish = (insn == bb->end); last = split_insn (insn); if (last) { @@ -2785,29 +2834,27 @@ split_all_insns (upd_life) while (GET_CODE (last) == BARRIER) last = PREV_INSN (last); - SET_BIT (blocks, i); - changed = 1; + SET_BIT (blocks, bb->index); + changed = true; insn = last; } - - if (insn == bb->end) - break; } - - if (insn == NULL) - abort (); } if (changed) { + int old_last_basic_block = last_basic_block; + find_many_sub_basic_blocks (blocks); + + if (old_last_basic_block != last_basic_block && upd_life) + blocks = sbitmap_resize (blocks, last_basic_block, 1); } if (changed && upd_life) - { - count_or_remove_death_notes (blocks, 1); - update_life_info (blocks, UPDATE_LIFE_LOCAL, PROP_DEATH_NOTES); - } + update_life_info (blocks, UPDATE_LIFE_GLOBAL_RM_NOTES, + PROP_DEATH_NOTES | PROP_REG_INFO); + #ifdef ENABLE_CHECKING verify_flow_info (); #endif @@ -2815,7 +2862,7 @@ split_all_insns (upd_life) sbitmap_free (blocks); } -/* Same as split_all_insns, but do not expect CFG to be available. +/* Same as split_all_insns, but do not expect CFG to be available. Used by machine depedent reorg passes. */ void @@ -3034,7 +3081,8 @@ peephole2_optimize (dump_file) regset_head rs_heads[MAX_INSNS_PER_PEEP2 + 2]; rtx insn, prev; regset live; - int i, b; + int i; + basic_block bb; #ifdef HAVE_conditional_execution sbitmap blocks; bool changed; @@ -3048,16 +3096,15 @@ peephole2_optimize (dump_file) live = INITIALIZE_REG_SET (rs_heads[i]); #ifdef HAVE_conditional_execution - blocks = sbitmap_alloc (n_basic_blocks); + blocks = sbitmap_alloc (last_basic_block); sbitmap_zero (blocks); changed = false; #else count_or_remove_death_notes (NULL, 1); #endif - for (b = n_basic_blocks - 1; b >= 0; --b) + FOR_EACH_BB_REVERSE (bb) { - basic_block bb = BASIC_BLOCK (b); struct propagate_block_info *pbi; /* Indicate that all slots except the last holds invalid data. */ @@ -3086,6 +3133,7 @@ peephole2_optimize (dump_file) rtx try, before_try, x; int match_len; rtx note; + bool was_call = false; /* Record this insn. */ if (--peep2_current < 0) @@ -3103,7 +3151,7 @@ peephole2_optimize (dump_file) cfg-related call notes. */ for (i = 0; i <= match_len; ++i) { - int j, k; + int j; rtx old_insn, new_insn, note; j = i + peep2_current; @@ -3112,21 +3160,17 @@ peephole2_optimize (dump_file) old_insn = peep2_insn_data[j].insn; if (GET_CODE (old_insn) != CALL_INSN) continue; + was_call = true; - new_insn = NULL_RTX; - if (GET_CODE (try) == SEQUENCE) - for (k = XVECLEN (try, 0) - 1; k >= 0; k--) - { - rtx x = XVECEXP (try, 0, k); - if (GET_CODE (x) == CALL_INSN) - { - new_insn = x; - break; - } - } - else if (GET_CODE (try) == CALL_INSN) - new_insn = try; - if (! new_insn) + new_insn = try; + while (new_insn != NULL_RTX) + { + if (GET_CODE (new_insn) == CALL_INSN) + break; + new_insn = NEXT_INSN (new_insn); + } + + if (new_insn == NULL_RTX) abort (); CALL_INSN_FUNCTION_USAGE (new_insn) @@ -3166,22 +3210,23 @@ peephole2_optimize (dump_file) if (i >= MAX_INSNS_PER_PEEP2 + 1) i -= MAX_INSNS_PER_PEEP2 + 1; - note = find_reg_note (peep2_insn_data[i].insn, + note = find_reg_note (peep2_insn_data[i].insn, REG_EH_REGION, NULL_RTX); /* Replace the old sequence with the new. */ - try = emit_insn_after (try, peep2_insn_data[i].insn); + try = emit_insn_after_scope (try, peep2_insn_data[i].insn, + INSN_SCOPE (peep2_insn_data[i].insn)); before_try = PREV_INSN (insn); delete_insn_chain (insn, peep2_insn_data[i].insn); /* Re-insert the EH_REGION notes. */ - if (note) + if (note || (was_call && nonlocal_goto_handler_labels)) { edge eh_edge; for (eh_edge = bb->succ; eh_edge ; eh_edge = eh_edge->succ_next) - if (eh_edge->flags & EDGE_EH) + if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL)) break; for (x = try ; x != before_try ; x = PREV_INSN (x)) @@ -3190,10 +3235,11 @@ peephole2_optimize (dump_file) && may_trap_p (PATTERN (x)) && !find_reg_note (x, REG_EH_REGION, NULL))) { - REG_NOTES (x) - = gen_rtx_EXPR_LIST (REG_EH_REGION, - XEXP (note, 0), - REG_NOTES (x)); + if (note) + REG_NOTES (x) + = gen_rtx_EXPR_LIST (REG_EH_REGION, + XEXP (note, 0), + REG_NOTES (x)); if (x != bb->end && eh_edge) { @@ -3201,7 +3247,8 @@ peephole2_optimize (dump_file) int flags; nfte = split_block (bb, x); - flags = EDGE_EH | EDGE_ABNORMAL; + flags = (eh_edge->flags + & (EDGE_EH | EDGE_ABNORMAL)); if (GET_CODE (x) == CALL_INSN) flags |= EDGE_ABNORMAL_CALL; nehe = make_edge (nfte->src, eh_edge->dest, @@ -3232,7 +3279,7 @@ peephole2_optimize (dump_file) death data structures are not so self-contained. So record that we've made a modification to this block and update life information at the end. */ - SET_BIT (blocks, b); + SET_BIT (blocks, bb->index); changed = true; for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i) @@ -3310,3 +3357,114 @@ peephole2_optimize (dump_file) #endif } #endif /* HAVE_peephole2 */ + +/* Common predicates for use with define_bypass. */ + +/* True if the dependency between OUT_INSN and IN_INSN is on the store + data not the address operand(s) of the store. IN_INSN must be + single_set. OUT_INSN must be either a single_set or a PARALLEL with + SETs inside. */ + +int +store_data_bypass_p (out_insn, in_insn) + rtx out_insn, in_insn; +{ + rtx out_set, in_set; + + in_set = single_set (in_insn); + if (! in_set) + abort (); + + if (GET_CODE (SET_DEST (in_set)) != MEM) + return false; + + out_set = single_set (out_insn); + if (out_set) + { + if (reg_mentioned_p (SET_DEST (out_set), SET_DEST (in_set))) + return false; + } + else + { + rtx out_pat; + int i; + + out_pat = PATTERN (out_insn); + if (GET_CODE (out_pat) != PARALLEL) + abort (); + + for (i = 0; i < XVECLEN (out_pat, 0); i++) + { + rtx exp = XVECEXP (out_pat, 0, i); + + if (GET_CODE (exp) == CLOBBER) + continue; + + if (GET_CODE (exp) != SET) + abort (); + + if (reg_mentioned_p (SET_DEST (exp), SET_DEST (in_set))) + return false; + } + } + + return true; +} + +/* True if the dependency between OUT_INSN and IN_INSN is in the IF_THEN_ELSE + condition, and not the THEN or ELSE branch. OUT_INSN may be either a single + or multiple set; IN_INSN should be single_set for truth, but for convenience + of insn categorization may be any JUMP or CALL insn. */ + +int +if_test_bypass_p (out_insn, in_insn) + rtx out_insn, in_insn; +{ + rtx out_set, in_set; + + 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 (); + } + + if (GET_CODE (SET_SRC (in_set)) != IF_THEN_ELSE) + return false; + in_set = SET_SRC (in_set); + + out_set = single_set (out_insn); + if (out_set) + { + if (reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 1)) + || reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 2))) + return false; + } + else + { + rtx out_pat; + int i; + + out_pat = PATTERN (out_insn); + if (GET_CODE (out_pat) != PARALLEL) + abort (); + + for (i = 0; i < XVECLEN (out_pat, 0); i++) + { + rtx exp = XVECEXP (out_pat, 0, i); + + if (GET_CODE (exp) == CLOBBER) + continue; + + if (GET_CODE (exp) != SET) + abort (); + + if (reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 1)) + || reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 2))) + return false; + } + } + + return true; +} diff --git a/contrib/gcc/reload.c b/contrib/gcc/reload.c index 71ed1d6..b151af7 100644 --- a/contrib/gcc/reload.c +++ b/contrib/gcc/reload.c @@ -244,6 +244,7 @@ static enum reg_class find_valid_class PARAMS ((enum machine_mode, int, unsigned int)); static int reload_inner_reg_of_subreg PARAMS ((rtx, enum machine_mode, int)); static void push_replacement PARAMS ((rtx *, int, enum machine_mode)); +static void dup_replacements PARAMS ((rtx *, rtx *)); static void combine_reloads PARAMS ((void)); static int find_reusable_reload PARAMS ((rtx *, rtx, enum reg_class, enum reload_type, int, int)); @@ -257,6 +258,7 @@ static int alternative_allows_memconst PARAMS ((const char *, int)); static rtx find_reloads_toplev PARAMS ((rtx, int, enum reload_type, int, int, rtx, int *)); static rtx make_memloc PARAMS ((rtx, int)); +static int maybe_memory_address_p PARAMS ((enum machine_mode, rtx, rtx *)); static int find_reloads_address PARAMS ((enum machine_mode, rtx *, rtx, rtx *, int, enum reload_type, int, rtx)); static rtx subst_reg_equivs PARAMS ((rtx, rtx)); @@ -275,7 +277,7 @@ static int find_inc_amount PARAMS ((rtx, rtx)); #ifdef HAVE_SECONDARY_RELOADS /* Determine if any secondary reloads are needed for loading (if IN_P is - non-zero) or storing (if IN_P is zero) X to or from a reload register of + 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 are needed, push them. @@ -367,7 +369,7 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode, if (icode != CODE_FOR_nothing) { - /* If IN_P is non-zero, the reload register will be the output in + /* If IN_P is nonzero, the reload register will be the output in operand 0. If IN_P is zero, the reload register will be the input in operand 1. Outputs should have an initial "=", which we must skip. */ @@ -644,7 +646,7 @@ get_secondary_mem (x, mode, opnum, type) : type == RELOAD_FOR_OUTPUT ? RELOAD_FOR_OUTPUT_ADDRESS : RELOAD_OTHER); - find_reloads_address (mode, (rtx*) 0, XEXP (loc, 0), &XEXP (loc, 0), + find_reloads_address (mode, &loc, XEXP (loc, 0), &XEXP (loc, 0), opnum, type, 0, 0); } @@ -817,6 +819,13 @@ reload_inner_reg_of_subreg (x, mode, output) || REGNO (inner) >= FIRST_PSEUDO_REGISTER) return 0; + if (!subreg_offset_representable_p + (REGNO (SUBREG_REG (x)), + GET_MODE (SUBREG_REG (x)), + SUBREG_BYTE (x), + GET_MODE (x))) + return 1; + /* If INNER is not ok for MODE, then INNER will need reloading. */ if (! HARD_REGNO_MODE_OK (subreg_regno (x), mode)) return 1; @@ -828,7 +837,7 @@ reload_inner_reg_of_subreg (x, mode, output) && output && GET_MODE_SIZE (GET_MODE (inner)) > UNITS_PER_WORD && ((GET_MODE_SIZE (GET_MODE (inner)) / UNITS_PER_WORD) - != HARD_REGNO_NREGS (REGNO (inner), GET_MODE (inner)))); + != (int) HARD_REGNO_NREGS (REGNO (inner), GET_MODE (inner)))); } /* Record one reload that needs to be performed. @@ -837,7 +846,7 @@ reload_inner_reg_of_subreg (x, mode, output) (IN is zero for data not read, and OUT is zero for data not written.) INLOC and OUTLOC point to the places in the instructions where IN and OUT were found. - If IN and OUT are both non-zero, it means the same register must be used + If IN and OUT are both nonzero, it means the same register must be used to reload both IN and OUT. CLASS is a register class required for the reloaded data. @@ -966,9 +975,8 @@ push_reload (in, out, inloc, outloc, class, if (in != 0 && GET_CODE (in) == SUBREG && (subreg_lowpart_p (in) || strict_low) -#ifdef CLASS_CANNOT_CHANGE_MODE - && (class != CLASS_CANNOT_CHANGE_MODE - || ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)), inmode)) +#ifdef CANNOT_CHANGE_MODE_CLASS + && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)), inmode, class) #endif && (CONSTANT_P (SUBREG_REG (in)) || GET_CODE (SUBREG_REG (in)) == PLUS @@ -1005,8 +1013,8 @@ push_reload (in, out, inloc, outloc, class, > UNITS_PER_WORD) && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))) / UNITS_PER_WORD) - != 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 @@ -1015,14 +1023,11 @@ push_reload (in, out, inloc, outloc, class, SUBREG_REG (in)) == NO_REGS)) #endif -#ifdef CLASS_CANNOT_CHANGE_MODE +#ifdef CANNOT_CHANGE_MODE_CLASS || (GET_CODE (SUBREG_REG (in)) == REG && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER - && (TEST_HARD_REG_BIT - (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE], - REGNO (SUBREG_REG (in)))) - && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)), - inmode)) + && REG_CANNOT_CHANGE_MODE_P + (REGNO (SUBREG_REG (in)), GET_MODE (SUBREG_REG (in)), inmode)) #endif )) { @@ -1080,10 +1085,8 @@ push_reload (in, out, inloc, outloc, class, and in that case the constraint should label it input-output.) */ if (out != 0 && GET_CODE (out) == SUBREG && (subreg_lowpart_p (out) || strict_low) -#ifdef CLASS_CANNOT_CHANGE_MODE - && (class != CLASS_CANNOT_CHANGE_MODE - || ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)), - outmode)) +#ifdef CANNOT_CHANGE_MODE_CLASS + && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)), outmode, class) #endif && (CONSTANT_P (SUBREG_REG (out)) || strict_low @@ -1107,8 +1110,8 @@ push_reload (in, out, inloc, outloc, class, > UNITS_PER_WORD) && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))) / UNITS_PER_WORD) - != 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 @@ -1117,14 +1120,12 @@ push_reload (in, out, inloc, outloc, class, SUBREG_REG (out)) == NO_REGS)) #endif -#ifdef CLASS_CANNOT_CHANGE_MODE +#ifdef CANNOT_CHANGE_MODE_CLASS || (GET_CODE (SUBREG_REG (out)) == REG && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER - && (TEST_HARD_REG_BIT - (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE], - REGNO (SUBREG_REG (out)))) - && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)), - outmode)) + && REG_CANNOT_CHANGE_MODE_P (REGNO (SUBREG_REG (out)), + GET_MODE (SUBREG_REG (out)), + outmode)) #endif )) { @@ -1285,17 +1286,12 @@ push_reload (in, out, inloc, outloc, class, So add an additional reload. */ #ifdef SECONDARY_MEMORY_NEEDED - { - int regnum; - - /* If a memory location is needed for the copy, make one. */ - if (in != 0 - && ((regnum = true_regnum (in)) >= 0) - && regnum < FIRST_PSEUDO_REGISTER - && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (regnum), - class, inmode)) - get_secondary_mem (in, inmode, opnum, type); - } + /* If a memory location is needed for the copy, make one. */ + if (in != 0 && (GET_CODE (in) == REG || GET_CODE (in) == SUBREG) + && reg_or_subregno (in) < FIRST_PSEUDO_REGISTER + && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (reg_or_subregno (in)), + class, inmode)) + get_secondary_mem (in, inmode, opnum, type); #endif i = n_reloads; @@ -1321,16 +1317,12 @@ push_reload (in, out, inloc, outloc, class, n_reloads++; #ifdef SECONDARY_MEMORY_NEEDED - { - int regnum; - - if (out != 0 - && ((regnum = true_regnum (out)) >= 0) - && regnum < FIRST_PSEUDO_REGISTER - && SECONDARY_MEMORY_NEEDED (class, REGNO_REG_CLASS (regnum), - outmode)) - get_secondary_mem (out, outmode, opnum, type); - } + if (out != 0 && (GET_CODE (out) == REG || GET_CODE (out) == SUBREG) + && reg_or_subregno (out) < FIRST_PSEUDO_REGISTER + && SECONDARY_MEMORY_NEEDED (class, + REGNO_REG_CLASS (reg_or_subregno (out)), + outmode)) + get_secondary_mem (out, outmode, opnum, type); #endif } else @@ -1575,6 +1567,25 @@ push_replacement (loc, reloadnum, mode) r->mode = mode; } } + +/* Duplicate any replacement we have recorded to apply at + location ORIG_LOC to also be performed at DUP_LOC. + This is used in insn patterns that use match_dup. */ + +static void +dup_replacements (dup_loc, orig_loc) + rtx *dup_loc; + rtx *orig_loc; +{ + int i, n = n_replacements; + + for (i = 0; i < n; i++) + { + struct replacement *r = &replacements[i]; + if (r->where == orig_loc) + push_replacement (dup_loc, r->what, r->mode); + } +} /* Transfer all replacements that used to be in reload FROM to be in reload TO. */ @@ -1593,7 +1604,7 @@ transfer_replacements (to, from) /* IN_RTX is the value loaded by a reload that we now decided to inherit, or a subpart of it. If we have any replacements registered for IN_RTX, cancel the reloads that were supposed to load them. - Return non-zero if we canceled any reloads. */ + Return nonzero if we canceled any reloads. */ int remove_address_replacements (in_rtx) rtx in_rtx; @@ -1833,7 +1844,7 @@ combine_reloads () If FOR_REAL is -1, this should not be done, because this call is just to see if a register can be found, not to find and install it. - EARLYCLOBBER is non-zero if OUT is an earlyclobber operand. This + EARLYCLOBBER is nonzero if OUT is an earlyclobber operand. This puts an additional constraint on being able to use IN for OUT since IN must not appear elsewhere in the insn (it is assumed that IN itself is safe from the earlyclobber). */ @@ -2136,13 +2147,13 @@ operands_match_p (x, y) /* If two operands must match, because they are really a single operand of an assembler insn, then two postincrements are invalid because the assembler insn would increment only once. - On the other hand, an postincrement matches ordinary indexing + On the other hand, a postincrement matches ordinary indexing if the postincrement is the output operand. */ if (code == POST_DEC || code == POST_INC || code == POST_MODIFY) return operands_match_p (XEXP (x, 0), y); /* Two preincrements are invalid because the assembler insn would increment only once. - On the other hand, an preincrement matches ordinary indexing + On the other hand, a preincrement matches ordinary indexing if the preincrement is the input operand. In this case, return 2, since some callers need to do special things when this happens. */ @@ -2465,6 +2476,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) char pref_or_nothing[MAX_RECOG_OPERANDS]; /* Nonzero for a MEM operand whose entire address needs a reload. */ int address_reloaded[MAX_RECOG_OPERANDS]; + /* Nonzero for an address operand that needs to be completely reloaded. */ + int address_operand_reloaded[MAX_RECOG_OPERANDS]; /* Value of enum reload_type to use for operand. */ enum reload_type operand_type[MAX_RECOG_OPERANDS]; /* Value of enum reload_type to use within address of operand. */ @@ -2643,6 +2656,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) RTX_CODE code = GET_CODE (recog_data.operand[i]); address_reloaded[i] = 0; + address_operand_reloaded[i] = 0; operand_type[i] = (modified[i] == RELOAD_READ ? RELOAD_FOR_INPUT : modified[i] == RELOAD_WRITE ? RELOAD_FOR_OUTPUT : RELOAD_OTHER); @@ -2654,12 +2668,14 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) if (*constraints[i] == 0) /* Ignore things like match_operator operands. */ ; - else if (constraints[i][0] == 'p') + else if (constraints[i][0] == 'p' + || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0])) { - find_reloads_address (recog_data.operand_mode[i], (rtx*) 0, - recog_data.operand[i], - recog_data.operand_loc[i], - i, operand_type[i], ind_levels, insn); + address_operand_reloaded[i] + = find_reloads_address (recog_data.operand_mode[i], (rtx*) 0, + recog_data.operand[i], + recog_data.operand_loc[i], + i, operand_type[i], ind_levels, insn); /* If we now have a simple operand where we used to have a PLUS or MULT, re-recognize and try again. */ @@ -2676,6 +2692,10 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) recog_data.operand[i] = *recog_data.operand_loc[i]; substed_operand[i] = recog_data.operand[i]; + + /* Address operands are reloaded in their existing mode, + no matter what is specified in the machine description. */ + operand_mode[i] = GET_MODE (recog_data.operand[i]); } else if (code == MEM) { @@ -2856,6 +2876,12 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) if (GET_CODE (SUBREG_REG (operand)) == REG && REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER) { + if (!subreg_offset_representable_p + (REGNO (SUBREG_REG (operand)), + GET_MODE (SUBREG_REG (operand)), + SUBREG_BYTE (operand), + GET_MODE (operand))) + force_reload = 1; offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)), GET_MODE (SUBREG_REG (operand)), SUBREG_BYTE (operand), @@ -2911,26 +2937,6 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) ) #endif ) - /* This following hunk of code should no longer be - needed at all with SUBREG_BYTE. If you need this - code back, please explain to me why so I can - fix the real problem. -DaveM */ -#if 0 - /* Subreg of a hard reg which can't handle the subreg's mode - or which would handle that mode in the wrong number of - registers for subregging to work. */ - || (GET_CODE (operand) == REG - && REGNO (operand) < FIRST_PSEUDO_REGISTER - && ((GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD - && (GET_MODE_SIZE (GET_MODE (operand)) - > UNITS_PER_WORD) - && ((GET_MODE_SIZE (GET_MODE (operand)) - / UNITS_PER_WORD) - != HARD_REGNO_NREGS (REGNO (operand), - GET_MODE (operand)))) - || ! HARD_REGNO_MODE_OK (REGNO (operand) + offset, - operand_mode[i]))) -#endif ) force_reload = 1; } @@ -3154,20 +3160,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) break; case 'E': -#ifndef REAL_ARITHMETIC - /* Match any floating double constant, but only if - we can examine the bits of it reliably. */ - if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT - || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD) - && GET_MODE (operand) != VOIDmode && ! flag_pretend_float) - break; -#endif - if (GET_CODE (operand) == CONST_DOUBLE) - win = 1; - break; - case 'F': - if (GET_CODE (operand) == CONST_DOUBLE) + if (GET_CODE (operand) == CONST_DOUBLE + || (GET_CODE (operand) == CONST_VECTOR + && (GET_MODE_CLASS (GET_MODE (operand)) + == MODE_VECTOR_FLOAT))) win = 1; break; @@ -3244,6 +3241,49 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) if (REG_CLASS_FROM_LETTER (c) == NO_REGS) { #ifdef EXTRA_CONSTRAINT + if (EXTRA_MEMORY_CONSTRAINT (c)) + { + if (force_reload) + break; + if (EXTRA_CONSTRAINT (operand, c)) + win = 1; + /* If the address was already reloaded, + we win as well. */ + if (GET_CODE (operand) == MEM && address_reloaded[i]) + win = 1; + /* Likewise if the address will be reloaded because + reg_equiv_address is nonzero. For reg_equiv_mem + we have to check. */ + if (GET_CODE (operand) == REG + && REGNO (operand) >= FIRST_PSEUDO_REGISTER + && reg_renumber[REGNO (operand)] < 0 + && ((reg_equiv_mem[REGNO (operand)] != 0 + && EXTRA_CONSTRAINT (reg_equiv_mem[REGNO (operand)], c)) + || (reg_equiv_address[REGNO (operand)] != 0))) + win = 1; + + /* 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) + badop = 0; + constmemok = 1; + offmemok = 1; + break; + } + if (EXTRA_ADDRESS_CONSTRAINT (c)) + { + if (EXTRA_CONSTRAINT (operand, c)) + win = 1; + + /* If we didn't already win, we can reload + the address into a base register. */ + this_alternative[i] = (int) MODE_BASE_REG_CLASS (VOIDmode); + badop = 0; + break; + } + if (EXTRA_CONSTRAINT (operand, c)) win = 1; #endif @@ -3606,7 +3646,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) for (i = 0; i < noperands; i++) goal_alternative_matched[i] = -1; - + for (i = 0; i < noperands; i++) if (! goal_alternative_win[i] && goal_alternative_matches[i] >= 0) @@ -3810,6 +3850,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) } else if (goal_alternative_matched[i] < 0 && goal_alternative_matches[i] < 0 + && !address_operand_reloaded[i] && optimize) { /* For each non-matching operand that's a MEM or a pseudo-register @@ -3957,9 +3998,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) { int opno = recog_data.dup_num[i]; *recog_data.dup_loc[i] = *recog_data.operand_loc[opno]; - if (operand_reloadnum[opno] >= 0) - push_replacement (recog_data.dup_loc[i], operand_reloadnum[opno], - insn_data[insn_code_number].operand[opno].mode); + dup_replacements (recog_data.dup_loc[i], recog_data.operand_loc[opno]); } #if 0 @@ -4313,7 +4352,7 @@ alternative_allows_memconst (constraint, altnum) /* Scan the requested alternative for 'm' or 'o'. If one of them is present, this alternative accepts memory constants. */ while ((c = *constraint++) && c != ',' && c != '#') - if (c == 'm' || c == 'o') + if (c == 'm' || c == 'o' || EXTRA_MEMORY_CONSTRAINT (c)) return 1; return 0; } @@ -4438,34 +4477,6 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn, return tem; } - /* If the SUBREG is wider than a word, the above test will fail. - For example, we might have a SImode SUBREG of a DImode SUBREG_REG - for a 16 bit target, or a DImode SUBREG of a TImode SUBREG_REG for - a 32 bit target. We still can - and have to - handle this - for non-paradoxical subregs of CONST_INTs. */ - if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0 - && reg_equiv_constant[regno] != 0 - && GET_CODE (reg_equiv_constant[regno]) == CONST_INT - && (GET_MODE_SIZE (GET_MODE (x)) - < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))) - { - int shift = SUBREG_BYTE (x) * BITS_PER_UNIT; - if (WORDS_BIG_ENDIAN) - shift = (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) - - GET_MODE_BITSIZE (GET_MODE (x)) - - shift); - /* Here we use the knowledge that CONST_INTs have a - HOST_WIDE_INT field. */ - if (shift >= HOST_BITS_PER_WIDE_INT) - shift = HOST_BITS_PER_WIDE_INT - 1; - return GEN_INT (INTVAL (reg_equiv_constant[regno]) >> shift); - } - - if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0 - && reg_equiv_constant[regno] != 0 - && GET_MODE (reg_equiv_constant[regno]) == VOIDmode) - abort (); - /* If the subreg contains a reg that will be converted to a mem, convert the subreg to a narrower memref now. Otherwise, we would get (subreg (mem ...) ...), @@ -4545,6 +4556,27 @@ make_memloc (ad, regno) return tem; } +/* Returns true if AD could be turned into a valid memory reference + to mode MODE by reloading the part pointed to by PART into a + register. */ + +static int +maybe_memory_address_p (mode, ad, part) + enum machine_mode mode; + rtx ad; + rtx *part; +{ + int retv; + rtx tem = *part; + rtx reg = gen_rtx_REG (GET_MODE (tem), max_reg_num ()); + + *part = reg; + retv = memory_address_p (mode, ad); + *part = tem; + + return retv; +} + /* Record all reloads needed for handling memory address AD which appears in *LOC in a memory reference to mode MODE which itself is found in location *MEMREFLOC. @@ -4611,9 +4643,9 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn) tem = make_memloc (ad, regno); if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0))) { - find_reloads_address (GET_MODE (tem), (rtx*) 0, XEXP (tem, 0), - &XEXP (tem, 0), opnum, ADDR_TYPE (type), - ind_levels, insn); + find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0), + &XEXP (tem, 0), opnum, + ADDR_TYPE (type), ind_levels, insn); } /* We can avoid a reload if the register's equivalent memory expression is valid as an indirect memory address. @@ -4825,26 +4857,24 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn) that the index needs a reload and find_reloads_address_1 will take care of it. - If we decide to do something here, it must be that - `double_reg_address_ok' is true and that this address rtl was made by - eliminate_regs. We generate a reload of the fp/sp/ap + constant and + 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. + + 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 rework the sum so that the reload register will be added to the index. This is safe because we know the address isn't shared. - We check for fp/ap/sp as both the first and second operand of the - innermost PLUS. */ + 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 - && (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) - && ! memory_address_p (mode, ad)) + && 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) + && ! maybe_memory_address_p (mode, ad, &XEXP (XEXP (ad, 0), 1))) { *loc = ad = gen_rtx_PLUS (GET_MODE (ad), plus_constant (XEXP (XEXP (ad, 0), 0), @@ -4861,15 +4891,10 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn) else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT && GET_CODE (XEXP (ad, 0)) == PLUS - && (XEXP (XEXP (ad, 0), 1) == frame_pointer_rtx -#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM - || XEXP (XEXP (ad, 0), 1) == hard_frame_pointer_rtx -#endif -#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM - || XEXP (XEXP (ad, 0), 1) == arg_pointer_rtx -#endif - || XEXP (XEXP (ad, 0), 1) == stack_pointer_rtx) - && ! memory_address_p (mode, ad)) + && 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) + && ! maybe_memory_address_p (mode, ad, &XEXP (XEXP (ad, 0), 0))) { *loc = ad = gen_rtx_PLUS (GET_MODE (ad), XEXP (XEXP (ad, 0), 0), @@ -5214,6 +5239,19 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn) SUBREG_BYTE (orig_op1), GET_MODE (orig_op1)))); } + /* Plus in the index register may be created only as a result of + register remateralization for expresion 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) + { + 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)), + GET_MODE (x), VOIDmode, 0, 0, opnum, type); + return 1; + } if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE || code0 == ZERO_EXTEND || code1 == MEM) @@ -5341,7 +5379,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn) 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), 0, XEXP (tem, 0), + find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0), &XEXP (tem, 0), opnum, RELOAD_OTHER, ind_levels, insn); @@ -5644,7 +5682,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn) { enum reg_class class = (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)); - if (CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x))) + if ((unsigned) CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x))) > reg_class_size[class]) { x = find_reloads_subreg_address (x, 0, opnum, type, @@ -5988,7 +6026,7 @@ copy_replacements_1 (px, py, orig_replacements) } } -/* Change any replacements being done to *X to be done to *Y */ +/* Change any replacements being done to *X to be done to *Y. */ void move_replacements (x, y) @@ -6859,7 +6897,7 @@ regno_clobbered_p (regno, insn, mode, sets) && GET_CODE (XEXP (elt, 0)) == REG) { unsigned int test = REGNO (XEXP (elt, 0)); - + if (test >= regno && test < endregno) return 1; } |