From 92318bc515d223b2eeebb665f76e131dd2318b2b Mon Sep 17 00:00:00 2001 From: kan Date: Thu, 10 Oct 2002 04:40:18 +0000 Subject: Gcc 3.2.1-prerelease from the FSF anoncvs repo gcc-3_2-branch on October 9th 2002 20:15 EST. --- contrib/gcc/ChangeLog | 336 +++++++++++++++++++++- contrib/gcc/Makefile.in | 10 +- contrib/gcc/c-decl.c | 23 +- contrib/gcc/c-objc-common.c | 8 + contrib/gcc/calls.c | 8 + contrib/gcc/config/arm/arm.h | 14 +- contrib/gcc/config/arm/arm.md | 9 +- contrib/gcc/config/i386/i386.c | 63 +++-- contrib/gcc/config/i386/i386.h | 23 +- contrib/gcc/config/i386/linux64.h | 19 +- contrib/gcc/config/i386/t-linux64 | 3 +- contrib/gcc/config/i386/winnt.c | 19 +- contrib/gcc/config/rs6000/rs6000.md | 2 +- contrib/gcc/config/sparc/linux64.h | 67 +---- contrib/gcc/config/sparc/sol2-bi.h | 29 +- contrib/gcc/config/sparc/sparc.c | 1 - contrib/gcc/config/sparc/sparc.md | 25 +- contrib/gcc/config/sparc/t-linux64 | 14 +- contrib/gcc/config/sparc/t-sol2-64 | 3 +- contrib/gcc/cp/ChangeLog | 85 ++++-- contrib/gcc/cp/cp-tree.h | 26 -- contrib/gcc/cp/decl.c | 25 +- contrib/gcc/cp/decl2.c | 39 +-- contrib/gcc/cp/init.c | 5 +- contrib/gcc/cp/pt.c | 42 +-- contrib/gcc/cppinit.c | 124 ++++++--- contrib/gcc/cpplib.c | 57 ++-- contrib/gcc/cppmacro.c | 6 + contrib/gcc/doc/cpp.texi | 37 +-- contrib/gcc/doc/extend.texi | 74 ++--- contrib/gcc/doc/invoke.texi | 22 +- contrib/gcc/doloop.c | 93 +++---- contrib/gcc/expr.c | 126 +++++---- contrib/gcc/f/version.c | 2 +- contrib/gcc/flags.h | 4 + contrib/gcc/gcc.c | 370 ++++++++++++++++++------ contrib/gcc/genmultilib | 70 ++++- contrib/gcc/jump.c | 12 + contrib/gcc/libgcc2.c | 9 +- contrib/gcc/loop.c | 540 +++++++++++++++++++----------------- contrib/gcc/loop.h | 3 + contrib/gcc/mklibgcc.in | 70 ++--- contrib/gcc/reload.c | 32 ++- contrib/gcc/reload1.c | 22 +- contrib/gcc/rtl.h | 1 + contrib/gcc/sched-deps.c | 10 +- contrib/gcc/sibcall.c | 13 +- contrib/gcc/toplev.c | 10 +- contrib/gcc/tree.h | 27 ++ contrib/gcc/unroll.c | 13 +- contrib/gcc/varasm.c | 2 + contrib/gcc/version.c | 2 +- 52 files changed, 1715 insertions(+), 934 deletions(-) (limited to 'contrib/gcc') diff --git a/contrib/gcc/ChangeLog b/contrib/gcc/ChangeLog index 783f3d1..44f9438 100644 --- a/contrib/gcc/ChangeLog +++ b/contrib/gcc/ChangeLog @@ -1,3 +1,335 @@ +2002-10-09 Zack Weinberg + + PR c/7353 + * c-decl.c (start_decl): Unconditionally issue error for + 'typedef foo = bar'. + (finish_decl): Remove special case for TYPE_DECL with initializer. + + * doc/extend.texi: Delete "Naming Types" section. Change all + cross-references to that section to refer to "Typeof" instead. + Add the useful safe-max()-macro example from "Naming Types" to + "Typeof", rewritten using that extension. Add some compatibility + notes to "Typeof." + +2002-10-02 Richard Henderson + + PR opt/7124 + * config/i386/i386.c (ix86_register_move_cost): Increase cost + for secondary_memory_needed pairs. + +Wed Oct 9 19:09:13 CEST 2002 Jan Hubicka + + PR opt/7912 + PR opt/7390 + * i386.c (athlon_cost): Fix the move costs. + +2002-10-09 Alan Modra + + * libgcc2.c (__floatdisf): Properly cure double rounding. + +2002-10-09 Gabriel Dos Reis + + PR doc/7484 + * doc/invoke.texi (Option Summary): List + -Wmissing-declarations as a C only option. + +2002-10-08 Jakub Jelinek + + * config/sparc/t-linux64 (MULTILIB_OPTIONS): Remove + mno-app-regs|mcmodel=medany. + (MULTILIB_DIRNAMES, MULTILIB_OSDIRNAMES): Remove alt. + (MULTILIB_EXCEPTIONS, MULTILIB_EXCLUSIONS, MULTILIB_MATCHES): Remove. + (CRTSTUFF_T_CFLAGS): Define. + +2002-09-25 Eric Botcazou + Volker Reichelt + + PR c/7411 + * expr.c (expand_expr) [PLUS]: Simplify after the operands + have been expanded in EXPAND_NORMAL mode. + +2002-10-06 Richard Henderson + + * config/rs6000/rs6000.md (load_toc_v4_PIC_2): Fix base constraint. + +2002-10-06 Roger Sayle + + PR optimization/6627 + * toplev.c (force_align_functions_log): New global variable. + * flags.h (force_align_functions_log): Add extern prototype. + * varasm.c (assemble_start_function): Use it to force minimum + function alignment. + * config/i386/i386.h (FUNCTION_BOUNDARY): Set the correct + minimum function alignment to one byte. + (TARGET_PTRMEMFUNC_VBIT_LOCATION): Store the virtual bit in + the least significant bit of vtable member function pointers. + * tree.h (enum ptrmemfunc_vbit_where_t): Move definition to + here from cp/cp-tree.h. + +2002-10-06 Neil Booth + + Debian BTS Bug #157416 + * cpplib.c (destringize_and_run): Kludge around getting + tokens from in-progress macros. + (_cpp_do__Pragma): Simplify. + +2002-10-06 Frank Ch. Eigler + + * cppinit.c (init_standard_includes, parse_option): Use strncmp. + +2002-10-05 Jakub Jelinek + + * gcc.c (set_multilib_dir): Don't access *end. + Use memcpy instead of strncpy. Don't write beyond malloced buffer. + (print_multilib_info): Don't show paths starting with ".:". + * genmultilib: Add new option, "yes" if multilibs are enabled. + Update comments. If multilibs not enabled, print .:${osdirout} + for each directory. If multilibs are enabled, always print + ${dirout}:${osdirout}, even if the two are the same. + * Makefile.in (s-mlib): Pass @enable_multilib@ to genmultilib. + Pass all MULTILIB_* variables to genmultilib even if + --disable-multilib but MULTILIB_OSDIRNAMES is not empty. + + * gcc.c (print_multi_os_directory): New variable. + (option_map): Support --print-multi-os-directory. + (struct prefix_list): Add os_multilib field. + (multilib_os_dir): New variable. + (static_specs): Add multilib_options. + (find_a_file): Add multilib argument. Search in GCC or OS multilib + subdirs if non-zero. + (read_specs, execute): Update callers. + (find_file): Likewise. Don't prefix name with multilib_dir, instead + pass 1 as multilib option. + (display_help): Include --print-multi-os-directory. + (add_prefix): Add os_multilib argument. Initialize pl->os_multilib. + (process_command): Update callers. Handle --print-multi-os-directory. + (do_spec_1) ['D']: Use multilib_os_directory if pl->os_multilib is + set. + (main): Update find_a_file and add_prefix callers. + Handle print_multi_os_directory. + (struct mdswitchstr): New. + (mdswitches, n_mdswitches): New variables. + (used_arg): Add MULTILIB_DEFAULT switches too if they are not + present on the command line nor their mutually incompatible + switches. + (default_arg): Optimize. + (set_multilib_dir): Compute multilib_os_dir. Initialize mdswitches + array. + (print_multilib_info): Only print GCC multilib dir name, not OS + multilib dirname. + * genmultilib: Add osdirnames parameter. Output multilib_options + variable. If osdirnames is specified, output dirnames as + dirname:osdirname. + * mklibgcc.in: Use MULTILIB_OSDIRNAMES, --print-multi-directory + and --print-multi-os-directory instead of SHLIB_SLIBDIR_SUFFIXES + to compute libgcc_s soname and install path. + * Makefile.in (libgcc.mk): Pass MULTILIB_OSDIRNAMES instead of + SHLIB_SLIBDIR_SUFFIXES to mklibgcc. + (s_mlib): Pass MULTILIB_OSDIRNAMES or nothing as last genmultilib + argument. + + * config/sparc/t-linux64 (MULTILIB_OSDIRNAMES): Set. + (SHLIB_SLIBDIR_SUFFIXES): Remove. + * config/sparc/linux64.h (STARTFILE_SPEC32, STARTFILE_SPEC64, + ENDFILE_SPEC32, ENDFILE_SPEC64, ENDFILE_COMMON): Remove. + (STARTFILE_SPEC, ENDFILE_SPEC): Don't distinguish between -m32 + and -m64. + * config/sparc/t-sol2-64 (MULTILIB_OSDIRNAMES): Set. + (SHLIB_SLIBDIR_SUFFIXES): Remove. + * config/sparc/sol2-bi.h (STARTFILE_SPEC32, STARTFILE_SPEC64): Remove. + (STARTFILE_ARCH_SPEC): Remove. + (STARTFILE_SPEC): Add values-X*.o here. + * config/i386/t-linux64 (MULTILIB_OSDIRNAMES): Set. + (SHLIB_SLIBDIR_SUFFIXES): Remove. + * config/i386/linux64.h (STARTFILE_PREFIX_SPEC): Remove. + (STARTFILE_SPEC, ENDFILE_SPEC): Don't distinguish between m32 and + !m32. + * config/mips/t-iris6 (MULTILIB_OSDIRNAMES): Set. + (SHLIB_SLIBDIR_SUFFIXES): Remove. + +2002-10-05 Neil Booth + + PR preprocessor/8120 + * doc/cpp.texi: Update documentation of bad use of ##. + +Thu Oct 3 23:15:15 CEST 2002 Jan Hubicka + + * i386.h (CPP_SPECS): fix defines for -msse, -msse2, -mpentium2,3. + +Thu Oct 3 21:35:36 CEST 2002 Jan Hubicka + + * toplev.c (rest_of_compilation): Dump loops before clobbering + the structure. + + * expr.c (force_operand): Use expand_simple_* to handle more + cases. + + * i386.c (q_regs_operand): Use ANY_QI_REG_P. + + * i386.c (override_options): Fix stack alignment. + (classify_argument): Handle variable sized types. + (ix86_expand_int_movcc): Avoid RTL sharing problem. + + * i386.md (prefetch_sse_rex, prefetch_3dnow_rex): New. + (prefetch): Properly handle 64bit case. + + * i386.c (classify_argument): Properly compute word size of the analyzed object. + + * jump.c (reg_or_subregno): New function. + * rtl.h (reg_or_subregno): Declare + * unroll.c (find_splittable_givs): Handle subregs. + + Richard Sandiford : + + * expr.c (force_operand): Fix reversed move. + + Andreas Jaeger : + + * config/i386/linux64.h (STARTFILE_PREFIX_SPEC): New. + + Janis Johnson : + + * loop.c (emit_prefetch_instructions): Several small fixes. + +Thu Sep 5 00:34:33 2002 J"orn Rennecke + + * loop.c (scan_loop): Don't mark separate insns out of a libcall + for moving. + (move_movables): Abort if we see the first insn of a libcall. + +2002-10-01 David S. Miller + + PR middle-end/7151 + * config/sparc/sparc.md (movdi_insn_sp32_v9): Accept 'e' regs. + (movdi reg/reg split): Match only on sparc32, and v9 when int regs. + +2002-10-01 David S. Miller + Jan Hubicka + + * reload1.c (gen_reload:SECONDARY_MEMORY_NEEDED): Handle SUBREG. + * reload.c (push_reload:SECONDARY_MEMORY_NEEDED): Likewise. + +2002-09-30 Bob Wilson + + * config/xtensa/xtensa.h (REG_CLASS_NAMES, REG_CLASS_CONTENTS): + Add new RL_REGS register class. + (PREFERRED_RELOAD_CLASS, PREFERRED_OUTPUT_RELOAD_CLASS): + Call xtensa_preferred_reload_class for both input and output reloads. + * config/xtensa/xtensa.c (xtensa_regno_to_class): Use new RL_REGS class. + (xtensa_preferred_reload_class): Handle output reloads; use RL_REGS + instead of either AR_REGS or GR_REGS classes. + (xtensa_secondary_reload_class): Use new RL_REGS class. + * config/xtensa/xtensa-protos.h (xtensa_preferred_reload_class): Update. + +2002-08-21 John David Anglin + + * cppinit.c (remove_dup_nonsys_dirs): Fix warning and return value. + +2002-08-20 John David Anglin + + * cppinit.c (remove_dup_dir): Add head_ptr argument to handle removal + at head. + (remove_dup_nonsys_dirs): New function. + (remove_dup_dirs): Change argument head to head_ptr. Remove warnings. + (merge_include_chains): Remove non-system include directories from + quote and bracket include chains when they duplicate equivalent system + directories. + * doc/cpp.texi (-I): Update. + * doc/cppopts.texi (-I): Update. + * doc/install.texi (--with-local-prefix): Further document usage of + this option. + * doc/invoke.texi (-I): Update. + +2002-09-30 Richard Earnshaw + + * arm.h (BASE_REG_CLASS): Always return LO_REGS for Thumb. + (MODE_BASE_REG_CLASS, case Thumb): Only return BASE_REGS if we know + that we have a SImode access, and only then if reload hasn't completed; + for all other cases, use LO_REGS. + +2002-09-29 David S. Miller + + * config/sparc/linux64.h (STARTFILE_SPEC32, ENDFILE_SPEC32): Kill + hardcoded paths. + +2002-09-27 Alexander N. Kabaev + + PR preprocessor/8055 + * cppmacro.c (stringify_arg): Do not overflow the buffer + with the terminating NUL when the argument to be stringified + has no tokens. + +2002-09-26 David S. Miller + + PR optimization/7335 + * calls.c (emit_library_call_value_1): Passing args by reference + converts a CONST function into a PURE one. + +2002-09-26 Richard Henderson + + PR c/7160 + * sched-deps.c (sched_analyze_insn): Make clobber insns depend + on call insns. + +2002-09-27 Alan Modra + + * doloop.c (doloop_modify_runtime ): Adjust + by absolute loop increment, not loop increment. + +2002-09-25 David S. Miller + + PR target/7842 + * config/sparc/sparc.c (set_extends): SImode ASHIFT does not + extend. + +2002-09-20 Jeroen Dobbelaere + + * config/arm/arm.md (sign_extract_onebit, not_signextract_onebit): + Add clobber of the condition code register. + +2002-09-18 Richard Earnshaw (rearnsha@arm.com) + + PR optimization/7967 + * arm.md (ne_zeroextractsi): Add clobber of the condition code + register. + +2002-09-17 Richard Henderson + + * sibcall.c (optimize_sibling_and_tail_recursive_call): Also remove + RTX_UNCHANGING_P markers for successful tail-recursive replacement. + +2002-09-16 Richard Henderson + + PR opt/7515 + * c-objc-common.c (c_cannot_inline_tree_fn): Don't auto-inline + functions that don't bind locally. + +2002-09-17 Alan Modra + + Merge from mainline. + 2002-07-20 Alan Modra + PR optimization/7130 + * loop.h (struct loop_info): Add "preconditioned". + * unroll.c (unroll_loop): Set it. + * doloop.c (doloop_modify_runtime): Correct count for unrolled loops. + + 2002-06-24 Alan Modra + PR optimization/6984 + * doloop.c (doloop_valid_p): Correct comment. + (doloop_modify_runtime ): Simplify. + (doloop_modify_runtime ): Don't emit code when NE. + +2002-09-16 Jeff Law + + * libgcc2.c: Do not include machmode.h. + +2002-09-16 Jason Merrill + Danny Smith + + * config/i386/winnt.c (ix86_handle_dll_attribute): Set + DECL_EXTERN and TREE_PUBLIC for dllimported variables here... + (i386_pe_mark_dllimport): Not here. + 2002-09-14 Stephane Carrez * config/m68hc11/m68hc11.md ("movdi_internal"): Allow any offsetable @@ -185,7 +517,7 @@ 2002-08-27 Mark Mitchell * doc/invoke.texi: Document -Wabi. - + 2002-08-23 David Edelsohn * config/rs6000/rs6000.c (rs6000_select_section): Treat @@ -201,7 +533,7 @@ * explow.c (expr_size): Call it. (int_expr_size): New fn. * expr.h: Declare it. - * expr.c (expand_expr) [CONSTRUCTOR]: Use it to calculate how + * expr.c (expand_expr) [CONSTRUCTOR]: Use it to calculate how much to store. 2002-08-23 Alan Modra diff --git a/contrib/gcc/Makefile.in b/contrib/gcc/Makefile.in index ebcbbc2..5afd30e 100644 --- a/contrib/gcc/Makefile.in +++ b/contrib/gcc/Makefile.in @@ -1003,7 +1003,7 @@ libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) $(LIB2ADD_ST) xgcc$(exeext SHLIB_MKMAP_OPTS='$(SHLIB_MKMAP_OPTS)' \ SHLIB_MAPFILES='$(SHLIB_MAPFILES)' \ SHLIB_NM_FLAGS='$(SHLIB_NM_FLAGS)' \ - SHLIB_SLIBDIR_SUFFIXES='$(SHLIB_SLIBDIR_SUFFIXES)' \ + MULTILIB_OSDIRNAMES='$(MULTILIB_OSDIRNAMES)' \ mkinstalldirs='$(SHELL) $(srcdir)/mkinstalldirs' \ $(SHELL) mklibgcc > tmp-libgcc.mk mv tmp-libgcc.mk libgcc.mk @@ -1037,7 +1037,8 @@ libgcc.a: $(LIBGCC_DEPS) # switches. multilib.h: s-mlib; @true s-mlib: $(srcdir)/genmultilib Makefile - if test @enable_multilib@ = yes; then \ + if test @enable_multilib@ = yes \ + || test -n "$(MULTILIB_OSDIRNAMES)"; then \ $(SHELL) $(srcdir)/genmultilib \ "$(MULTILIB_OPTIONS)" \ "$(MULTILIB_DIRNAMES)" \ @@ -1045,9 +1046,12 @@ s-mlib: $(srcdir)/genmultilib Makefile "$(MULTILIB_EXCEPTIONS)" \ "$(MULTILIB_EXTRA_OPTS)" \ "$(MULTILIB_EXCLUSIONS)" \ + "$(MULTILIB_OSDIRNAMES)" \ + "@enable_multilib@" \ > tmp-mlib.h; \ else \ - $(SHELL) $(srcdir)/genmultilib '' '' '' '' '' '' > tmp-mlib.h; \ + $(SHELL) $(srcdir)/genmultilib '' '' '' '' '' '' '' no \ + > tmp-mlib.h; \ fi $(SHELL) $(srcdir)/move-if-change tmp-mlib.h multilib.h $(STAMP) s-mlib diff --git a/contrib/gcc/c-decl.c b/contrib/gcc/c-decl.c index a6e010b..ea0b5f6 100644 --- a/contrib/gcc/c-decl.c +++ b/contrib/gcc/c-decl.c @@ -3485,15 +3485,9 @@ start_decl (declarator, declspecs, initialized, attributes) switch (TREE_CODE (decl)) { case TYPE_DECL: - /* typedef foo = bar means give foo the same type as bar. - We haven't parsed bar yet, so `finish_decl' will fix that up. - Any other case of an initialization in a TYPE_DECL is an error. */ - if (pedantic || list_length (declspecs) > 1) - { - error ("typedef `%s' is initialized", - IDENTIFIER_POINTER (DECL_NAME (decl))); - initialized = 0; - } + error ("typedef `%s' is initialized", + IDENTIFIER_POINTER (DECL_NAME (decl))); + initialized = 0; break; case FUNCTION_DECL: @@ -3642,16 +3636,7 @@ finish_decl (decl, init, asmspec_tree) init = 0; if (init) - { - if (TREE_CODE (decl) != TYPE_DECL) - store_init_value (decl, init); - else - { - /* typedef foo = bar; store the type of bar as the type of foo. */ - TREE_TYPE (decl) = TREE_TYPE (init); - DECL_INITIAL (decl) = init = 0; - } - } + store_init_value (decl, init); /* Deduce size of array from initialization, if not already known */ if (TREE_CODE (type) == ARRAY_TYPE diff --git a/contrib/gcc/c-objc-common.c b/contrib/gcc/c-objc-common.c index 0ed3869..43ec820 100644 --- a/contrib/gcc/c-objc-common.c +++ b/contrib/gcc/c-objc-common.c @@ -149,6 +149,14 @@ c_cannot_inline_tree_fn (fnp) && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL) return 1; + /* Don't auto-inline anything that might not be bound within + this unit of translation. */ + if (!DECL_DECLARED_INLINE_P (fn) && flag_pic && TREE_PUBLIC (fn)) + { + DECL_UNINLINABLE (fn) = 1; + return 1; + } + if (! function_attribute_inlinable_p (fn)) { DECL_UNINLINABLE (fn) = 1; diff --git a/contrib/gcc/calls.c b/contrib/gcc/calls.c index c0a73e7..449c933 100644 --- a/contrib/gcc/calls.c +++ b/contrib/gcc/calls.c @@ -3666,6 +3666,14 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) #endif ; + /* If this was a CONST function, it is now PURE since + it now reads memory. */ + if (flags & ECF_CONST) + { + flags &= ~ECF_CONST; + flags |= ECF_PURE; + } + if (GET_MODE (val) == MEM && ! must_copy) slot = val; else if (must_copy) diff --git a/contrib/gcc/config/arm/arm.h b/contrib/gcc/config/arm/arm.h index 5e8b5d9..c5431b5 100644 --- a/contrib/gcc/config/arm/arm.h +++ b/contrib/gcc/config/arm/arm.h @@ -1093,14 +1093,16 @@ enum reg_class /* The class value for index registers, and the one for base regs. */ #define INDEX_REG_CLASS (TARGET_THUMB ? LO_REGS : GENERAL_REGS) -#define BASE_REG_CLASS (TARGET_THUMB ? BASE_REGS : GENERAL_REGS) +#define BASE_REG_CLASS (TARGET_THUMB ? LO_REGS : GENERAL_REGS) -/* For the Thumb the high registers cannot be used as base - registers when addressing quanitities in QI or HI mode. */ +/* For the Thumb the high registers cannot be used as base registers + when addressing quanitities in QI or HI mode; if we don't know the + mode, then we must be conservative. After reload we must also be + conservative, since we can't support SP+reg addressing, and we + can't fix up any bad substitutions. */ #define MODE_BASE_REG_CLASS(MODE) \ - (TARGET_ARM ? BASE_REGS : \ - (((MODE) == QImode || (MODE) == HImode || (MODE) == VOIDmode) \ - ? LO_REGS : BASE_REGS)) + (TARGET_ARM ? GENERAL_REGS : \ + (((MODE) == SImode && !reload_completed) ? BASE_REGS : LO_REGS)) /* When SMALL_REGISTER_CLASSES is nonzero, the compiler allows registers explicitly used in the rtl to be used as spill registers diff --git a/contrib/gcc/config/arm/arm.md b/contrib/gcc/config/arm/arm.md index b901504..5180c75 100644 --- a/contrib/gcc/config/arm/arm.md +++ b/contrib/gcc/config/arm/arm.md @@ -1837,7 +1837,8 @@ (match_operand:SI 1 "s_register_operand" "r") (match_operand:SI 2 "const_int_operand" "n") (match_operand:SI 3 "const_int_operand" "n")) - (const_int 0)))] + (const_int 0))) + (clobber (reg:CC CC_REGNUM))] "TARGET_ARM && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32 && INTVAL (operands[2]) > 0 @@ -8947,7 +8948,8 @@ [(set (match_operand:SI 0 "s_register_operand" "=r") (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") (const_int 1) - (match_operand:SI 2 "const_int_operand" "n")))] + (match_operand:SI 2 "const_int_operand" "n"))) + (clobber (reg:CC CC_REGNUM))] "TARGET_ARM" "* operands[2] = GEN_INT (1 << INTVAL (operands[2])); @@ -8963,7 +8965,8 @@ (not:SI (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") (const_int 1) - (match_operand:SI 2 "const_int_operand" "n"))))] + (match_operand:SI 2 "const_int_operand" "n")))) + (clobber (reg:CC CC_REGNUM))] "TARGET_ARM" "* operands[2] = GEN_INT (1 << INTVAL (operands[2])); diff --git a/contrib/gcc/config/i386/i386.c b/contrib/gcc/config/i386/i386.c index f07ebad..5e48715 100644 --- a/contrib/gcc/config/i386/i386.c +++ b/contrib/gcc/config/i386/i386.c @@ -284,25 +284,25 @@ struct processor_costs athlon_cost = { 8, /* "large" insn */ 9, /* MOVE_RATIO */ 4, /* cost for loading QImode using movzbl */ - {4, 5, 4}, /* cost of loading integer registers + {3, 4, 3}, /* cost of loading integer registers in QImode, HImode and SImode. Relative to reg-reg move (2). */ - {2, 3, 2}, /* cost of storing integer registers */ + {3, 4, 3}, /* cost of storing integer registers */ 4, /* cost of reg,reg fld/fst */ - {6, 6, 20}, /* cost of loading fp registers + {4, 4, 12}, /* cost of loading fp registers in SFmode, DFmode and XFmode */ - {4, 4, 16}, /* cost of loading integer registers */ + {6, 6, 8}, /* cost of loading integer registers */ 2, /* cost of moving MMX register */ - {2, 2}, /* cost of loading MMX registers + {4, 4}, /* cost of loading MMX registers in SImode and DImode */ - {2, 2}, /* cost of storing MMX registers + {4, 4}, /* cost of storing MMX registers in SImode and DImode */ 2, /* cost of moving SSE register */ - {2, 2, 8}, /* cost of loading SSE registers + {4, 4, 6}, /* cost of loading SSE registers in SImode, DImode and TImode */ - {2, 2, 8}, /* cost of storing SSE registers + {4, 4, 5}, /* cost of storing SSE registers in SImode, DImode and TImode */ - 6, /* MMX or SSE register to integer */ + 5, /* MMX or SSE register to integer */ 64, /* size of prefetch block */ 6, /* number of parallel prefetches */ }; @@ -1649,7 +1649,11 @@ classify_argument (mode, type, classes, bit_offset) { int bytes = (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode); - int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; + int words = (bytes + (bit_offset % 64) / 8 + UNITS_PER_WORD - 1) / UNITS_PER_WORD; + + /* Variable sized structures are always passed on the stack. */ + if (mode == BLKmode && type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) + return 0; if (type && AGGREGATE_TYPE_P (type)) { @@ -3206,7 +3210,7 @@ q_regs_operand (op, mode) return 0; if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); - return QI_REG_P (op); + return ANY_QI_REG_P (op); } /* Return true if op is a NON_Q_REGS class register. */ @@ -6123,7 +6127,10 @@ print_operand_address (file, addr) int scale; if (! ix86_decompose_address (addr, &parts)) - abort (); + { + output_operand_lossage ("Wrong address expression or operand constraint"); + return; + } base = parts.base; index = parts.index; @@ -8237,7 +8244,7 @@ ix86_expand_int_movcc (operands) clob = gen_rtx_CLOBBER (VOIDmode, clob); tmp = gen_rtx_SET (VOIDmode, out, tmp); - tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob)); + tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, copy_rtx (tmp), clob)); emit_insn (tmp); } else @@ -12355,17 +12362,33 @@ ix86_register_move_cost (mode, class1, class2) enum reg_class class1, class2; { /* In case we require secondary memory, compute cost of the store followed - by load. In case of copying from general_purpose_register we may emit - multiple stores followed by single load causing memory size mismatch - stall. Count this as arbitarily high cost of 20. */ + by load. In order to avoid bad register allocation choices, we need + for this to be *at least* as high as the symmetric MEMORY_MOVE_COST. */ + if (ix86_secondary_memory_needed (class1, class2, mode, 0)) { - int add_cost = 0; + int cost = 1; + + cost += MAX (MEMORY_MOVE_COST (mode, class1, 0), + MEMORY_MOVE_COST (mode, class1, 1)); + cost += MAX (MEMORY_MOVE_COST (mode, class2, 0), + MEMORY_MOVE_COST (mode, class2, 1)); + + /* In case of copying from general_purpose_register we may emit multiple + stores followed by single load causing memory size mismatch stall. + Count this as arbitarily high cost of 20. */ if (CLASS_MAX_NREGS (class1, mode) > CLASS_MAX_NREGS (class2, mode)) - add_cost = 20; - return (MEMORY_MOVE_COST (mode, class1, 0) - + MEMORY_MOVE_COST (mode, class2, 1) + add_cost); + cost += 20; + + /* In the case of FP/MMX moves, the registers actually overlap, and we + have to switch modes in order to treat them differently. */ + if ((MMX_CLASS_P (class1) && MAYBE_FLOAT_CLASS_P (class2)) + || (MMX_CLASS_P (class2) && MAYBE_FLOAT_CLASS_P (class1))) + cost += 20; + + return cost; } + /* Moves between SSE/MMX and integer unit are expensive. */ if (MMX_CLASS_P (class1) != MMX_CLASS_P (class2) || SSE_CLASS_P (class1) != SSE_CLASS_P (class2)) diff --git a/contrib/gcc/config/i386/i386.h b/contrib/gcc/config/i386/i386.h index 07502a2..58d2c433 100644 --- a/contrib/gcc/config/i386/i386.h +++ b/contrib/gcc/config/i386/i386.h @@ -584,9 +584,13 @@ extern int ix86_arch; %{march=pentium-mmx:-D__i586 -D__i586__ -D__pentium -D__pentium__ \ -D__pentium__mmx__ \ %{!mcpu*:-D__tune_i586__ -D__tune_pentium__ -D__tune_pentium_mmx__}}\ -%{march=pentiumpro|march=i686:-D__i686 -D__i686__ \ +%{march=pentiumpro|march=i686|march=pentium2|march=pentium3:-D__i686 -D__i686__ \ -D__pentiumpro -D__pentiumpro__ \ %{!mcpu*:-D__tune_i686__ -D__tune_pentiumpro__ }}\ +%{march=march=pentium2|march=pentium3: -D__pentium2 -D__pentium2__\ + %{!mcpu*:-D__tune_pentium2__ }}\ +%{march=pentium3: -D__pentium3 -D__pentium3__\ + %{!mcpu*:-D__tune_pentium3__ }}\ %{march=k6:-D__k6 -D__k6__ %{!mcpu*:-D__tune_k6__ }}\ %{march=k6-2:-D__k6 -D__k6__ -D__k6_2__ \ %{!mcpu*:-D__tune_k6__ -D__tune_k6_2__ }}\ @@ -601,7 +605,7 @@ extern int ix86_arch; %{m386|mcpu=i386:-D__tune_i386__ }\ %{m486|mcpu=i486:-D__tune_i486__ }\ %{mpentium|mcpu=pentium|mcpu=i586|mcpu=pentium-mmx:-D__tune_i586__ -D__tune_pentium__ }\ -%{mpentiumpro|mcpu=pentiumpro|mcpu=i686|cpu=pentium2|cpu=pentium3:-D__tune_i686__ \ +%{mpentiumpro|mcpu=pentiumpro|mcpu=i686|mcpu=pentium2|mcpu=pentium3:-D__tune_i686__ \ -D__tune_pentiumpro__ }\ %{mcpu=k6|mcpu=k6-2|mcpu=k6-3:-D__tune_k6__ }\ %{mcpu=athlon|mcpu=athlon-tbird|mcpu=athlon-4|mcpu=athlon-xp|mcpu=athlon-mp:\ @@ -609,17 +613,17 @@ extern int ix86_arch; %{mcpu=athlon-4|mcpu=athlon-xp|mcpu=athlon-mp:\ -D__tune_athlon_sse__ }\ %{mcpu=pentium4:-D__tune_pentium4__ }\ -%{march=athlon-xp|march=athlon-mp|march=pentium3|march=pentium4:\ +%{march=athlon-xp|march=athlon-mp|march=pentium3|march=pentium4|msse|msse2:\ -D__SSE__ }\ %{march=pentium-mmx|march=k6|march=k6-2|march=k6-3\ |march=athlon|march=athlon-tbird|march=athlon-4|march=athlon-xp\ -|march=athlon-mp|march=pentium2|march=pentium3|march=pentium4: -D__MMX__ }\ +|march=athlon-mp|march=pentium2|march=pentium3|march=pentium4|mmx|msse|m3dnow: -D__MMX__ }\ %{march=k6-2|march=k6-3\ |march=athlon|march=athlon-tbird|march=athlon-4|march=athlon-xp\ -|march=athlon-mp: -D__3dNOW__ }\ +|march=athlon-mp|m3dnow: -D__3dNOW__ }\ %{march=athlon|march=athlon-tbird|march=athlon-4|march=athlon-xp\ |march=athlon-mp: -D__3dNOW_A__ }\ -%{march=pentium4: -D__SSE2__ }\ +%{march=pentium4|msse2: -D__SSE2__ }\ %{!march*:%{!mcpu*:%{!m386:%{!m486:%{!mpentium*:%(cpp_cpu_default)}}}}}" #ifndef CPP_CPU_SPEC @@ -756,8 +760,11 @@ extern int ix86_arch; #define FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN \ (ix86_preferred_stack_boundary > STACK_BOUNDARY && !TARGET_64BIT) -/* Allocation boundary for the code of a function. */ -#define FUNCTION_BOUNDARY 16 +/* Minimum allocation boundary for the code of a function. */ +#define FUNCTION_BOUNDARY 8 + +/* C++ stores the virtual bit in the lowest bit of function pointers. */ +#define TARGET_PTRMEMFUNC_VBIT_LOCATION ptrmemfunc_vbit_in_pfn /* Alignment of field after `int : 0' in a structure. */ diff --git a/contrib/gcc/config/i386/linux64.h b/contrib/gcc/config/i386/linux64.h index 6158431..8a0bfbe 100644 --- a/contrib/gcc/config/i386/linux64.h +++ b/contrib/gcc/config/i386/linux64.h @@ -50,21 +50,14 @@ Boston, MA 02111-1307, USA. */ #undef STARTFILE_SPEC #define STARTFILE_SPEC \ - "%{m32:%{!shared: \ - %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \ - %{!p:%{profile:gcrt1.o%s} %{!profile:crt1.o%s}}}} \ - crti.o%s %{static:crtbeginT.o%s}\ - %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}} \ - %{!m32:%{!shared: \ - %{pg:/usr/lib64/gcrt1.o%s} %{!pg:%{p:/usr/lib64/gcrt1.o%s} \ - %{!p:%{profile:/usr/lib64/gcrt1.o%s} %{!profile:/usr/lib64/crt1.o%s}}}}\ - /usr/lib64/crti.o%s %{static:crtbeginT.o%s} \ - %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}}" + "%{!shared: \ + %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \ + %{!p:%{profile:gcrt1.o%s} %{!profile:crt1.o%s}}}} \ + crti.o%s %{static:crtbeginT.o%s} \ + %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}" #undef ENDFILE_SPEC -#define ENDFILE_SPEC "\ - %{m32:%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s} \ - %{!m32:%{!shared:crtend.o%s} %{shared:crtendS.o%s} /usr/lib64/crtn.o%s}" +#define ENDFILE_SPEC "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s" #define MULTILIB_DEFAULTS { "m64" } diff --git a/contrib/gcc/config/i386/t-linux64 b/contrib/gcc/config/i386/t-linux64 index 46a7caa..31b6ad4 100644 --- a/contrib/gcc/config/i386/t-linux64 +++ b/contrib/gcc/config/i386/t-linux64 @@ -6,10 +6,9 @@ SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver \ MULTILIB_OPTIONS = m64/m32 MULTILIB_DIRNAMES = 64 32 +MULTILIB_OSDIRNAMES = ../lib64 ../lib LIBGCC = stmp-multilib INSTALL_LIBGCC = install-multilib EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o - -SHLIB_SLIBDIR_SUFFIXES = 64:64 32: diff --git a/contrib/gcc/config/i386/winnt.c b/contrib/gcc/config/i386/winnt.c index 9d955df..6928a8c 100644 --- a/contrib/gcc/config/i386/winnt.c +++ b/contrib/gcc/config/i386/winnt.c @@ -76,6 +76,15 @@ ix86_handle_dll_attribute (node, name, args, flags, no_add_attrs) } } + /* `extern' needn't be specified with dllimport. + Specify `extern' now and hope for the best. Sigh. */ + else if (TREE_CODE (*node) == VAR_DECL + && is_attribute_p ("dllimport", name)) + { + DECL_EXTERNAL (*node) = 1; + TREE_PUBLIC (*node) = 1; + } + return NULL_TREE; } @@ -300,16 +309,6 @@ i386_pe_mark_dllimport (decl) return; } - /* `extern' needn't be specified with dllimport. - Specify `extern' now and hope for the best. Sigh. */ - if (TREE_CODE (decl) == VAR_DECL - /* ??? Is this test for vtables needed? */ - && !DECL_VIRTUAL_P (decl)) - { - DECL_EXTERNAL (decl) = 1; - TREE_PUBLIC (decl) = 1; - } - newname = alloca (strlen (oldname) + 11); sprintf (newname, "@i._imp__%s", oldname); diff --git a/contrib/gcc/config/rs6000/rs6000.md b/contrib/gcc/config/rs6000/rs6000.md index f032bfd..6e86d73 100644 --- a/contrib/gcc/config/rs6000/rs6000.md +++ b/contrib/gcc/config/rs6000/rs6000.md @@ -9657,7 +9657,7 @@ (define_insn "load_toc_v4_PIC_2" [(set (match_operand:SI 0 "register_operand" "=r") - (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r") + (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "b") (minus:SI (match_operand:SI 2 "immediate_operand" "s") (match_operand:SI 3 "immediate_operand" "s")))))] "TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2" diff --git a/contrib/gcc/config/sparc/linux64.h b/contrib/gcc/config/sparc/linux64.h index 1dfd97f..c7d8f491 100644 --- a/contrib/gcc/config/sparc/linux64.h +++ b/contrib/gcc/config/sparc/linux64.h @@ -1,5 +1,5 @@ /* Definitions for 64-bit SPARC running Linux-based GNU systems with ELF. - Copyright 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + Copyright 1996, 1997, 1998, 2000, 2002 Free Software Foundation, Inc. Contributed by David S. Miller (davem@caip.rutgers.edu) This file is part of GNU CC. @@ -56,38 +56,12 @@ Boston, MA 02111-1307, USA. */ #undef STARTFILE_SPEC -#define STARTFILE_SPEC32 \ +#define STARTFILE_SPEC \ "%{!shared: \ - %{pg:/usr/lib/gcrt1.o%s} %{!pg:%{p:/usr/lib/gcrt1.o%s} %{!p:/usr/lib/crt1.o%s}}}\ - /usr/lib/crti.o%s %{static:crtbeginT.o%s}\ + %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\ + crti.o%s %{static:crtbeginT.o%s}\ %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}" -#define STARTFILE_SPEC64 \ - "%{!shared: \ - %{pg:/usr/lib64/gcrt1.o%s} %{!pg:%{p:/usr/lib64/gcrt1.o%s} %{!p:/usr/lib64/crt1.o%s}}}\ - /usr/lib64/crti.o%s %{static:crtbeginT.o%s}\ - %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}" - -#ifdef SPARC_BI_ARCH - -#if DEFAULT_ARCH32_P -#define STARTFILE_SPEC "\ -%{m32:" STARTFILE_SPEC32 "} \ -%{m64:" STARTFILE_SPEC64 "} \ -%{!m32:%{!m64:" STARTFILE_SPEC32 "}}" -#else -#define STARTFILE_SPEC "\ -%{m32:" STARTFILE_SPEC32 "} \ -%{m64:" STARTFILE_SPEC64 "} \ -%{!m32:%{!m64:" STARTFILE_SPEC64 "}}" -#endif - -#else - -#define STARTFILE_SPEC STARTFILE_SPEC64 - -#endif - /* Provide a ENDFILE_SPEC appropriate for GNU/Linux. Here we tack on the GNU/Linux magical crtend.o file (see crtstuff.c) which provides part of the support for getting C++ file-scope static @@ -96,36 +70,9 @@ Boston, MA 02111-1307, USA. */ #undef ENDFILE_SPEC -#define ENDFILE_SPEC32 \ - "%{!shared:crtend.o%s} %{shared:crtendS.o%s} /usr/lib/crtn.o%s" - -#define ENDFILE_SPEC64 \ - "%{!shared:crtend.o%s} %{shared:crtendS.o%s} /usr/lib64/crtn.o%s" - -#define ENDFILE_SPEC_COMMON \ - "%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s}" - -#ifdef SPARC_BI_ARCH - -#if DEFAULT_ARCH32_P -#define ENDFILE_SPEC "\ -%{m32:" ENDFILE_SPEC32 "} \ -%{m64:" ENDFILE_SPEC64 "} \ -%{!m32:%{!m64:" ENDFILE_SPEC32 "}} " \ -ENDFILE_SPEC_COMMON -#else -#define ENDFILE_SPEC "\ -%{m32:" ENDFILE_SPEC32 "} \ -%{m64:" ENDFILE_SPEC64 "} \ -%{!m32:%{!m64:" ENDFILE_SPEC64 "}} " \ -ENDFILE_SPEC_COMMON -#endif - -#else - -#define ENDFILE_SPEC ENDFILE_SPEC64 " " ENDFILE_SPEC_COMMON - -#endif +#define ENDFILE_SPEC \ + "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s\ + %{ffast-math|funsafe-math-optimizations:crtfastmath.o%s}" /* The GNU C++ standard library requires that these macros be defined. */ #undef CPLUSPLUS_CPP_SPEC diff --git a/contrib/gcc/config/sparc/sol2-bi.h b/contrib/gcc/config/sparc/sol2-bi.h index 9828d63..e19e888 100644 --- a/contrib/gcc/config/sparc/sol2-bi.h +++ b/contrib/gcc/config/sparc/sol2-bi.h @@ -72,30 +72,6 @@ %{!mcpu*:%(asm_cpu_default)} \ " -#define STARTFILE_SPEC32 "\ -%{ansi:values-Xc.o%s} \ -%{!ansi: \ - %{traditional:values-Xt.o%s} \ - %{!traditional:values-Xa.o%s}}" - -#define STARTFILE_SPEC64 "\ -%{ansi:/usr/lib/sparcv9/values-Xc.o%s} \ -%{!ansi: \ - %{traditional:/usr/lib/sparcv9/values-Xt.o%s} \ - %{!traditional:/usr/lib/sparcv9/values-Xa.o%s}}" - -#if DEFAULT_ARCH32_P -#define STARTFILE_ARCH_SPEC "\ -%{m32:" STARTFILE_SPEC32 "} \ -%{m64:" STARTFILE_SPEC64 "} \ -%{!m32:%{!m64:" STARTFILE_SPEC32 "}}" -#else -#define STARTFILE_ARCH_SPEC "\ -%{m32:" STARTFILE_SPEC32 "} \ -%{m64:" STARTFILE_SPEC64 "} \ -%{!m32:%{!m64:" STARTFILE_SPEC64 "}}" -#endif - #undef STARTFILE_SPEC #define STARTFILE_SPEC "%{!shared: \ %{!symbolic: \ @@ -103,7 +79,10 @@ %{!p: \ %{pg:gcrt1.o%s gmon.o%s} \ %{!pg:crt1.o%s}}}} \ - crti.o%s " STARTFILE_ARCH_SPEC " \ + crti.o%s \ + %{ansi:values-Xc.o%s} \ + %{!ansi: %{traditional:values-Xt.o%s} \ + %{!traditional:values-Xa.o%s}} \ crtbegin.o%s" #undef CPP_CPU_DEFAULT_SPEC diff --git a/contrib/gcc/config/sparc/sparc.c b/contrib/gcc/config/sparc/sparc.c index 6ef28141c..c23cbef 100644 --- a/contrib/gcc/config/sparc/sparc.c +++ b/contrib/gcc/config/sparc/sparc.c @@ -8650,7 +8650,6 @@ set_extends (insn) return INTVAL (op1) >= 0; return (GET_CODE (op1) == REG && sparc_check_64 (op1, insn) == 1); } - case ASHIFT: case LSHIFTRT: return GET_MODE (SET_SRC (pat)) == SImode; /* Positive integers leave the high bits zero. */ diff --git a/contrib/gcc/config/sparc/sparc.md b/contrib/gcc/config/sparc/sparc.md index ebb6768..746dc72 100644 --- a/contrib/gcc/config/sparc/sparc.md +++ b/contrib/gcc/config/sparc/sparc.md @@ -2517,7 +2517,7 @@ ; }") -;; Be careful, fmovd does not exist when !arch64. +;; Be careful, fmovd does not exist when !v9. ;; We match MEM moves directly when we have correct even ;; numbered registers, but fall into splits otherwise. ;; The constraint ordering here is really important to @@ -2531,9 +2531,9 @@ (define_insn "*movdi_insn_sp32_v9" [(set (match_operand:DI 0 "nonimmediate_operand" - "=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?f") + "=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?f,?e,?e,?W") (match_operand:DI 1 "input_operand" - " J,J,U,T,r,o,i,r, f, T, o, f, f"))] + " J,J,U,T,r,o,i,r, f, T, o, f, f, e, W, e"))] "! TARGET_ARCH64 && TARGET_V9 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "@ @@ -2549,9 +2549,13 @@ ldd\\t%1, %0 # # - #" - [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,*") - (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,2")]) + # + fmovd\\t%1, %0 + ldd\\t%1, %0 + std\\t%1, %0" + [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,*,fpmove,fpload,fpstore") + (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,2,*,*,*") + (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,*,double,*,*")]) (define_insn "*movdi_insn_sp32" [(set (match_operand:DI 0 "nonimmediate_operand" @@ -2861,7 +2865,14 @@ (define_split [(set (match_operand:DI 0 "register_operand" "") (match_operand:DI 1 "const_double_operand" ""))] - "! TARGET_ARCH64 && reload_completed" + "reload_completed + && (! TARGET_V9 + || (! TARGET_ARCH64 + && ((GET_CODE (operands[0]) == REG + && REGNO (operands[0]) < 32) + || (GET_CODE (operands[0]) == SUBREG + && GET_CODE (SUBREG_REG (operands[0])) == REG + && REGNO (SUBREG_REG (operands[0])) < 32))))" [(clobber (const_int 0))] " { diff --git a/contrib/gcc/config/sparc/t-linux64 b/contrib/gcc/config/sparc/t-linux64 index a648626..3e3fa4c 100644 --- a/contrib/gcc/config/sparc/t-linux64 +++ b/contrib/gcc/config/sparc/t-linux64 @@ -1,8 +1,6 @@ -MULTILIB_OPTIONS = m64/m32 mno-app-regs|mcmodel=medany -MULTILIB_DIRNAMES = 64 32 alt -MULTILIB_MATCHES = mcmodel?medany=mcmodel?medmid -MULTILIB_EXCEPTIONS = m32/mno-app-regs* m32/mcmodel=* -MULTILIB_EXCLUSIONS = m32/!m64/mno-app-regs m32/!m64/mcmodel=medany +MULTILIB_OPTIONS = m64/m32 +MULTILIB_DIRNAMES = 64 32 +MULTILIB_OSDIRNAMES = ../lib64 ../lib LIBGCC = stmp-multilib INSTALL_LIBGCC = install-multilib @@ -10,10 +8,12 @@ INSTALL_LIBGCC = install-multilib EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o \ crtfastmath.o -SHLIB_SLIBDIR_SUFFIXES = 64:64 32: - # Override t-slibgcc-elf-ver to export some libgcc symbols with # the symbol versions that glibc used. # Avoid the t-linux version file. SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver \ $(srcdir)/config/sparc/libgcc-sparc-glibc.ver + +CRTSTUFF_T_CFLAGS = `if test x$$($(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) \ + -print-multi-os-directory) \ + = x../lib64; then echo -mcmodel=medany; fi` diff --git a/contrib/gcc/config/sparc/t-sol2-64 b/contrib/gcc/config/sparc/t-sol2-64 index 39204d7..3c15f0a 100644 --- a/contrib/gcc/config/sparc/t-sol2-64 +++ b/contrib/gcc/config/sparc/t-sol2-64 @@ -1,11 +1,10 @@ MULTILIB_OPTIONS = m32/m64 MULTILIB_DIRNAMES = sparcv7 sparcv9 MULTILIB_MATCHES = +MULTILIB_OSDIRNAMES = . sparcv9 LIBGCC = stmp-multilib INSTALL_LIBGCC = install-multilib EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o gmon.o crt1.o crti.o crtn.o gcrt1.o \ crtfastmath.o - -SHLIB_SLIBDIR_SUFFIXES = sparcv9:/sparcv9 sparcv7: diff --git a/contrib/gcc/cp/ChangeLog b/contrib/gcc/cp/ChangeLog index f75f91f..cc84a03 100644 --- a/contrib/gcc/cp/ChangeLog +++ b/contrib/gcc/cp/ChangeLog @@ -1,3 +1,54 @@ +2002-10-09 Zack Weinberg + + PR c/7353 + * decl.c (start_decl): Unconditionally issue error for + 'typedef foo = bar'. + (cp_finish_decl): Remove special case for TYPE_DECL with initializer. + (grokdeclarator): Remove redundant error for 'typedef foo = bar'. + +2002-10-03 Mark Mitchell + + PR c++/7754 + * decl2.c (finish_anon_union): Do not expand anonymous unions when + procesing template functions. + * pt.c (tsubst_decl, case VAR_DECL): Try to complete the variable + type. Call layout_decl. + (tsubst_expr, case DECL_STMT): Handle anonymous unions. + +2002-10-07 Richard Henderson + + * decl2.c: Complete reversion of c++/7754. + +2002-10-06 Roger Sayle + + PR optimization/6627 + * cp/cp-tree.h (enum ptrmemfunc_vbit_where_t): Delete definition + from here, and move it to tree.h. + * cp/decl.c (cxx_init_decl_processing): If storing the vbit + in function pointers, ensure that force_align_functions_log + is atleast one. + +2002-10-04 H.J. Lu (hjl@gnu.org) + + * pt.c (tsubst_decl, case VAR_DECL): Back out the last change. + (tsubst_expr, case DECL_STMT): Likewise. + +2002-10-02 Mark Mitchell + + PR c++/7754 + * decl2.c (finish_anon_union): Do not expand anonymous unions when + procesing template functions. + * pt.c (tsubst_decl, case VAR_DECL): Try to complete the variable + type. Call layout_decl. + (tsubst_expr, case DECL_STMT): Handle anonymous unions. + +2002-10-02 Mark Mitchell + + PR c++/7188. + * init.c (expand_member_init): Allow a FIELD_DECL to be passed in + directly. + * pt.c (tsubst_initializer_list): Use expand_member_init. + 2002-09-04 Jakub Jelinek * decl.c (start_cleanup_fn): Clear interface_only before @@ -336,7 +387,7 @@ 2002-04-29 Nathan Sidwell PR c++/5719 - * decl.c (grok_op_properties): Assignment ops don't have to return + * decl.c (grok_op_properties): Assignment ops don't have to return by value. operator% should. 2002-04-28 Franz Sirl @@ -420,7 +471,7 @@ (finish_init_stmts): Set STMT_EXPR_NO_SCOPE. * semantics.c (begin_gobal_stmt_expr): Adjust call to expand_start_stmt_expr. - + 2002-04-15 Mark Mitchell * decl.c (register_dtor_fn): Pass the address of dso_handle, not @@ -449,11 +500,11 @@ * typeck.c (type_after_usual_arithmetic_conversions): If two types have the same variant, return immediately. - When two floating-point operands are the same precision: + When two floating-point operands are the same precision: convert to float if one of the operands is float; if neither operand is one of the standard types, return the type of the first operand. - + 2002-04-12 Richard Sandiford * decl.c (duplicate_decls): Don't try to unify an implicit typedef @@ -511,7 +562,7 @@ set before checking it. PR c++/6179 - * method.c (implicitly_declare_fn): Pass unqualified type to + * method.c (implicitly_declare_fn): Pass unqualified type to synthesize_exception_spec. 2002-04-03 Jason Merrill @@ -576,7 +627,7 @@ PR c++/4884 * call.c (build_op_delete_call): Allow for the fact the placement may be a COMPOUND_EXPR. - + 2002-03-26 Nathan Sidwell PR c++/5682 @@ -630,7 +681,7 @@ 2002-03-18 Ashif Harji - * lang-specs.h (compiler default_compilers): Add + * lang-specs.h (compiler default_compilers): Add -no-integrated-cpp flag to invoke an external cpp. 2002-03-18 Jason Merrill @@ -747,7 +798,7 @@ with pointer to member conversions. 2002-03-08 Craig Rodrigues - + * cp-tree.h (CLEAR_BINFO_MARKED): Make both parts of conditional return void. @@ -781,7 +832,7 @@ * decl.c (finish_function): Only warn about missing return statement with -Wreturn-type. -2002-02-24 Craig Rodrigues +2002-02-24 Craig Rodrigues PR c++/4093 * cp-tree.h (SET_BINFO_MARKED): Cast false part of condition @@ -835,7 +886,7 @@ 2002-02-19 Jason Merrill - ABI change: Mangle `void (A::*)() const' as + ABI change: Mangle `void (A::*)() const' as M1AKFvvE, not MK1AFvvE. * mangle.c (write_function_type): Write cv-quals for member function type here. @@ -910,14 +961,14 @@ (coerce_template_template_parms, convert_template_argument, coerce_template_parms, maybe_get_template_decl_from_type_decl, lookup_template_class, tsubst_friend_function, tsubst_friend_class, - instantiate_class_template, tsubst_template_arg_vector, - tsubst_template_parms, tsubst_aggr_type, tsubst_default_argument, + instantiate_class_template, tsubst_template_arg_vector, + tsubst_template_parms, tsubst_aggr_type, tsubst_default_argument, tsubst_decl, tsubst_arg_types, tsubst_function_type, - tsubst_call_declarator_parms, tsubst, tsubst_copy, tsubst_expr, + tsubst_call_declarator_parms, tsubst, tsubst_copy, tsubst_expr, instantiate_template, fn_type_unification, - resolve_overloaded_unification, verify_class_unification, - unify, get_bindings_real, do_type_instantiation, - regenerate_decl_from_template, instantiate_decl, + resolve_overloaded_unification, verify_class_unification, + unify, get_bindings_real, do_type_instantiation, + regenerate_decl_from_template, instantiate_decl, tsubst_initializer_list, tsubst_enum, get_mostly_instantiated_function_type, invalid_nontype_parm_type_p): Likewise. @@ -978,7 +1029,7 @@ 2002-02-01 Jason Merrill PR c++/4872 - * decl.c (finish_function): Warn about a non-void function with + * decl.c (finish_function): Warn about a non-void function with no return statement and no abnormal exit. * cp-tree.h (struct cp_language_function): Add returns_abnormally. (current_function_returns_abnormally): New macro. diff --git a/contrib/gcc/cp/cp-tree.h b/contrib/gcc/cp/cp-tree.h index 787114f..4bd0879 100644 --- a/contrib/gcc/cp/cp-tree.h +++ b/contrib/gcc/cp/cp-tree.h @@ -2557,32 +2557,6 @@ extern int flag_new_for_scope; member function. [expr.unary.op]/3 */ #define PTRMEM_OK_P(NODE) TREE_LANG_FLAG_0 (NODE) -/* A pointer-to-function member type looks like: - - struct { - __P __pfn; - ptrdiff_t __delta; - }; - - If __pfn is NULL, it is a NULL pointer-to-member-function. - - (Because the vtable is always the first thing in the object, we - don't need its offset.) If the function is virtual, then PFN is - one plus twice the index into the vtable; otherwise, it is just a - pointer to the function. - - Unfortunately, using the lowest bit of PFN doesn't work in - architectures that don't impose alignment requirements on function - addresses, or that use the lowest bit to tell one ISA from another, - for example. For such architectures, we use the lowest bit of - DELTA instead of the lowest bit of the PFN, and DELTA will be - multiplied by 2. */ -enum ptrmemfunc_vbit_where_t -{ - ptrmemfunc_vbit_in_pfn, - ptrmemfunc_vbit_in_delta -}; - /* Get the POINTER_TYPE to the METHOD_TYPE associated with this pointer to member function. TYPE_PTRMEMFUNC_P _must_ be true, before using this macro. */ diff --git a/contrib/gcc/cp/decl.c b/contrib/gcc/cp/decl.c index 105e7a0..26484d7 100644 --- a/contrib/gcc/cp/decl.c +++ b/contrib/gcc/cp/decl.c @@ -6517,6 +6517,12 @@ cxx_init_decl_processing () flag_inline_functions = 0; } + /* Force minimum function alignment if using the least significant + bit of function pointers to store the virtual bit. */ + if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn + && force_align_functions_log < 1) + force_align_functions_log = 1; + /* Initially, C. */ current_lang_name = lang_name_c; @@ -7322,14 +7328,8 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes) switch (TREE_CODE (decl)) { case TYPE_DECL: - /* typedef foo = bar means give foo the same type as bar. - We haven't parsed bar yet, so `cp_finish_decl' will fix that up. - Any other case of an initialization in a TYPE_DECL is an error. */ - if (pedantic || list_length (declspecs) > 1) - { - error ("typedef `%D' is initialized", decl); - initialized = 0; - } + error ("typedef `%D' is initialized", decl); + initialized = 0; break; case FUNCTION_DECL: @@ -8241,12 +8241,6 @@ cp_finish_decl (decl, init, asmspec_tree, flags) /* Take care of TYPE_DECLs up front. */ if (TREE_CODE (decl) == TYPE_DECL) { - if (init && DECL_INITIAL (decl)) - { - /* typedef foo = bar; store the type of bar as the type of foo. */ - TREE_TYPE (decl) = type = TREE_TYPE (init); - DECL_INITIAL (decl) = init = NULL_TREE; - } if (type != error_mark_node && IS_AGGR_TYPE (type) && DECL_NAME (decl)) { @@ -11345,9 +11339,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) bad_specifiers (decl, "type", virtualp, quals != NULL_TREE, inlinep, friendp, raises != NULL_TREE); - if (initialized) - error ("typedef declaration includes an initializer"); - return decl; } diff --git a/contrib/gcc/cp/decl2.c b/contrib/gcc/cp/decl2.c index 0eb4799..4334963 100644 --- a/contrib/gcc/cp/decl2.c +++ b/contrib/gcc/cp/decl2.c @@ -1975,26 +1975,31 @@ finish_anon_union (anon_union_decl) return; } - main_decl = build_anon_union_vars (anon_union_decl, - &DECL_ANON_UNION_ELEMS (anon_union_decl), - static_p, external_p); - - if (main_decl == NULL_TREE) + if (!processing_template_decl) { - warning ("anonymous aggregate with no members"); - return; - } + main_decl + = build_anon_union_vars (anon_union_decl, + &DECL_ANON_UNION_ELEMS (anon_union_decl), + static_p, external_p); + + if (main_decl == NULL_TREE) + { + warning ("anonymous aggregate with no members"); + return; + } - if (static_p) - { - make_decl_rtl (main_decl, 0); - COPY_DECL_RTL (main_decl, anon_union_decl); - expand_anon_union_decl (anon_union_decl, - NULL_TREE, - DECL_ANON_UNION_ELEMS (anon_union_decl)); + if (static_p) + { + make_decl_rtl (main_decl, 0); + COPY_DECL_RTL (main_decl, anon_union_decl); + expand_anon_union_decl (anon_union_decl, + NULL_TREE, + DECL_ANON_UNION_ELEMS (anon_union_decl)); + return; + } } - else - add_decl_stmt (anon_union_decl); + + add_decl_stmt (anon_union_decl); } /* Finish processing a builtin type TYPE. It's name is NAME, diff --git a/contrib/gcc/cp/init.c b/contrib/gcc/cp/init.c index 369e511..a46d853 100644 --- a/contrib/gcc/cp/init.c +++ b/contrib/gcc/cp/init.c @@ -1094,7 +1094,10 @@ expand_member_init (exp, name, init) } else { - field = lookup_field (type, name, 1, 0); + if (TREE_CODE (name) == IDENTIFIER_NODE) + field = lookup_field (type, name, 1, 0); + else + field = name; if (! member_init_ok_or_else (field, type, name)) return NULL_TREE; diff --git a/contrib/gcc/cp/pt.c b/contrib/gcc/cp/pt.c index 2180e4b..8fc9f74 100644 --- a/contrib/gcc/cp/pt.c +++ b/contrib/gcc/cp/pt.c @@ -6079,6 +6079,8 @@ tsubst_decl (t, args, type, complain) } r = copy_decl (t); + if (TREE_CODE (r) == VAR_DECL) + type = complete_type (type); TREE_TYPE (r) = type; c_apply_type_quals_to_decl (cp_type_quals (type), r); DECL_CONTEXT (r) = ctx; @@ -6115,6 +6117,8 @@ tsubst_decl (t, args, type, complain) TREE_CHAIN (r) = NULL_TREE; if (TREE_CODE (r) == VAR_DECL && VOID_TYPE_P (type)) cp_error_at ("instantiation of `%D' as type `%T'", r, type); + /* Compute the size, alignment, etc. of R. */ + layout_decl (r, 0); } break; @@ -7374,9 +7378,6 @@ tsubst_expr (t, args, complain, in_decl) decl = tsubst (decl, args, complain, in_decl); if (decl != error_mark_node) { - if (TREE_CODE (decl) != TYPE_DECL) - /* Make sure the type is instantiated now. */ - complete_type (TREE_TYPE (decl)); if (init) DECL_INITIAL (decl) = error_mark_node; /* By marking the declaration as instantiated, we avoid @@ -7386,19 +7387,26 @@ tsubst_expr (t, args, complain, in_decl) do. */ if (TREE_CODE (decl) == VAR_DECL) DECL_TEMPLATE_INSTANTIATED (decl) = 1; - maybe_push_decl (decl); - if (DECL_PRETTY_FUNCTION_P (decl)) + if (TREE_CODE (decl) == VAR_DECL + && ANON_AGGR_TYPE_P (TREE_TYPE (decl))) + /* Anonymous aggregates are a special case. */ + finish_anon_union (decl); + else { - /* For __PRETTY_FUNCTION__ we have to adjust the - initializer. */ - const char *const name - = (*decl_printable_name) (current_function_decl, 2); - init = cp_fname_init (name); - TREE_TYPE (decl) = TREE_TYPE (init); + maybe_push_decl (decl); + if (DECL_PRETTY_FUNCTION_P (decl)) + { + /* For __PRETTY_FUNCTION__ we have to adjust the + initializer. */ + const char *const name + = (*decl_printable_name) (current_function_decl, 2); + init = cp_fname_init (name); + TREE_TYPE (decl) = TREE_TYPE (init); + } + else + init = tsubst_expr (init, args, complain, in_decl); + cp_finish_decl (decl, init, NULL_TREE, 0); } - else - init = tsubst_expr (init, args, complain, in_decl); - cp_finish_decl (decl, init, NULL_TREE, 0); } } @@ -10274,8 +10282,10 @@ tsubst_initializer_list (t, argvec) else init = convert_from_reference (init); - *p = build_tree_list (decl, init); - p = &TREE_CHAIN (*p); + *p = expand_member_init (current_class_ref, decl, + init ? init : void_type_node); + if (*p) + p = &TREE_CHAIN (*p); } return first; } diff --git a/contrib/gcc/cppinit.c b/contrib/gcc/cppinit.c index adaa30f..c7d5041 100644 --- a/contrib/gcc/cppinit.c +++ b/contrib/gcc/cppinit.c @@ -103,9 +103,13 @@ static void mark_named_operators PARAMS ((cpp_reader *)); static void append_include_chain PARAMS ((cpp_reader *, char *, int, int)); static struct search_path * remove_dup_dir PARAMS ((cpp_reader *, + struct search_path *, + struct search_path **)); +static struct search_path * remove_dup_nonsys_dirs PARAMS ((cpp_reader *, + struct search_path **, struct search_path *)); static struct search_path * remove_dup_dirs PARAMS ((cpp_reader *, - struct search_path *)); + struct search_path **)); static void merge_include_chains PARAMS ((cpp_reader *)); static bool push_include PARAMS ((cpp_reader *, struct pending_option *)); @@ -272,55 +276,98 @@ append_include_chain (pfile, dir, path, cxx_aware) } /* Handle a duplicated include path. PREV is the link in the chain - before the duplicate. The duplicate is removed from the chain and - freed. Returns PREV. */ + before the duplicate, or NULL if the duplicate is at the head of + the chain. The duplicate is removed from the chain and freed. + Returns PREV. */ static struct search_path * -remove_dup_dir (pfile, prev) +remove_dup_dir (pfile, prev, head_ptr) cpp_reader *pfile; struct search_path *prev; + struct search_path **head_ptr; { - struct search_path *cur = prev->next; + struct search_path *cur; + + if (prev != NULL) + { + cur = prev->next; + prev->next = cur->next; + } + else + { + cur = *head_ptr; + *head_ptr = cur->next; + } if (CPP_OPTION (pfile, verbose)) fprintf (stderr, _("ignoring duplicate directory \"%s\"\n"), cur->name); - prev->next = cur->next; free ((PTR) cur->name); free (cur); return prev; } +/* Remove duplicate non-system directories for which there is an equivalent + system directory later in the chain. The range for removal is between + *HEAD_PTR and END. Returns the directory before END, or NULL if none. + This algorithm is quadratic in the number of system directories, which is + acceptable since there aren't usually that many of them. */ +static struct search_path * +remove_dup_nonsys_dirs (pfile, head_ptr, end) + cpp_reader *pfile; + struct search_path **head_ptr; + struct search_path *end; +{ + int sysdir = 0; + struct search_path *prev = NULL, *cur, *other; + + for (cur = *head_ptr; cur; cur = cur->next) + { + if (cur->sysp) + { + sysdir = 1; + for (other = *head_ptr, prev = NULL; + other != end; + other = other ? other->next : *head_ptr) + { + if (!other->sysp + && INO_T_EQ (cur->ino, other->ino) + && cur->dev == other->dev) + { + other = remove_dup_dir (pfile, prev, head_ptr); + if (CPP_OPTION (pfile, verbose)) + fprintf (stderr, + _(" as it is a non-system directory that duplicates a system directory\n")); + } + prev = other; + } + } + } + + if (!sysdir) + for (cur = *head_ptr; cur != end; cur = cur->next) + prev = cur; + + return prev; +} + /* Remove duplicate directories from a chain. Returns the tail of the chain, or NULL if the chain is empty. This algorithm is quadratic in the number of -I switches, which is acceptable since there aren't usually that many of them. */ static struct search_path * -remove_dup_dirs (pfile, head) +remove_dup_dirs (pfile, head_ptr) cpp_reader *pfile; - struct search_path *head; + struct search_path **head_ptr; { struct search_path *prev = NULL, *cur, *other; - for (cur = head; cur; cur = cur->next) + for (cur = *head_ptr; cur; cur = cur->next) { - for (other = head; other != cur; other = other->next) + for (other = *head_ptr; other != cur; other = other->next) if (INO_T_EQ (cur->ino, other->ino) && cur->dev == other->dev) { - if (cur->sysp && !other->sysp) - { - cpp_warning (pfile, - "changing search order for system directory \"%s\"", - cur->name); - if (strcmp (cur->name, other->name)) - cpp_warning (pfile, - " as it is the same as non-system directory \"%s\"", - other->name); - else - cpp_warning (pfile, - " as it has already been specified as a non-system directory"); - } - cur = remove_dup_dir (pfile, prev); + cur = remove_dup_dir (pfile, prev, head_ptr); break; } prev = cur; @@ -358,28 +405,33 @@ merge_include_chains (pfile) else brack = systm; - /* This is a bit tricky. First we drop dupes from the quote-include - list. Then we drop dupes from the bracket-include list. - Finally, if qtail and brack are the same directory, we cut out - brack and move brack up to point to qtail. + /* This is a bit tricky. First we drop non-system dupes of system + directories from the merged bracket-include list. Next we drop + dupes from the bracket and quote include lists. Then we drop + non-system dupes from the merged quote-include list. Finally, + if qtail and brack are the same directory, we cut out brack and + move brack up to point to qtail. We can't just merge the lists and then uniquify them because then we may lose directories from the <> search path that should - be there; consider -Ifoo -Ibar -I- -Ifoo -Iquux. It is however + be there; consider -Ifoo -Ibar -I- -Ifoo -Iquux. It is however safe to treat -Ibar -Ifoo -I- -Ifoo -Iquux as if written -Ibar -I- -Ifoo -Iquux. */ - remove_dup_dirs (pfile, brack); - qtail = remove_dup_dirs (pfile, quote); + remove_dup_nonsys_dirs (pfile, &brack, systm); + remove_dup_dirs (pfile, &brack); if (quote) { + qtail = remove_dup_dirs (pfile, "e); qtail->next = brack; + qtail = remove_dup_nonsys_dirs (pfile, "e, brack); + /* If brack == qtail, remove brack as it's simpler. */ - if (brack && INO_T_EQ (qtail->ino, brack->ino) + if (qtail && brack && INO_T_EQ (qtail->ino, brack->ino) && qtail->dev == brack->dev) - brack = remove_dup_dir (pfile, qtail); + brack = remove_dup_dir (pfile, qtail, "e); } else quote = brack; @@ -848,7 +900,7 @@ init_standard_includes (pfile) && !CPP_OPTION (pfile, no_standard_cplusplus_includes))) { /* Does this dir start with the prefix? */ - if (!memcmp (p->fname, default_prefix, default_len)) + if (!strncmp (p->fname, default_prefix, default_len)) { /* Yes; change prefix and add to search list. */ int flen = strlen (p->fname); @@ -1296,7 +1348,7 @@ parse_option (input) md = (mn + mx) / 2; opt_len = cl_options[md].opt_len; - comp = memcmp (input, cl_options[md].opt_text, opt_len); + comp = strncmp (input, cl_options[md].opt_text, opt_len); if (comp > 0) mn = md + 1; @@ -1321,7 +1373,7 @@ parse_option (input) for (; mn < (unsigned int) N_OPTS; mn++) { opt_len = cl_options[mn].opt_len; - if (memcmp (input, cl_options[mn].opt_text, opt_len)) + if (strncmp (input, cl_options[mn].opt_text, opt_len)) break; if (input[opt_len] == '\0') return mn; diff --git a/contrib/gcc/cpplib.c b/contrib/gcc/cpplib.c index 096a711..cff9eeb 100644 --- a/contrib/gcc/cpplib.c +++ b/contrib/gcc/cpplib.c @@ -1224,6 +1224,9 @@ destringize_and_run (pfile, in) { const unsigned char *src, *limit; char *dest, *result; + cpp_context saved_context; + cpp_context *saved_cur_context; + unsigned int saved_line; dest = result = alloca (in->len + 1); for (src = in->text, limit = src + in->len; src < limit;) @@ -1235,7 +1238,40 @@ destringize_and_run (pfile, in) } *dest = '\0'; + /* FIXME. All this saving is a horrible kludge to handle the case + when we're in a macro expansion. + + A better strategy it to not convert _Pragma to #pragma if doing + preprocessed output, but to just pass it through as-is, unless it + is a CPP pragma in which case is should be processed normally. + When compiling the preprocessed output the _Pragma should be + handled. This will be become necessary when we move to + line-at-a-time lexing since we will be macro-expanding the line + before outputting / compiling it. */ + saved_line = pfile->line; + saved_context = pfile->base_context; + saved_cur_context = pfile->context; + pfile->context = &pfile->base_context; run_directive (pfile, T_PRAGMA, result, dest - result); + pfile->context = saved_cur_context; + pfile->base_context = saved_context; + pfile->line = saved_line; + + /* See above comment. For the moment, we'd like + + token1 _Pragma ("foo") token2 + + to be output as + + token1 + # 7 "file.c" + #pragma foo + # 7 "file.c" + token2 + + Getting the line markers is a little tricky. */ + if (pfile->cb.line_change) + (*pfile->cb.line_change) (pfile, pfile->cur_token, false); } /* Handle the _Pragma operator. */ @@ -1245,25 +1281,10 @@ _cpp_do__Pragma (pfile) { const cpp_token *string = get__Pragma_string (pfile); - if (!string) - cpp_error (pfile, "_Pragma takes a parenthesized string literal"); + if (string) + destringize_and_run (pfile, &string->val.str); else - { - /* Ideally, we'd like - token1 _Pragma ("foo") token2 - to be output as - token1 - # 7 "file.c" - #pragma foo - # 7 "file.c" - token2 - Getting these correct line markers is a little tricky. */ - - unsigned int orig_line = pfile->line; - destringize_and_run (pfile, &string->val.str); - pfile->line = orig_line; - pfile->buffer->saved_flags = BOL; - } + cpp_error (pfile, "_Pragma takes a parenthesized string literal"); } /* Just ignore #sccs, on systems where we define it at all. */ diff --git a/contrib/gcc/cppmacro.c b/contrib/gcc/cppmacro.c index c85ac21..70e52fd 100644 --- a/contrib/gcc/cppmacro.c +++ b/contrib/gcc/cppmacro.c @@ -348,6 +348,12 @@ stringify_arg (pfile, arg) } /* Commit the memory, including NUL, and return the token. */ + if ((size_t) (BUFF_LIMIT (pfile->u_buff) - dest) < 1) + { + size_t len_so_far = dest - BUFF_FRONT (pfile->u_buff); + _cpp_extend_buff (pfile, &pfile->u_buff, 1); + dest = BUFF_FRONT (pfile->u_buff) + len_so_far; + } len = dest - BUFF_FRONT (pfile->u_buff); BUFF_FRONT (pfile->u_buff) = dest + 1; return new_string_token (pfile, dest - len, len); diff --git a/contrib/gcc/doc/cpp.texi b/contrib/gcc/doc/cpp.texi index 8e829d8..39e6a28 100644 --- a/contrib/gcc/doc/cpp.texi +++ b/contrib/gcc/doc/cpp.texi @@ -830,11 +830,22 @@ version of GCC in use. You can add to this list with the @option{-I@var{dir}} command line option. All the directories named by @option{-I} are searched, in -left-to-right order, @emph{before} the default directories. You can -also prevent GCC from searching any of the default directories with the -@option{-nostdinc} option. This is useful when you are compiling an +left-to-right order, @emph{before} the default directories. The only +exception is when @file{dir} is already searched by default. In +this case, the option is ignored and the search order for system +directories remains unchanged. + +Duplicate directories are removed from the quote and bracket search +chains before the two chains are merged to make the final search chain. +Thus, it is possible for a directory to occur twice in the final search +chain if it was specified in both the quote and bracket chains. + +You can prevent GCC from searching any of the default directories with +the @option{-nostdinc} option. This is useful when you are compiling an operating system kernel or some other program that does not use the standard C library facilities, or the standard C library itself. +@option{-I} options are not ignored as described above when +@option{-nostdinc} is in effect. GCC looks for headers requested with @code{@w{#include "@var{file}"}} first in the directory containing the current file, then in the same @@ -843,12 +854,6 @@ For example, if @file{/usr/include/sys/stat.h} contains @code{@w{#include "types.h"}}, GCC looks for @file{types.h} first in @file{/usr/include/sys}, then in its usual search path. -If you name a search directory with @option{-I@var{dir}} that is also a -system include directory, the @option{-I} wins; the directory will be -searched according to the @option{-I} ordering, and it will not be -treated as a system include directory. GCC will warn you when a system -include directory is hidden in this way. - @samp{#line} (@pxref{Line Control}) does not change GCC's idea of the directory containing the current file. @@ -1081,8 +1086,8 @@ found in that directory will be considered system headers. All directories named by @option{-isystem} are searched @emph{after} all directories named by @option{-I}, no matter what their order was on the command line. If the same directory is named by both @option{-I} and -@option{-isystem}, @option{-I} wins; it is as if the @option{-isystem} option -had never been specified at all. GCC warns you when this happens. +@option{-isystem}, the @option{-I} option is ignored. GCC provides an +informative message when this occurs if @option{-v} is used. @findex #pragma GCC system_header There is also a directive, @code{@w{#pragma GCC system_header}}, which @@ -1815,9 +1820,7 @@ conformance to the C Standard. GNU CPP follows the host convention when processing system header files, but when processing user files @code{__STDC__} is always 1. This has been reported to cause problems; for instance, some versions of Solaris provide X Windows headers that -expect @code{__STDC__} to be either undefined or 1. You may be able to -work around this sort of problem by using an @option{-I} option to -cancel treatment of those headers as system headers. @xref{Invocation}. +expect @code{__STDC__} to be either undefined or 1. @xref{Invocation}. @item __STDC_VERSION__ This macro expands to the C Standard's version number, a long integer @@ -3733,9 +3736,9 @@ Here are a few more obsolete features. @item Attempting to paste two tokens which together do not form a valid preprocessing token. -The preprocessor currently warns about this and outputs the two tokens -adjacently, which is probably the behavior the programmer intends. It -may not work in future, though. +The preprocessor currently warns about this, and the resulting +preprocessed output is undefined. The tokens remain distinct if the +preprocessor is being used directly by the compiler front end. Most of the time, when you get this warning, you will find that @samp{##} is being used superstitiously, to guard against whitespace appearing diff --git a/contrib/gcc/doc/extend.texi b/contrib/gcc/doc/extend.texi index 79eea70..281e4ac 100644 --- a/contrib/gcc/doc/extend.texi +++ b/contrib/gcc/doc/extend.texi @@ -385,7 +385,6 @@ extensions, accepted by GCC in C89 mode and in C++. * Labels as Values:: Getting pointers to labels, and computed gotos. * Nested Functions:: As in Algol and Pascal, lexical scoping of functions. * Constructing Calls:: Dispatching a call to another function. -* Naming Types:: Giving a name to the type of some expression. * Typeof:: @code{typeof}: referring to the type of an expression. * Lvalues:: Using @samp{?:}, @samp{,} and casts in lvalues. * Conditionals:: Omitting the middle operand of a @samp{?:} expression. @@ -495,8 +494,7 @@ the value of an enumeration constant, the width of a bit-field, or the initial value of a static variable. If you don't know the type of the operand, you can still do this, but you -must use @code{typeof} (@pxref{Typeof}) or type naming (@pxref{Naming -Types}). +must use @code{typeof} (@pxref{Typeof}). Statement expressions are not supported fully in G++, and their fate there is unclear. (It is possible that they will become fully supported @@ -845,29 +843,6 @@ the containing function. You should specify, for @var{result}, a value returned by @code{__builtin_apply}. @end deftypefn -@node Naming Types -@section Naming an Expression's Type -@cindex naming types - -You can give a name to the type of an expression using a @code{typedef} -declaration with an initializer. Here is how to define @var{name} as a -type name for the type of @var{exp}: - -@example -typedef @var{name} = @var{exp}; -@end example - -This is useful in conjunction with the statements-within-expressions -feature. Here is how the two together can be used to define a safe -``maximum'' macro that operates on any arithmetic type: - -@example -#define max(a,b) \ - (@{typedef _ta = (a), _tb = (b); \ - _ta _a = (a); _tb _b = (b); \ - _a > _b ? _a : _b; @}) -@end example - @cindex underscores in variables in macros @cindex @samp{_} in variables in macros @cindex local variables in macros @@ -919,6 +894,21 @@ A @code{typeof}-construct can be used anywhere a typedef name could be used. For example, you can use it in a declaration, in a cast, or inside of @code{sizeof} or @code{typeof}. +@code{typeof} is often useful in conjunction with the +statements-within-expressions feature. Here is how the two together can +be used to define a safe ``maximum'' macro that operates on any +arithmetic type and evaluates each of its arguments exactly once: + +@example +#define max(a,b) \ + (@{ typeof (a) _a = (a); \ + typeof (b) _b = (b); \ + _a > _b ? _a : _b; @}) +@end example + +@noindent +Some more examples of the use of @code{typeof}: + @itemize @bullet @item This declares @code{y} with the type of what @code{x} points to. @@ -968,6 +958,26 @@ Thus, @code{array (pointer (char), 4)} is the type of arrays of 4 pointers to @code{char}. @end itemize +@emph{Compatibility Note:} In addition to @code{typeof}, GCC 2 supported +a more limited extension which permitted one to write + +@example +typedef @var{T} = @var{expr}; +@end example + +@noindent +with the effect of declaring @var{T} to have the type of the expression +@var{expr}. This extension does not work with GCC 3 (versions between +3.0 and 3.2 will crash; 3.2.1 and later give an error). Code which +relies on it should be rewritten to use @code{typeof}: + +@example +typedef typeof(@var{expr}) @var{T}; +@end example + +@noindent +This will work with all versions of GCC@. + @node Lvalues @section Generalized Lvalues @cindex compound expressions as lvalues @@ -6170,12 +6180,12 @@ the minimum value of variables @var{i} and @var{j}. However, side effects in @code{X} or @code{Y} may cause unintended behavior. For example, @code{MIN (i++, j++)} will fail, incrementing -the smaller counter twice. A GNU C extension allows you to write safe -macros that avoid this kind of problem (@pxref{Naming Types,,Naming an -Expression's Type}). However, writing @code{MIN} and @code{MAX} as -macros also forces you to use function-call notation for a -fundamental arithmetic operation. Using GNU C++ extensions, you can -write @w{@samp{int min = i ?} are built into the compiler, they properly handle expressions with side-effects; @w{@samp{int min = i++ t1 - abs_inc; + If the loop has been unrolled, the full calculation is + + t1 = abs_inc * unroll_number; increment per loop + n = abs (final - initial) / t1; full loops + n += (abs (final - initial) % t1) != 0; partial loop + + However, in certain cases the unrolled loop will be preconditioned + by emitting copies of the loop body with conditional branches, + so that the unrolled loop is always a full loop and thus needs + no exit tests. In this case we don't want to add the partial + loop count. As above, when t1 is a power of two we don't need to + worry about overflow. The division and modulo operations can be avoided by requiring that the increment is a power of 2 (precondition_loop_p enforces @@ -658,58 +668,32 @@ doloop_modify_runtime (loop, iterations_max, fprintf (loop_dump_stream, "Doloop: Basic induction var skips initial incr.\n"); - diff = expand_simple_binop (mode, PLUS, diff, increment, diff, - unsigned_p, OPTAB_LIB_WIDEN); + diff = expand_simple_binop (mode, PLUS, diff, GEN_INT (abs_inc), + diff, unsigned_p, OPTAB_LIB_WIDEN); } } - if (abs_inc * loop_info->unroll_number != 1) + abs_loop_inc = abs_inc * loop_info->unroll_number; + if (abs_loop_inc != 1) { int shift_count; - rtx extra; - rtx label; - unsigned HOST_WIDE_INT limit; - shift_count = exact_log2 (abs_inc * loop_info->unroll_number); + shift_count = exact_log2 (abs_loop_inc); if (shift_count < 0) abort (); - /* abs (final - initial) / (abs_inc * unroll_number) */ - iterations = expand_simple_binop (GET_MODE (diff), LSHIFTRT, - diff, GEN_INT (shift_count), - NULL_RTX, 1, - OPTAB_LIB_WIDEN); - - if (abs_inc != 1) - { - /* abs (final - initial) % (abs_inc * unroll_number) */ - rtx count = GEN_INT (abs_inc * loop_info->unroll_number - 1); - extra = expand_simple_binop (GET_MODE (iterations), AND, - diff, count, NULL_RTX, 1, - OPTAB_LIB_WIDEN); - - /* If (abs (final - initial) % (abs_inc * unroll_number) - <= abs_inc * (unroll - 1)), - jump past following increment instruction. */ - label = gen_label_rtx (); - limit = abs_inc * (loop_info->unroll_number - 1); - emit_cmp_and_jump_insns (extra, GEN_INT (limit), - limit == 0 ? EQ : LEU, NULL_RTX, - GET_MODE (extra), 0, label); - JUMP_LABEL (get_last_insn ()) = label; - LABEL_NUSES (label)++; - - /* Increment the iteration count by one. */ - iterations = expand_simple_binop (GET_MODE (iterations), PLUS, - iterations, GEN_INT (1), - iterations, 1, - OPTAB_LIB_WIDEN); + if (!loop_info->preconditioned) + diff = expand_simple_binop (GET_MODE (diff), PLUS, + diff, GEN_INT (abs_loop_inc - 1), + diff, 1, OPTAB_LIB_WIDEN); - emit_label (label); - } + /* (abs (final - initial) + abs_inc * unroll_number - 1) + / (abs_inc * unroll_number) */ + diff = expand_simple_binop (GET_MODE (diff), LSHIFTRT, + diff, GEN_INT (shift_count), + diff, 1, OPTAB_LIB_WIDEN); } - else - iterations = diff; + iterations = diff; /* If there is a NOTE_INSN_LOOP_VTOP, we have a `for' or `while' style loop, with a loop exit test at the start. Thus, we can @@ -722,17 +706,20 @@ doloop_modify_runtime (loop, iterations_max, iteration count to one if necessary. */ if (! loop->vtop) { - rtx label; - if (loop_dump_stream) fprintf (loop_dump_stream, "Doloop: Do-while loop.\n"); - /* A `do-while' loop must iterate at least once. If the - iteration count is bogus, we set the iteration count to 1. + /* A `do-while' loop must iterate at least once. For code like + i = initial; do { ... } while (++i < final); + we will calculate a bogus iteration count if initial > final. + So detect this and set the iteration count to 1. Note that if the loop has been unrolled, then the loop body - is guaranteed to execute at least once. */ - if (loop_info->unroll_number == 1) + is guaranteed to execute at least once. Also, when the + comparison is NE, our calculated count will be OK. */ + if (loop_info->unroll_number == 1 && comparison_code != NE) { + rtx label; + /* Emit insns to test if the loop will immediately terminate and to set the iteration count to 1 if true. */ label = gen_label_rtx(); diff --git a/contrib/gcc/expr.c b/contrib/gcc/expr.c index 2a5c6f9..99f7fcf 100644 --- a/contrib/gcc/expr.c +++ b/contrib/gcc/expr.c @@ -5434,16 +5434,13 @@ rtx force_operand (value, target) rtx value, target; { - optab binoptab = 0; - /* Use a temporary to force order of execution of calls to - `force_operand'. */ - rtx tmp; - rtx op2; + rtx op1, op2; /* Use subtarget as the target for operand 0 of a binary operation. */ rtx subtarget = get_subtarget (target); + enum rtx_code code = GET_CODE (value); /* Check for a PIC address load. */ - if ((GET_CODE (value) == PLUS || GET_CODE (value) == MINUS) + if ((code == PLUS || code == MINUS) && XEXP (value, 0) == pic_offset_table_rtx && (GET_CODE (XEXP (value, 1)) == SYMBOL_REF || GET_CODE (XEXP (value, 1)) == LABEL_REF @@ -5455,60 +5452,88 @@ force_operand (value, target) return subtarget; } - if (GET_CODE (value) == PLUS) - binoptab = add_optab; - else if (GET_CODE (value) == MINUS) - binoptab = sub_optab; - else if (GET_CODE (value) == MULT) + if (code == ZERO_EXTEND || code == SIGN_EXTEND) { - op2 = XEXP (value, 1); - if (!CONSTANT_P (op2) - && !(GET_CODE (op2) == REG && op2 != subtarget)) - subtarget = 0; - tmp = force_operand (XEXP (value, 0), subtarget); - return expand_mult (GET_MODE (value), tmp, - force_operand (op2, NULL_RTX), - target, 1); + if (!target) + target = gen_reg_rtx (GET_MODE (value)); + convert_move (target, force_operand (XEXP (value, 0), NULL), + code == ZERO_EXTEND); + return target; } - if (binoptab) + if (GET_RTX_CLASS (code) == '2' || GET_RTX_CLASS (code) == 'c') { op2 = XEXP (value, 1); - if (!CONSTANT_P (op2) - && !(GET_CODE (op2) == REG && op2 != subtarget)) + if (!CONSTANT_P (op2) && !(GET_CODE (op2) == REG && op2 != subtarget)) subtarget = 0; - if (binoptab == sub_optab && GET_CODE (op2) == CONST_INT) + if (code == MINUS && GET_CODE (op2) == CONST_INT) { - binoptab = add_optab; + code = PLUS; op2 = negate_rtx (GET_MODE (value), op2); } /* Check for an addition with OP2 a constant integer and our first - operand a PLUS of a virtual register and something else. In that - case, we want to emit the sum of the virtual register and the - constant first and then add the other value. This allows virtual - register instantiation to simply modify the constant rather than - creating another one around this addition. */ - if (binoptab == add_optab && GET_CODE (op2) == CONST_INT + operand a PLUS of a virtual register and something else. In that + case, we want to emit the sum of the virtual register and the + constant first and then add the other value. This allows virtual + register instantiation to simply modify the constant rather than + creating another one around this addition. */ + if (code == PLUS && GET_CODE (op2) == CONST_INT && GET_CODE (XEXP (value, 0)) == PLUS && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG && REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER) { - rtx temp = expand_binop (GET_MODE (value), binoptab, - XEXP (XEXP (value, 0), 0), op2, - subtarget, 0, OPTAB_LIB_WIDEN); - return expand_binop (GET_MODE (value), binoptab, temp, - force_operand (XEXP (XEXP (value, 0), 1), 0), - target, 0, OPTAB_LIB_WIDEN); + rtx temp = expand_simple_binop (GET_MODE (value), code, + XEXP (XEXP (value, 0), 0), op2, + subtarget, 0, OPTAB_LIB_WIDEN); + return expand_simple_binop (GET_MODE (value), code, temp, + force_operand (XEXP (XEXP (value, + 0), 1), 0), + target, 0, OPTAB_LIB_WIDEN); + } + + op1 = force_operand (XEXP (value, 0), subtarget); + op2 = force_operand (op2, NULL_RTX); + switch (code) + { + case MULT: + return expand_mult (GET_MODE (value), op1, op2, target, 1); + case DIV: + if (!INTEGRAL_MODE_P (GET_MODE (value))) + return expand_simple_binop (GET_MODE (value), code, op1, op2, + target, 1, OPTAB_LIB_WIDEN); + else + return expand_divmod (0, + FLOAT_MODE_P (GET_MODE (value)) + ? RDIV_EXPR : TRUNC_DIV_EXPR, + GET_MODE (value), op1, op2, target, 0); + break; + case MOD: + return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2, + target, 0); + break; + case UDIV: + return expand_divmod (0, TRUNC_DIV_EXPR, GET_MODE (value), op1, op2, + target, 1); + break; + case UMOD: + return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2, + target, 1); + break; + case ASHIFTRT: + return expand_simple_binop (GET_MODE (value), code, op1, op2, + target, 0, OPTAB_LIB_WIDEN); + break; + default: + return expand_simple_binop (GET_MODE (value), code, op1, op2, + target, 1, OPTAB_LIB_WIDEN); } - - tmp = force_operand (XEXP (value, 0), subtarget); - return expand_binop (GET_MODE (value), binoptab, tmp, - force_operand (op2, NULL_RTX), - target, 0, OPTAB_LIB_WIDEN); - /* We give UNSIGNEDP = 0 to expand_binop - because the only operations we are expanding here are signed ones. */ + } + if (GET_RTX_CLASS (code) == '1') + { + op1 = force_operand (XEXP (value, 0), NULL_RTX); + return expand_simple_unop (GET_MODE (value), code, op1, target, 0); } #ifdef INSN_SCHEDULING @@ -7563,16 +7588,23 @@ expand_expr (exp, target, tmode, modifier) } } + if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1)) + subtarget = 0; + /* No sense saving up arithmetic to be done if it's all in the wrong mode to form part of an address. And force_operand won't know whether to sign-extend or zero-extend. */ if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER) || mode != ptr_mode) - goto binop; - - if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1)) - subtarget = 0; + { + op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); + op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); + temp = simplify_binary_operation (PLUS, mode, op0, op1); + if (temp) + return temp; + goto binop2; + } op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier); op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier); diff --git a/contrib/gcc/f/version.c b/contrib/gcc/f/version.c index b9dc05c..a420cc9 100644 --- a/contrib/gcc/f/version.c +++ b/contrib/gcc/f/version.c @@ -1,4 +1,4 @@ #include "ansidecl.h" #include "f/version.h" -const char *const ffe_version_string = "3.2.1 20020916 (prerelease)"; +const char *const ffe_version_string = "3.2.1 20021009 (prerelease)"; diff --git a/contrib/gcc/flags.h b/contrib/gcc/flags.h index 40d42f2..85e0792 100644 --- a/contrib/gcc/flags.h +++ b/contrib/gcc/flags.h @@ -604,6 +604,10 @@ extern int align_labels_max_skip; extern int align_functions; extern int align_functions_log; +/* Like align_functions_log above, but used by front-ends to force the + minimum function alignment. Zero means no alignment is forced. */ +extern int force_align_functions_log; + /* Nonzero if we dump in VCG format, not plain text. */ extern int dump_for_graph; diff --git a/contrib/gcc/gcc.c b/contrib/gcc/gcc.c index 9604516..cf86f9b 100644 --- a/contrib/gcc/gcc.c +++ b/contrib/gcc/gcc.c @@ -172,6 +172,11 @@ static const char *print_prog_name = NULL; static int print_multi_directory; +/* Flag saying to print the relative path we'd use to + find OS libraries given the current compiler flags. */ + +static int print_multi_os_directory; + /* Flag saying to print the list of subdirectories and compiler flags used to select them in a standard form. */ @@ -285,9 +290,10 @@ static struct compiler *lookup_compiler PARAMS ((const char *, size_t, const cha static char *build_search_list PARAMS ((struct path_prefix *, const char *, int)); static void putenv_from_prefixes PARAMS ((struct path_prefix *, const char *)); static int access_check PARAMS ((const char *, int)); -static char *find_a_file PARAMS ((struct path_prefix *, const char *, int)); +static char *find_a_file PARAMS ((struct path_prefix *, const char *, + int, int)); static void add_prefix PARAMS ((struct path_prefix *, const char *, - const char *, int, int, int *)); + const char *, int, int, int *, int)); static void translate_options PARAMS ((int *, const char *const **)); static char *skip_whitespace PARAMS ((char *)); static void delete_if_ordinary PARAMS ((const char *)); @@ -963,6 +969,7 @@ static const struct option_map option_map[] = {"--print-missing-file-dependencies", "-MG", 0}, {"--print-multi-lib", "-print-multi-lib", 0}, {"--print-multi-directory", "-print-multi-directory", 0}, + {"--print-multi-os-directory", "-print-multi-os-directory", 0}, {"--print-prog-name", "-print-prog-name=", "aj"}, {"--profile", "-p", 0}, {"--profile-blocks", "-a", 0}, @@ -1248,7 +1255,9 @@ struct prefix_list int require_machine_suffix; /* Don't use without machine_suffix. */ /* 2 means try both machine_suffix and just_machine_suffix. */ int *used_flag_ptr; /* 1 if a file was found with this prefix. */ - int priority; /* Sort key - priority within list */ + int priority; /* Sort key - priority within list. */ + int os_multilib; /* 1 if OS multilib scheme should be used, + 0 for GCC multilib scheme. */ }; struct path_prefix @@ -1337,6 +1346,11 @@ static const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX; set_multilib_dir based on the compilation options. */ static const char *multilib_dir; + +/* Subdirectory to use for locating libraries in OS conventions. Set by + set_multilib_dir based on the compilation options. */ + +static const char *multilib_os_dir; /* Structure to keep track of the specs that have been defined so far. These are accessed using %(specname) or %[specname] in a compiler @@ -1390,6 +1404,7 @@ static struct spec_list static_specs[] = INIT_STATIC_SPEC ("multilib_extra", &multilib_extra), INIT_STATIC_SPEC ("multilib_matches", &multilib_matches), INIT_STATIC_SPEC ("multilib_exclusions", &multilib_exclusions), + INIT_STATIC_SPEC ("multilib_options", &multilib_options), INIT_STATIC_SPEC ("linker", &linker_name_spec), INIT_STATIC_SPEC ("link_libgcc", &link_libgcc_spec), INIT_STATIC_SPEC ("md_exec_prefix", &md_exec_prefix), @@ -1832,7 +1847,7 @@ read_specs (filename, main_p) (long) (p1 - buffer + 1)); p[-2] = '\0'; - new_filename = find_a_file (&startfile_prefixes, p1, R_OK); + new_filename = find_a_file (&startfile_prefixes, p1, R_OK, 0); read_specs (new_filename ? new_filename : p1, FALSE); continue; } @@ -1851,7 +1866,7 @@ read_specs (filename, main_p) (long) (p1 - buffer + 1)); p[-2] = '\0'; - new_filename = find_a_file (&startfile_prefixes, p1, R_OK); + new_filename = find_a_file (&startfile_prefixes, p1, R_OK, 0); if (new_filename) read_specs (new_filename, FALSE); else if (verbose_flag) @@ -2480,16 +2495,17 @@ access_check (name, mode) Return 0 if not found, otherwise return its name, allocated with malloc. */ static char * -find_a_file (pprefix, name, mode) +find_a_file (pprefix, name, mode, multilib) struct path_prefix *pprefix; const char *name; - int mode; + int mode, multilib; { char *temp; const char *const file_suffix = ((mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : ""); struct prefix_list *pl; int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1; + const char *multilib_name, *multilib_os_name; #ifdef DEFAULT_ASSEMBLER if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0) @@ -2504,6 +2520,22 @@ find_a_file (pprefix, name, mode) if (machine_suffix) len += strlen (machine_suffix); + multilib_name = name; + multilib_os_name = name; + if (multilib && multilib_os_dir) + { + int len1 = multilib_dir ? strlen (multilib_dir) + 1 : 0; + int len2 = strlen (multilib_os_dir) + 1; + + len += len1 > len2 ? len1 : len2; + if (multilib_dir) + multilib_name = ACONCAT ((multilib_dir, dir_separator_str, name, + NULL)); + if (strcmp (multilib_os_dir, ".") != 0) + multilib_os_name = ACONCAT ((multilib_os_dir, dir_separator_str, name, + NULL)); + } + temp = xmalloc (len); /* Determine the filename to execute (special case for absolute paths). */ @@ -2519,6 +2551,9 @@ find_a_file (pprefix, name, mode) else for (pl = pprefix->plist; pl; pl = pl->next) { + const char *this_name + = pl->os_multilib ? multilib_os_name : multilib_name; + if (machine_suffix) { /* Some systems have a suffix for executable files. @@ -2527,7 +2562,7 @@ find_a_file (pprefix, name, mode) { strcpy (temp, pl->prefix); strcat (temp, machine_suffix); - strcat (temp, name); + strcat (temp, multilib_name); strcat (temp, file_suffix); if (access_check (temp, mode) == 0) { @@ -2537,10 +2572,10 @@ find_a_file (pprefix, name, mode) } } - /* Now try just the name. */ + /* Now try just the multilib_name. */ strcpy (temp, pl->prefix); strcat (temp, machine_suffix); - strcat (temp, name); + strcat (temp, multilib_name); if (access_check (temp, mode) == 0) { if (pl->used_flag_ptr != 0) @@ -2559,7 +2594,7 @@ find_a_file (pprefix, name, mode) { strcpy (temp, pl->prefix); strcat (temp, just_machine_suffix); - strcat (temp, name); + strcat (temp, multilib_name); strcat (temp, file_suffix); if (access_check (temp, mode) == 0) { @@ -2571,7 +2606,7 @@ find_a_file (pprefix, name, mode) strcpy (temp, pl->prefix); strcat (temp, just_machine_suffix); - strcat (temp, name); + strcat (temp, multilib_name); if (access_check (temp, mode) == 0) { if (pl->used_flag_ptr != 0) @@ -2589,7 +2624,7 @@ find_a_file (pprefix, name, mode) if (file_suffix[0] != 0) { strcpy (temp, pl->prefix); - strcat (temp, name); + strcat (temp, this_name); strcat (temp, file_suffix); if (access_check (temp, mode) == 0) { @@ -2600,7 +2635,7 @@ find_a_file (pprefix, name, mode) } strcpy (temp, pl->prefix); - strcat (temp, name); + strcat (temp, this_name); if (access_check (temp, mode) == 0) { if (pl->used_flag_ptr != 0) @@ -2638,13 +2673,15 @@ enum path_prefix_priority 2 means try both machine_suffix and just_machine_suffix. */ static void -add_prefix (pprefix, prefix, component, priority, require_machine_suffix, warn) +add_prefix (pprefix, prefix, component, priority, require_machine_suffix, + warn, os_multilib) struct path_prefix *pprefix; const char *prefix; const char *component; /* enum prefix_priority */ int priority; int require_machine_suffix; int *warn; + int os_multilib; { struct prefix_list *pl, **prev; int len; @@ -2666,6 +2703,7 @@ add_prefix (pprefix, prefix, component, priority, require_machine_suffix, warn) pl->require_machine_suffix = require_machine_suffix; pl->used_flag_ptr = warn; pl->priority = priority; + pl->os_multilib = os_multilib; if (warn) *warn = 0; @@ -2709,7 +2747,7 @@ execute () commands[0].prog = argbuf[0]; /* first command. */ commands[0].argv = &argbuf[0]; - string = find_a_file (&exec_prefixes, commands[0].prog, X_OK); + string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, 0); if (string) commands[0].argv[0] = string; @@ -2723,7 +2761,8 @@ execute () argbuf[i] = 0; /* termination of command args. */ commands[n_commands].prog = argbuf[i + 1]; commands[n_commands].argv = &argbuf[i + 1]; - string = find_a_file (&exec_prefixes, commands[n_commands].prog, X_OK); + string = find_a_file (&exec_prefixes, commands[n_commands].prog, + X_OK, 0); if (string) commands[n_commands].argv[0] = string; n_commands++; @@ -3041,6 +3080,7 @@ display_help () fputs (_("\ -print-multi-lib Display the mapping between command line options and\n\ multiple library search directories\n"), stdout); + fputs (_(" -print-multi-os-directory Display the relative path to OS libraries\n"), stdout); fputs (_(" -Wa, Pass comma-separated on to the assembler\n"), stdout); fputs (_(" -Wp, Pass comma-separated on to the preprocessor\n"), stdout); fputs (_(" -Wl, Pass comma-separated on to the linker\n"), stdout); @@ -3202,9 +3242,9 @@ process_command (argc, argv) set_std_prefix (gcc_exec_prefix, len); add_prefix (&exec_prefixes, gcc_exec_prefix, "GCC", - PREFIX_PRIORITY_LAST, 0, NULL); + PREFIX_PRIORITY_LAST, 0, NULL, 0); add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC", - PREFIX_PRIORITY_LAST, 0, NULL); + PREFIX_PRIORITY_LAST, 0, NULL, 0); } /* COMPILER_PATH and LIBRARY_PATH have values @@ -3232,10 +3272,10 @@ process_command (argc, argv) else nstore[endp - startp] = 0; add_prefix (&exec_prefixes, nstore, 0, - PREFIX_PRIORITY_LAST, 0, NULL); + PREFIX_PRIORITY_LAST, 0, NULL, 0); add_prefix (&include_prefixes, concat (nstore, "include", NULL), - 0, PREFIX_PRIORITY_LAST, 0, NULL); + 0, PREFIX_PRIORITY_LAST, 0, NULL, 0); if (*endp == 0) break; endp = startp = endp + 1; @@ -3267,7 +3307,7 @@ process_command (argc, argv) else nstore[endp - startp] = 0; add_prefix (&startfile_prefixes, nstore, NULL, - PREFIX_PRIORITY_LAST, 0, NULL); + PREFIX_PRIORITY_LAST, 0, NULL, 1); if (*endp == 0) break; endp = startp = endp + 1; @@ -3300,7 +3340,7 @@ process_command (argc, argv) else nstore[endp - startp] = 0; add_prefix (&startfile_prefixes, nstore, NULL, - PREFIX_PRIORITY_LAST, 0, NULL); + PREFIX_PRIORITY_LAST, 0, NULL, 1); if (*endp == 0) break; endp = startp = endp + 1; @@ -3401,6 +3441,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" print_multi_lib = 1; else if (! strcmp (argv[i], "-print-multi-directory")) print_multi_directory = 1; + else if (! strcmp (argv[i], "-print-multi-os-directory")) + print_multi_os_directory = 1; else if (! strncmp (argv[i], "-Wa,", 4)) { int prev, j; @@ -3570,7 +3612,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" { if (len == 7) add_prefix (&include_prefixes, "include", NULL, - PREFIX_PRIORITY_B_OPT, 0, NULL); + PREFIX_PRIORITY_B_OPT, 0, NULL, 0); else { char * string = xmalloc (len + 1); @@ -3578,16 +3620,16 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" strncpy (string, value, len - 7); strcpy (string + len - 7, "include"); add_prefix (&include_prefixes, string, NULL, - PREFIX_PRIORITY_B_OPT, 0, NULL); + PREFIX_PRIORITY_B_OPT, 0, NULL, 0); } } add_prefix (&exec_prefixes, value, NULL, - PREFIX_PRIORITY_B_OPT, 0, &warn_B); + PREFIX_PRIORITY_B_OPT, 0, &warn_B, 0); add_prefix (&startfile_prefixes, value, NULL, - PREFIX_PRIORITY_B_OPT, 0, &warn_B); + PREFIX_PRIORITY_B_OPT, 0, &warn_B, 0); add_prefix (&include_prefixes, concat (value, "include", NULL), - NULL, PREFIX_PRIORITY_B_OPT, 0, NULL); + NULL, PREFIX_PRIORITY_B_OPT, 0, NULL, 0); n_switches++; } break; @@ -3760,17 +3802,17 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" as well as trying the machine and the version. */ #ifndef OS2 add_prefix (&exec_prefixes, standard_exec_prefix, "GCC", - PREFIX_PRIORITY_LAST, 1, warn_std_ptr); + PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0); add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS", - PREFIX_PRIORITY_LAST, 2, warn_std_ptr); + PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0); add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS", - PREFIX_PRIORITY_LAST, 2, warn_std_ptr); + PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0); #endif add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS", - PREFIX_PRIORITY_LAST, 1, warn_std_ptr); + PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0); add_prefix (&startfile_prefixes, standard_exec_prefix_1, "BINUTILS", - PREFIX_PRIORITY_LAST, 1, warn_std_ptr); + PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0); tooldir_prefix = concat (tooldir_base_prefix, spec_machine, dir_separator_str, NULL); @@ -3793,11 +3835,11 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" add_prefix (&exec_prefixes, concat (gcc_exec_tooldir_prefix, "bin", dir_separator_str, NULL), - NULL, PREFIX_PRIORITY_LAST, 0, NULL); + NULL, PREFIX_PRIORITY_LAST, 0, NULL, 0); add_prefix (&startfile_prefixes, concat (gcc_exec_tooldir_prefix, "lib", dir_separator_str, NULL), - NULL, PREFIX_PRIORITY_LAST, 0, NULL); + NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1); } tooldir_prefix = concat (standard_exec_prefix, spec_machine, @@ -3807,10 +3849,10 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" add_prefix (&exec_prefixes, concat (tooldir_prefix, "bin", dir_separator_str, NULL), - "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL); + "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 0); add_prefix (&startfile_prefixes, concat (tooldir_prefix, "lib", dir_separator_str, NULL), - "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL); + "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1); /* More prefixes are enabled in main, after we read the specs file and determine whether this is cross-compilation or not. */ @@ -3860,6 +3902,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" ; else if (! strcmp (argv[i], "-print-multi-directory")) ; + else if (! strcmp (argv[i], "-print-multi-os-directory")) + ; else if (! strcmp (argv[i], "-ftarget-help")) ; else if (! strcmp (argv[i], "-fhelp")) @@ -4363,9 +4407,14 @@ do_spec_1 (spec, inswitch, soft_matched_part) continue; #endif /* Try subdirectory if there is one. */ - if (multilib_dir != NULL) + if (multilib_dir != NULL + || (pl->os_multilib && multilib_os_dir != NULL)) { - if (machine_suffix) + const char *multi_dir; + + multi_dir = pl->os_multilib ? multilib_os_dir + : multilib_dir; + if (machine_suffix && multilib_dir) { if (strlen (pl->prefix) + strlen (machine_suffix) >= bufsize) @@ -4388,14 +4437,14 @@ do_spec_1 (spec, inswitch, soft_matched_part) } if (!pl->require_machine_suffix) { - if (is_directory (pl->prefix, multilib_dir, 1)) + if (is_directory (pl->prefix, multi_dir, 1)) { do_spec_1 ("-L", 0, NULL); #ifdef SPACE_AFTER_L_OPTION do_spec_1 (" ", 0, NULL); #endif do_spec_1 (pl->prefix, 1, NULL); - do_spec_1 (multilib_dir, 1, NULL); + do_spec_1 (multi_dir, 1, NULL); /* Make this a separate argument. */ do_spec_1 (" ", 0, NULL); } @@ -5616,11 +5665,9 @@ find_file (name) char *newname; /* Try multilib_dir if it is defined. */ - if (multilib_dir != NULL) + if (multilib_os_dir != NULL) { - const char *const try = ACONCAT ((multilib_dir, dir_separator_str, name, NULL)); - - newname = find_a_file (&startfile_prefixes, try, R_OK); + newname = find_a_file (&startfile_prefixes, name, R_OK, 1); /* If we don't find it in the multi library dir, then fall through and look for it in the normal places. */ @@ -5628,7 +5675,7 @@ find_file (name) return newname; } - newname = find_a_file (&startfile_prefixes, name, R_OK); + newname = find_a_file (&startfile_prefixes, name, R_OK, 0); return newname ? newname : name; } @@ -5863,7 +5910,7 @@ main (argc, argv) spec_version, dir_separator_str, NULL); just_machine_suffix = concat (spec_machine, dir_separator_str, NULL); - specs_file = find_a_file (&startfile_prefixes, "specs", R_OK); + specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, 0); /* Read the specs file unless it is a default one. */ if (specs_file != 0 && strcmp (specs_file, "specs")) read_specs (specs_file, TRUE); @@ -5888,18 +5935,18 @@ main (argc, argv) if (*md_exec_prefix) { add_prefix (&exec_prefixes, md_exec_prefix, "GCC", - PREFIX_PRIORITY_LAST, 0, NULL); + PREFIX_PRIORITY_LAST, 0, NULL, 0); add_prefix (&startfile_prefixes, md_exec_prefix, "GCC", - PREFIX_PRIORITY_LAST, 0, NULL); + PREFIX_PRIORITY_LAST, 0, NULL, 0); } if (*md_startfile_prefix) add_prefix (&startfile_prefixes, md_startfile_prefix, "GCC", - PREFIX_PRIORITY_LAST, 0, NULL); + PREFIX_PRIORITY_LAST, 0, NULL, 1); if (*md_startfile_prefix_1) add_prefix (&startfile_prefixes, md_startfile_prefix_1, "GCC", - PREFIX_PRIORITY_LAST, 0, NULL); + PREFIX_PRIORITY_LAST, 0, NULL, 1); /* If standard_startfile_prefix is relative, base it on standard_exec_prefix. This lets us move the installed tree @@ -5907,28 +5954,28 @@ main (argc, argv) standard_startfile_prefix on that as well. */ if (IS_ABSOLUTE_PATHNAME (standard_startfile_prefix)) add_prefix (&startfile_prefixes, standard_startfile_prefix, "BINUTILS", - PREFIX_PRIORITY_LAST, 0, NULL); + PREFIX_PRIORITY_LAST, 0, NULL, 1); else { if (gcc_exec_prefix) add_prefix (&startfile_prefixes, concat (gcc_exec_prefix, machine_suffix, standard_startfile_prefix, NULL), - NULL, PREFIX_PRIORITY_LAST, 0, NULL); + NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1); add_prefix (&startfile_prefixes, concat (standard_exec_prefix, machine_suffix, standard_startfile_prefix, NULL), - NULL, PREFIX_PRIORITY_LAST, 0, NULL); + NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1); } add_prefix (&startfile_prefixes, standard_startfile_prefix_1, - "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL); + "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1); add_prefix (&startfile_prefixes, standard_startfile_prefix_2, - "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL); + "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1); #if 0 /* Can cause surprises, and one can use -B./ instead. */ add_prefix (&startfile_prefixes, "./", NULL, - PREFIX_PRIORITY_LAST, 1, NULL); + PREFIX_PRIORITY_LAST, 1, NULL, 0); #endif } else @@ -5938,14 +5985,15 @@ main (argc, argv) add_prefix (&startfile_prefixes, concat (gcc_exec_prefix, machine_suffix, standard_startfile_prefix, NULL), - "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL); + "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1); } /* Process any user specified specs in the order given on the command line. */ for (uptr = user_specs_head; uptr; uptr = uptr->next) { - char *filename = find_a_file (&startfile_prefixes, uptr->filename, R_OK); + char *filename = find_a_file (&startfile_prefixes, uptr->filename, + R_OK, 0); read_specs (filename ? filename : uptr->filename, FALSE); } @@ -5987,7 +6035,7 @@ main (argc, argv) if (print_prog_name) { - char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK); + char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK, 0); printf ("%s\n", (newname ? newname : print_prog_name)); return (0); } @@ -6007,6 +6055,15 @@ main (argc, argv) return (0); } + if (print_multi_os_directory) + { + if (multilib_os_dir == NULL) + printf (".\n"); + else + printf ("%s\n", multilib_os_dir); + return (0); + } + if (target_help_flag) { /* Print if any target specific options. */ @@ -6166,7 +6223,7 @@ main (argc, argv) /* We'll use ld if we can't find collect2. */ if (! strcmp (linker_name_spec, "collect2")) { - char *s = find_a_file (&exec_prefixes, "collect2", X_OK); + char *s = find_a_file (&exec_prefixes, "collect2", X_OK, 0); if (s == NULL) linker_name_spec = "ld"; } @@ -6460,6 +6517,15 @@ next_member: goto next_member; } +struct mdswitchstr +{ + const char *str; + int len; +}; + +static struct mdswitchstr *mdswitches; +static int n_mdswitches; + /* Check whether a particular argument was used. The first time we canonicalize the switches to keep only the ones we care about. */ @@ -6525,8 +6591,9 @@ used_arg (p, len) xmalloc from calling fatal, and prevents us from re-executing this block of code. */ mswitches - = (struct mswitchstr *) xmalloc ((sizeof (struct mswitchstr)) - * (n_switches ? n_switches : 1)); + = (struct mswitchstr *) + xmalloc (sizeof (struct mswitchstr) + * (n_mdswitches + (n_switches ? n_switches : 1))); for (i = 0; i < n_switches; i++) { int xlen = strlen (switches[i].part1); @@ -6542,6 +6609,57 @@ used_arg (p, len) break; } } + + /* Add MULTILIB_DEFAULTS switches too, as long as they were not present + on the command line nor any options mutually incompatible with + them. */ + for (i = 0; i < n_mdswitches; i++) + { + const char *r; + + for (q = multilib_options; *q != '\0'; q++) + { + while (*q == ' ') + q++; + + r = q; + while (strncmp (q, mdswitches[i].str, mdswitches[i].len) != 0 + || strchr (" /", q[mdswitches[i].len]) == NULL) + { + while (*q != ' ' && *q != '/' && *q != '\0') + q++; + if (*q != '/') + break; + q++; + } + + if (*q != ' ' && *q != '\0') + { + while (*r != ' ' && *r != '\0') + { + q = r; + while (*q != ' ' && *q != '/' && *q != '\0') + q++; + + if (used_arg (r, q - r)) + break; + + if (*q != '/') + { + mswitches[n_mswitches].str = mdswitches[i].str; + mswitches[n_mswitches].len = mdswitches[i].len; + mswitches[n_mswitches].replace = (char *) 0; + mswitches[n_mswitches].rep_len = 0; + n_mswitches++; + break; + } + + r = q + 1; + } + break; + } + } + } } for (i = 0; i < n_mswitches; i++) @@ -6556,25 +6674,11 @@ default_arg (p, len) const char *p; int len; { - const char *start, *end; - - for (start = multilib_defaults; *start != '\0'; start = end + 1) - { - while (*start == ' ' || *start == '\t') - start++; - - if (*start == '\0') - break; - - for (end = start + 1; *end != ' ' && *end != '\t' && *end != '\0'; end++) - ; - - if ((end - start) == len && strncmp (p, start, len) == 0) - return 1; + int i; - if (*end == '\0') - break; - } + for (i = 0; i < n_mdswitches; i++) + if (len == mdswitches[i].len && ! strncmp (p, mdswitches[i].str, len)) + return 1; return 0; } @@ -6596,8 +6700,51 @@ set_multilib_dir () const char *p; unsigned int this_path_len; const char *this_path, *this_arg; + const char *start, *end; int not_arg; - int ok; + int ok, ndfltok, first; + + n_mdswitches = 0; + start = multilib_defaults; + while (*start == ' ' || *start == '\t') + start++; + while (*start != '\0') + { + n_mdswitches++; + while (*start != ' ' && *start != '\t' && *start != '\0') + start++; + while (*start == ' ' || *start == '\t') + start++; + } + + if (n_mdswitches) + { + int i = 0; + + mdswitches + = (struct mdswitchstr *) xmalloc (sizeof (struct mdswitchstr) + * n_mdswitches); + for (start = multilib_defaults; *start != '\0'; start = end + 1) + { + while (*start == ' ' || *start == '\t') + start++; + + if (*start == '\0') + break; + + for (end = start + 1; + *end != ' ' && *end != '\t' && *end != '\0'; end++) + ; + + obstack_grow (&multilib_obstack, start, end - start); + obstack_1grow (&multilib_obstack, 0); + mdswitches[i].str = obstack_finish (&multilib_obstack); + mdswitches[i++].len = end - start; + + if (*end == '\0') + break; + } + } p = multilib_exclusions; while (*p != '\0') @@ -6652,6 +6799,7 @@ set_multilib_dir () ++p; } + first = 1; p = multilib_select; while (*p != '\0') { @@ -6674,6 +6822,7 @@ set_multilib_dir () /* Check the arguments. */ ok = 1; + ndfltok = 1; ++p; while (*p != ';') { @@ -6709,32 +6858,65 @@ set_multilib_dir () there is a more specific library which uses this argument. If this argument is a default, we need not consider that more specific library. */ - if (! default_arg (this_arg, p - this_arg)) - { - ok = used_arg (this_arg, p - this_arg); - if (not_arg) - ok = ! ok; - } + ok = used_arg (this_arg, p - this_arg); + if (not_arg) + ok = ! ok; + + if (! ok) + ndfltok = 0; + + if (default_arg (this_arg, p - this_arg)) + ok = 1; if (*p == ' ') ++p; } - if (ok) + if (ok && first) { if (this_path_len != 1 || this_path[0] != '.') { char *new_multilib_dir = xmalloc (this_path_len + 1); + char *q; + strncpy (new_multilib_dir, this_path, this_path_len); new_multilib_dir[this_path_len] = '\0'; + q = strchr (new_multilib_dir, ':'); + if (q != NULL) + *q = '\0'; multilib_dir = new_multilib_dir; } - break; + first = 0; + } + + if (ndfltok) + { + const char *q = this_path, *end = this_path + this_path_len; + + while (q < end && *q != ':') + q++; + if (q < end) + { + char *new_multilib_os_dir = xmalloc (end - q); + memcpy (new_multilib_os_dir, q + 1, end - q - 1); + new_multilib_os_dir[end - q - 1] = '\0'; + multilib_os_dir = new_multilib_os_dir; + break; + } } ++p; } + + if (multilib_dir == NULL && multilib_os_dir != NULL + && strcmp (multilib_os_dir, ".") == 0) + { + free ((char *) multilib_os_dir); + multilib_os_dir = NULL; + } + else if (multilib_dir != NULL && multilib_os_dir == NULL) + multilib_os_dir = multilib_dir; } /* Print out the multiple library subdirectory selection @@ -6774,6 +6956,12 @@ print_multilib_info () ++p; } + /* When --disable-multilib was used but target defines + MULTILIB_OSDIRNAMES, entries starting with .: are there just + to find multilib_os_dir, so skip them from output. */ + if (this_path[0] == '.' && this_path[1] == ':') + skip = 1; + /* Check for matches with the multilib_exclusions. We don't bother with the '!' in either list. If any of the exclusion rules match all of its options with the select rule, we skip it. */ @@ -6915,7 +7103,7 @@ print_multilib_info () { const char *p1; - for (p1 = last_path; p1 < p; p1++) + for (p1 = last_path; p1 < p && *p1 != ':'; p1++) putchar (*p1); putchar (';'); } diff --git a/contrib/gcc/genmultilib b/contrib/gcc/genmultilib index 3cbfaa1..ca3b71b 100644 --- a/contrib/gcc/genmultilib +++ b/contrib/gcc/genmultilib @@ -63,6 +63,14 @@ # for the rule to exclude a set. Options can be preceded with a '!' to # match a logical NOT. +# The optional sevenths argument is a list of OS subdirectory names. +# The format is the same as of the second argument. +# The difference is that second argument describes multilib directories +# in GCC conventions, while this one the OS multilib convention. + +# The last option should be "yes" if multilibs are enabled. If it is not +# "yes", all GCC multilib dir names will be ".". + # The output looks like # #define MULTILIB_MATCHES "\ # SUBDIRECTORY OPTIONS;\ @@ -79,17 +87,18 @@ # Here is an example (this is from the actual sparc64 case): # genmultilib 'm64/m32 mno-app-regs|mcmodel=medany' '64 32 alt' # 'mcmodel?medany=mcmodel?medmid' 'm32/mno-app-regs* m32/mcmodel=*' -# 'm32/!m64/mno-app-regs m32/!m64/mcmodel=medany' +# '' 'm32/!m64/mno-app-regs m32/!m64/mcmodel=medany' +# '../lib64 ../lib32 alt' yes # This produces: # ". !m64 !m32 !mno-app-regs !mcmodel=medany;", -# "64 m64 !m32 !mno-app-regs !mcmodel=medany;", -# "32 !m64 m32 !mno-app-regs !mcmodel=medany;", +# "64:../lib64 m64 !m32 !mno-app-regs !mcmodel=medany;", +# "32:../lib32 !m64 m32 !mno-app-regs !mcmodel=medany;", # "alt !m64 !m32 mno-app-regs mcmodel=medany;", # "alt !m64 !m32 mno-app-regs !mcmodel=medany;", # "alt !m64 !m32 !mno-app-regs mcmodel=medany;", -# "64/alt m64 !m32 mno-app-regs mcmodel=medany;", -# "64/alt m64 !m32 mno-app-regs !mcmodel=medany;", -# "64/alt m64 !m32 !mno-app-regs mcmodel=medany;", +# "64/alt:../lib64/alt m64 !m32 mno-app-regs mcmodel=medany;", +# "64/alt:../lib64/alt m64 !m32 mno-app-regs !mcmodel=medany;", +# "64/alt:../lib64/alt m64 !m32 !mno-app-regs mcmodel=medany;", # # The effect is that `gcc -mno-app-regs' (for example) will append "alt" # to the directory name when searching for libraries or startup files and @@ -106,6 +115,8 @@ matches=$3 exceptions=$4 extra=$5 exclusions=$6 +osdirnames=$7 +enable_multilib=$8 echo "static const char *const multilib_raw[] = {" @@ -202,6 +213,29 @@ if [ -n "${dirnames}" ]; then done fi +# Construct a sed pattern which will convert option names to OS directory +# names. +toosdirnames= +if [ -n "${osdirnames}" ]; then + set x ${osdirnames} + shift + for set in ${options}; do + for opts in `echo ${set} | sed -e 's|/| |'g`; do + patt="/" + for opt in `echo ${opts} | sed -e 's_|_ _'g`; do + if [ "$1" != "${opt}" ]; then + toosdirnames="${toosdirnames} -e s|/${opt}/|/${1}/|g" + patt="${patt}${1}/" + if [ "${patt}" != "/${1}/" ]; then + toosdirnames="${toosdirnames} -e s|${patt}|/${1}/|g" + fi + fi + done + shift + done + done +fi + # We need another recursive shell script to correctly handle positive # matches. If we are invoked as # genmultilib "opt1 opt2" "" "opt1=nopt1 opt2=nopt2" @@ -257,6 +291,25 @@ for combo in ${combinations}; do # Remove the leading and trailing slashes. dirout=`echo ${dirout} | sed -e 's|^/||' -e 's|/$||g'` + # Use the OS directory names rather than the option names. + if [ -n "${toosdirnames}" ]; then + osdirout=`echo ${combo} | sed ${toosdirnames}` + # Remove the leading and trailing slashes. + osdirout=`echo ${osdirout} | sed -e 's|^/||' -e 's|/$||g'` + if [ "x${enable_multilib}" != xyes ]; then + dirout=".:${osdirout}" + else + dirout="${dirout}:${osdirout}" + fi + else + if [ "x${enable_multilib}" != xyes ]; then + # genmultilib with --disable-multilib should be + # called with '' '' '' '' '' '' '' no + # if MULTILIB_OSDIRNAMES is empty. + exit 1 + fi + fi + # Look through the options. We must output each option that is # present, and negate each option that is not present. optout= @@ -313,6 +366,11 @@ done echo "NULL" echo "};" +# Output the options now +moptions=`echo ${options} | sed -e 's,[ ][ ]*, ,g'` +echo "" +echo "static const char *multilib_options = \"${moptions}\";" + rm -f tmpmultilib2 exit 0 diff --git a/contrib/gcc/jump.c b/contrib/gcc/jump.c index cad10ff..1a26b59 100644 --- a/contrib/gcc/jump.c +++ b/contrib/gcc/jump.c @@ -2428,3 +2428,15 @@ true_regnum (x) } return -1; } + +/* Return regno of the register REG and handle subregs too. */ +unsigned int +reg_or_subregno (reg) + rtx reg; +{ + if (REG_P (reg)) + return REGNO (reg); + if (GET_CODE (reg) == SUBREG) + return REGNO (SUBREG_REG (reg)); + abort (); +} diff --git a/contrib/gcc/libgcc2.c b/contrib/gcc/libgcc2.c index 59d48d8..dd5eee7 100644 --- a/contrib/gcc/libgcc2.c +++ b/contrib/gcc/libgcc2.c @@ -1,7 +1,7 @@ /* More subroutines needed by GCC output code on some machines. */ /* Compile this one with gcc. */ /* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001 Free Software Foundation, Inc. + 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of GCC. @@ -36,8 +36,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "tconfig.h" #include "tsystem.h" -#include "machmode.h" - /* Don't use `fancy_abort' here even if config.h says to use it. */ #ifdef abort #undef abort @@ -1117,7 +1115,10 @@ __floatdisf (DWtype u) && u < ((DWtype) 1 << DF_SIZE))) { if ((UDWtype) u & (REP_BIT - 1)) - u |= REP_BIT; + { + u &= ~ (REP_BIT - 1); + u |= REP_BIT; + } } } f = (Wtype) (u >> WORD_SIZE); diff --git a/contrib/gcc/loop.c b/contrib/gcc/loop.c index 4450845..732a84d 100644 --- a/contrib/gcc/loop.c +++ b/contrib/gcc/loop.c @@ -640,6 +640,7 @@ scan_loop (loop, flags) int threshold; /* Nonzero if we are scanning instructions in a sub-loop. */ int loop_depth = 0; + int in_libcall; loop->top = 0; @@ -756,290 +757,311 @@ scan_loop (loop, flags) When MAYBE_NEVER is 0, all insns will be executed at least once so that is not a problem. */ - for (p = next_insn_in_loop (loop, loop->scan_start); + for (in_libcall = 0, p = next_insn_in_loop (loop, loop->scan_start); p != NULL_RTX; p = next_insn_in_loop (loop, p)) { - if (GET_CODE (p) == INSN - && (set = single_set (p)) - && GET_CODE (SET_DEST (set)) == REG -#ifdef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED - && SET_DEST (set) != pic_offset_table_rtx -#endif - && ! regs->array[REGNO (SET_DEST (set))].may_not_optimize) + if (in_libcall && INSN_P (p) && find_reg_note (p, REG_RETVAL, NULL_RTX)) + in_libcall--; + if (GET_CODE (p) == INSN) { - int tem1 = 0; - int tem2 = 0; - int move_insn = 0; - rtx src = SET_SRC (set); - rtx dependencies = 0; - - /* Figure out what to use as a source of this insn. If a REG_EQUIV - note is given or if a REG_EQUAL note with a constant operand is - specified, use it as the source and mark that we should move - this insn by calling emit_move_insn rather that duplicating the - insn. - - Otherwise, only use the REG_EQUAL contents if a REG_RETVAL note - is present. */ - temp = find_reg_note (p, REG_EQUIV, NULL_RTX); + temp = find_reg_note (p, REG_LIBCALL, NULL_RTX); if (temp) - src = XEXP (temp, 0), move_insn = 1; - else + in_libcall++; + if (! in_libcall + && (set = single_set (p)) + && GET_CODE (SET_DEST (set)) == REG +#ifdef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED + && SET_DEST (set) != pic_offset_table_rtx +#endif + && ! regs->array[REGNO (SET_DEST (set))].may_not_optimize) { - temp = find_reg_note (p, REG_EQUAL, NULL_RTX); - if (temp && CONSTANT_P (XEXP (temp, 0))) + int tem1 = 0; + int tem2 = 0; + int move_insn = 0; + rtx src = SET_SRC (set); + rtx dependencies = 0; + + /* Figure out what to use as a source of this insn. If a + REG_EQUIV note is given or if a REG_EQUAL note with a + constant operand is specified, use it as the source and + mark that we should move this insn by calling + emit_move_insn rather that duplicating the insn. + + Otherwise, only use the REG_EQUAL contents if a REG_RETVAL + note is present. */ + temp = find_reg_note (p, REG_EQUIV, NULL_RTX); + if (temp) src = XEXP (temp, 0), move_insn = 1; - if (temp && find_reg_note (p, REG_RETVAL, NULL_RTX)) - { - src = XEXP (temp, 0); - /* A libcall block can use regs that don't appear in - the equivalent expression. To move the libcall, - we must move those regs too. */ - dependencies = libcall_other_reg (p, src); - } - } - - /* For parallels, add any possible uses to the depencies, as we can't move - the insn without resolving them first. */ - if (GET_CODE (PATTERN (p)) == PARALLEL) - { - for (i = 0; i < XVECLEN (PATTERN (p), 0); i++) + else { - rtx x = XVECEXP (PATTERN (p), 0, i); - if (GET_CODE (x) == USE) - dependencies = gen_rtx_EXPR_LIST (VOIDmode, XEXP (x, 0), dependencies); + temp = find_reg_note (p, REG_EQUAL, NULL_RTX); + if (temp && CONSTANT_P (XEXP (temp, 0))) + src = XEXP (temp, 0), move_insn = 1; + if (temp && find_reg_note (p, REG_RETVAL, NULL_RTX)) + { + src = XEXP (temp, 0); + /* A libcall block can use regs that don't appear in + the equivalent expression. To move the libcall, + we must move those regs too. */ + dependencies = libcall_other_reg (p, src); + } } - } - /* Don't try to optimize a register that was made - by loop-optimization for an inner loop. - We don't know its life-span, so we can't compute the benefit. */ - if (REGNO (SET_DEST (set)) >= max_reg_before_loop) - ; - else if (/* The register is used in basic blocks other - than the one where it is set (meaning that - something after this point in the loop might - depend on its value before the set). */ - ! reg_in_basic_block_p (p, SET_DEST (set)) - /* And the set is not guaranteed to be executed once - the loop starts, or the value before the set is - needed before the set occurs... - - ??? Note we have quadratic behaviour here, mitigated - by the fact that the previous test will often fail for - large loops. Rather than re-scanning the entire loop - each time for register usage, we should build tables - of the register usage and use them here instead. */ - && (maybe_never - || loop_reg_used_before_p (loop, set, p))) - /* It is unsafe to move the set. - - This code used to consider it OK to move a set of a variable - which was not created by the user and not used in an exit test. - That behavior is incorrect and was removed. */ - ; - else if ((tem = loop_invariant_p (loop, src)) - && (dependencies == 0 - || (tem2 = loop_invariant_p (loop, dependencies)) != 0) - && (regs->array[REGNO (SET_DEST (set))].set_in_loop == 1 - || (tem1 - = consec_sets_invariant_p - (loop, SET_DEST (set), - regs->array[REGNO (SET_DEST (set))].set_in_loop, - p))) - /* If the insn can cause a trap (such as divide by zero), - can't move it unless it's guaranteed to be executed - once loop is entered. Even a function call might - prevent the trap insn from being reached - (since it might exit!) */ - && ! ((maybe_never || call_passed) - && may_trap_p (src))) - { - struct movable *m; - int regno = REGNO (SET_DEST (set)); - - /* A potential lossage is where we have a case where two insns - can be combined as long as they are both in the loop, but - we move one of them outside the loop. For large loops, - this can lose. The most common case of this is the address - of a function being called. - - Therefore, if this register is marked as being used exactly - once if we are in a loop with calls (a "large loop"), see if - we can replace the usage of this register with the source - of this SET. If we can, delete this insn. - - Don't do this if P has a REG_RETVAL note or if we have - SMALL_REGISTER_CLASSES and SET_SRC is a hard register. */ - - if (loop_info->has_call - && regs->array[regno].single_usage != 0 - && regs->array[regno].single_usage != const0_rtx - && REGNO_FIRST_UID (regno) == INSN_UID (p) - && (REGNO_LAST_UID (regno) - == INSN_UID (regs->array[regno].single_usage)) - && regs->array[regno].set_in_loop == 1 - && GET_CODE (SET_SRC (set)) != ASM_OPERANDS - && ! side_effects_p (SET_SRC (set)) - && ! find_reg_note (p, REG_RETVAL, NULL_RTX) - && (! SMALL_REGISTER_CLASSES - || (! (GET_CODE (SET_SRC (set)) == REG - && REGNO (SET_SRC (set)) < FIRST_PSEUDO_REGISTER))) - /* This test is not redundant; SET_SRC (set) might be - a call-clobbered register and the life of REGNO - might span a call. */ - && ! modified_between_p (SET_SRC (set), p, - regs->array[regno].single_usage) - && no_labels_between_p (p, regs->array[regno].single_usage) - && validate_replace_rtx (SET_DEST (set), SET_SRC (set), - regs->array[regno].single_usage)) + /* For parallels, add any possible uses to the depencies, as + we can't move the insn without resolving them first. */ + if (GET_CODE (PATTERN (p)) == PARALLEL) { - /* Replace any usage in a REG_EQUAL note. Must copy the - new source, so that we don't get rtx sharing between the - SET_SOURCE and REG_NOTES of insn p. */ - REG_NOTES (regs->array[regno].single_usage) - = replace_rtx (REG_NOTES (regs->array[regno].single_usage), - SET_DEST (set), copy_rtx (SET_SRC (set))); - - delete_insn (p); - for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); i++) - regs->array[regno+i].set_in_loop = 0; - continue; + for (i = 0; i < XVECLEN (PATTERN (p), 0); i++) + { + rtx x = XVECEXP (PATTERN (p), 0, i); + if (GET_CODE (x) == USE) + dependencies + = gen_rtx_EXPR_LIST (VOIDmode, XEXP (x, 0), + dependencies); + } } - m = (struct movable *) xmalloc (sizeof (struct movable)); - m->next = 0; - m->insn = p; - m->set_src = src; - m->dependencies = dependencies; - m->set_dest = SET_DEST (set); - m->force = 0; - m->consec = regs->array[REGNO (SET_DEST (set))].set_in_loop - 1; - m->done = 0; - m->forces = 0; - m->partial = 0; - m->move_insn = move_insn; - m->move_insn_first = 0; - m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0); - m->savemode = VOIDmode; - m->regno = regno; - /* Set M->cond if either loop_invariant_p - or consec_sets_invariant_p returned 2 - (only conditionally invariant). */ - m->cond = ((tem | tem1 | tem2) > 1); - m->global = LOOP_REG_GLOBAL_P (loop, regno); - m->match = 0; - m->lifetime = LOOP_REG_LIFETIME (loop, regno); - m->savings = regs->array[regno].n_times_set; - if (find_reg_note (p, REG_RETVAL, NULL_RTX)) - m->savings += libcall_benefit (p); - for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); i++) - regs->array[regno+i].set_in_loop = move_insn ? -2 : -1; - /* Add M to the end of the chain MOVABLES. */ - loop_movables_add (movables, m); - - if (m->consec > 0) + /* Don't try to optimize a register that was made + by loop-optimization for an inner loop. + We don't know its life-span, so we can't compute + the benefit. */ + if (REGNO (SET_DEST (set)) >= max_reg_before_loop) + ; + else if (/* The register is used in basic blocks other + than the one where it is set (meaning that + something after this point in the loop might + depend on its value before the set). */ + ! reg_in_basic_block_p (p, SET_DEST (set)) + /* And the set is not guaranteed to be executed once + the loop starts, or the value before the set is + needed before the set occurs... + + ??? Note we have quadratic behaviour here, mitigated + by the fact that the previous test will often fail for + large loops. Rather than re-scanning the entire loop + each time for register usage, we should build tables + of the register usage and use them here instead. */ + && (maybe_never + || loop_reg_used_before_p (loop, set, p))) + /* It is unsafe to move the set. + + This code used to consider it OK to move a set of a variable + which was not created by the user and not used in an exit + test. + That behavior is incorrect and was removed. */ + ; + else if ((tem = loop_invariant_p (loop, src)) + && (dependencies == 0 + || (tem2 + = loop_invariant_p (loop, dependencies)) != 0) + && (regs->array[REGNO (SET_DEST (set))].set_in_loop == 1 + || (tem1 + = consec_sets_invariant_p + (loop, SET_DEST (set), + regs->array[REGNO (SET_DEST (set))].set_in_loop, + p))) + /* If the insn can cause a trap (such as divide by zero), + can't move it unless it's guaranteed to be executed + once loop is entered. Even a function call might + prevent the trap insn from being reached + (since it might exit!) */ + && ! ((maybe_never || call_passed) + && may_trap_p (src))) { - /* It is possible for the first instruction to have a - REG_EQUAL note but a non-invariant SET_SRC, so we must - remember the status of the first instruction in case - the last instruction doesn't have a REG_EQUAL note. */ - m->move_insn_first = m->move_insn; - - /* Skip this insn, not checking REG_LIBCALL notes. */ - p = next_nonnote_insn (p); - /* Skip the consecutive insns, if there are any. */ - p = skip_consec_insns (p, m->consec); - /* Back up to the last insn of the consecutive group. */ - p = prev_nonnote_insn (p); - - /* We must now reset m->move_insn, m->is_equiv, and possibly - m->set_src to correspond to the effects of all the - insns. */ - temp = find_reg_note (p, REG_EQUIV, NULL_RTX); - if (temp) - m->set_src = XEXP (temp, 0), m->move_insn = 1; - else + struct movable *m; + int regno = REGNO (SET_DEST (set)); + + /* A potential lossage is where we have a case where two insns + can be combined as long as they are both in the loop, but + we move one of them outside the loop. For large loops, + this can lose. The most common case of this is the address + of a function being called. + + Therefore, if this register is marked as being used + exactly once if we are in a loop with calls + (a "large loop"), see if we can replace the usage of + this register with the source of this SET. If we can, + delete this insn. + + Don't do this if P has a REG_RETVAL note or if we have + SMALL_REGISTER_CLASSES and SET_SRC is a hard register. */ + + if (loop_info->has_call + && regs->array[regno].single_usage != 0 + && regs->array[regno].single_usage != const0_rtx + && REGNO_FIRST_UID (regno) == INSN_UID (p) + && (REGNO_LAST_UID (regno) + == INSN_UID (regs->array[regno].single_usage)) + && regs->array[regno].set_in_loop == 1 + && GET_CODE (SET_SRC (set)) != ASM_OPERANDS + && ! side_effects_p (SET_SRC (set)) + && ! find_reg_note (p, REG_RETVAL, NULL_RTX) + && (! SMALL_REGISTER_CLASSES + || (! (GET_CODE (SET_SRC (set)) == REG + && (REGNO (SET_SRC (set)) + < FIRST_PSEUDO_REGISTER)))) + /* This test is not redundant; SET_SRC (set) might be + a call-clobbered register and the life of REGNO + might span a call. */ + && ! modified_between_p (SET_SRC (set), p, + regs->array[regno].single_usage) + && no_labels_between_p (p, + regs->array[regno].single_usage) + && validate_replace_rtx (SET_DEST (set), SET_SRC (set), + regs->array[regno].single_usage)) { - temp = find_reg_note (p, REG_EQUAL, NULL_RTX); - if (temp && CONSTANT_P (XEXP (temp, 0))) - m->set_src = XEXP (temp, 0), m->move_insn = 1; - else - m->move_insn = 0; + /* Replace any usage in a REG_EQUAL note. Must copy + the new source, so that we don't get rtx sharing + between the SET_SOURCE and REG_NOTES of insn p. */ + REG_NOTES (regs->array[regno].single_usage) + = (replace_rtx + (REG_NOTES (regs->array[regno].single_usage), + SET_DEST (set), copy_rtx (SET_SRC (set)))); + delete_insn (p); + for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); + i++) + regs->array[regno+i].set_in_loop = 0; + continue; } - m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0); - } - } - /* If this register is always set within a STRICT_LOW_PART - or set to zero, then its high bytes are constant. - So clear them outside the loop and within the loop - just load the low bytes. - We must check that the machine has an instruction to do so. - Also, if the value loaded into the register - depends on the same register, this cannot be done. */ - else if (SET_SRC (set) == const0_rtx - && GET_CODE (NEXT_INSN (p)) == INSN - && (set1 = single_set (NEXT_INSN (p))) - && GET_CODE (set1) == SET - && (GET_CODE (SET_DEST (set1)) == STRICT_LOW_PART) - && (GET_CODE (XEXP (SET_DEST (set1), 0)) == SUBREG) - && (SUBREG_REG (XEXP (SET_DEST (set1), 0)) - == SET_DEST (set)) - && !reg_mentioned_p (SET_DEST (set), SET_SRC (set1))) - { - int regno = REGNO (SET_DEST (set)); - if (regs->array[regno].set_in_loop == 2) - { - struct movable *m; + m = (struct movable *) xmalloc (sizeof (struct movable)); m->next = 0; m->insn = p; + m->set_src = src; + m->dependencies = dependencies; m->set_dest = SET_DEST (set); - m->dependencies = 0; m->force = 0; - m->consec = 0; + m->consec + = regs->array[REGNO (SET_DEST (set))].set_in_loop - 1; m->done = 0; m->forces = 0; - m->move_insn = 0; + m->partial = 0; + m->move_insn = move_insn; m->move_insn_first = 0; - m->partial = 1; - /* If the insn may not be executed on some cycles, - we can't clear the whole reg; clear just high part. - Not even if the reg is used only within this loop. - Consider this: - while (1) - while (s != t) { - if (foo ()) x = *s; - use (x); - } - Clearing x before the inner loop could clobber a value - being saved from the last time around the outer loop. - However, if the reg is not used outside this loop - and all uses of the register are in the same - basic block as the store, there is no problem. - - If this insn was made by loop, we don't know its - INSN_LUID and hence must make a conservative - assumption. */ - m->global = (INSN_UID (p) >= max_uid_for_loop - || LOOP_REG_GLOBAL_P (loop, regno) - || (labels_in_range_p - (p, REGNO_FIRST_LUID (regno)))); - if (maybe_never && m->global) - m->savemode = GET_MODE (SET_SRC (set1)); - else - m->savemode = VOIDmode; + m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0); + m->savemode = VOIDmode; m->regno = regno; - m->cond = 0; + /* Set M->cond if either loop_invariant_p + or consec_sets_invariant_p returned 2 + (only conditionally invariant). */ + m->cond = ((tem | tem1 | tem2) > 1); + m->global = LOOP_REG_GLOBAL_P (loop, regno); m->match = 0; m->lifetime = LOOP_REG_LIFETIME (loop, regno); - m->savings = 1; + m->savings = regs->array[regno].n_times_set; + if (find_reg_note (p, REG_RETVAL, NULL_RTX)) + m->savings += libcall_benefit (p); for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); i++) - regs->array[regno+i].set_in_loop = -1; + regs->array[regno+i].set_in_loop = move_insn ? -2 : -1; /* Add M to the end of the chain MOVABLES. */ loop_movables_add (movables, m); + + if (m->consec > 0) + { + /* It is possible for the first instruction to have a + REG_EQUAL note but a non-invariant SET_SRC, so we must + remember the status of the first instruction in case + the last instruction doesn't have a REG_EQUAL note. */ + m->move_insn_first = m->move_insn; + + /* Skip this insn, not checking REG_LIBCALL notes. */ + p = next_nonnote_insn (p); + /* Skip the consecutive insns, if there are any. */ + p = skip_consec_insns (p, m->consec); + /* Back up to the last insn of the consecutive group. */ + p = prev_nonnote_insn (p); + + /* We must now reset m->move_insn, m->is_equiv, and + possibly m->set_src to correspond to the effects of + all the insns. */ + temp = find_reg_note (p, REG_EQUIV, NULL_RTX); + if (temp) + m->set_src = XEXP (temp, 0), m->move_insn = 1; + else + { + temp = find_reg_note (p, REG_EQUAL, NULL_RTX); + if (temp && CONSTANT_P (XEXP (temp, 0))) + m->set_src = XEXP (temp, 0), m->move_insn = 1; + else + m->move_insn = 0; + + } + m->is_equiv + = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0); + } + } + /* If this register is always set within a STRICT_LOW_PART + or set to zero, then its high bytes are constant. + So clear them outside the loop and within the loop + just load the low bytes. + We must check that the machine has an instruction to do so. + Also, if the value loaded into the register + depends on the same register, this cannot be done. */ + else if (SET_SRC (set) == const0_rtx + && GET_CODE (NEXT_INSN (p)) == INSN + && (set1 = single_set (NEXT_INSN (p))) + && GET_CODE (set1) == SET + && (GET_CODE (SET_DEST (set1)) == STRICT_LOW_PART) + && (GET_CODE (XEXP (SET_DEST (set1), 0)) == SUBREG) + && (SUBREG_REG (XEXP (SET_DEST (set1), 0)) + == SET_DEST (set)) + && !reg_mentioned_p (SET_DEST (set), SET_SRC (set1))) + { + int regno = REGNO (SET_DEST (set)); + if (regs->array[regno].set_in_loop == 2) + { + struct movable *m; + m = (struct movable *) xmalloc (sizeof (struct movable)); + m->next = 0; + m->insn = p; + m->set_dest = SET_DEST (set); + m->dependencies = 0; + m->force = 0; + m->consec = 0; + m->done = 0; + m->forces = 0; + m->move_insn = 0; + m->move_insn_first = 0; + m->partial = 1; + /* If the insn may not be executed on some cycles, + we can't clear the whole reg; clear just high part. + Not even if the reg is used only within this loop. + Consider this: + while (1) + while (s != t) { + if (foo ()) x = *s; + use (x); + } + Clearing x before the inner loop could clobber a value + being saved from the last time around the outer loop. + However, if the reg is not used outside this loop + and all uses of the register are in the same + basic block as the store, there is no problem. + + If this insn was made by loop, we don't know its + INSN_LUID and hence must make a conservative + assumption. */ + m->global = (INSN_UID (p) >= max_uid_for_loop + || LOOP_REG_GLOBAL_P (loop, regno) + || (labels_in_range_p + (p, REGNO_FIRST_LUID (regno)))); + if (maybe_never && m->global) + m->savemode = GET_MODE (SET_SRC (set1)); + else + m->savemode = VOIDmode; + m->regno = regno; + m->cond = 0; + m->match = 0; + m->lifetime = LOOP_REG_LIFETIME (loop, regno); + m->savings = 1; + for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); + i++) + regs->array[regno+i].set_in_loop = -1; + /* Add M to the end of the chain MOVABLES. */ + loop_movables_add (movables, m); + } } } } @@ -1911,10 +1933,10 @@ move_movables (loop, movables, threshold, insn_count) for (count = m->consec; count >= 0; count--) { /* If this is the first insn of a library call sequence, - skip to the end. */ + something is very wrong. */ if (GET_CODE (p) != NOTE && (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX))) - p = XEXP (temp, 0); + abort (); /* If this is the last insn of a libcall sequence, then delete every insn in the sequence except the last. @@ -4090,11 +4112,17 @@ emit_prefetch_instructions (loop) { rtx reg = gen_reg_rtx (Pmode); rtx loop_start = loop->start; + rtx init_val = info[i].class->initial_value; rtx add_val = simplify_gen_binary (PLUS, Pmode, info[i].giv->add_val, GEN_INT (y * PREFETCH_BLOCK)); - loop_iv_add_mult_emit_before (loop, info[i].class->initial_value, + /* Functions called by LOOP_IV_ADD_EMIT_BEFORE expect a + non-constant INIT_VAL to have the same mode as REG, which + in this case we know to be Pmode. */ + if (GET_MODE (init_val) != Pmode && !CONSTANT_P (init_val)) + init_val = convert_to_mode (Pmode, init_val, 0); + loop_iv_add_mult_emit_before (loop, init_val, info[i].giv->mult_val, add_val, reg, 0, loop_start); emit_insn_before (gen_prefetch (reg, GEN_INT (info[i].write), diff --git a/contrib/gcc/loop.h b/contrib/gcc/loop.h index 8e3a935..6d18b01 100644 --- a/contrib/gcc/loop.h +++ b/contrib/gcc/loop.h @@ -314,6 +314,9 @@ struct loop_info int has_multiple_exit_targets; /* Nonzero if there is an indirect jump in the current function. */ int has_indirect_jump; + /* Whether loop unrolling has emitted copies of the loop body so + that the main loop needs no exit tests. */ + int preconditioned; /* Register or constant initial loop value. */ rtx initial_value; /* Register or constant value used for comparison test. */ diff --git a/contrib/gcc/mklibgcc.in b/contrib/gcc/mklibgcc.in index c5db6f0..30f660c 100644 --- a/contrib/gcc/mklibgcc.in +++ b/contrib/gcc/mklibgcc.in @@ -32,7 +32,7 @@ # SHLIB_MAPFILES # SHLIB_NM_FLAGS # SHLIB_INSTALL -# SHLIB_SLIBDIR_SUFFIXES +# MULTILIB_OSDIRNAMES # Make needs VPATH to be literal. echo 'srcdir = @srcdir@' @@ -317,22 +317,18 @@ for ml in $MULTILIBS; do fi shlib_so_name="$shlib_base_name" shlib_dir= - if [ -n "$SHLIB_SLIBDIR_SUFFIXES" ]; then + if [ -n "$MULTILIB_OSDIRNAMES" ]; then if [ "$dir" != . ]; then + gcc_multilib_dir=`./xgcc -B./ $flags --print-multi-directory` + os_multilib_dir=`./xgcc -B./ $flags --print-multi-os-directory` shlib_dir="$dir"/ - for suffix_pair in $SHLIB_SLIBDIR_SUFFIXES ; do - base_ml_dir=`echo ${suffix_pair} | sed -e 's/:.*$//' -e 's/=/$(EQ)/g'` - if [ "$dir" = "$base_ml_dir" ]; then - shlib_so_name=libgcc_s - break - else - canon_dir=`echo $dir | sed -n -e "s:$base_ml_dir/::p"` - if [ -n "$canon_dir" ]; then - shlib_so_name=libgcc_s_`echo $canon_dir | sed s,/,_,g` - break - fi - fi - done + gcc_multilib_sup=`echo $gcc_multilib_dir | sed 's~^[^/]*/~~'` + os_multilib_base=`echo $os_multilib_dir | sed -n "s~/${gcc_multilib_sup}\$~~p"` + if [ -z "$os_multilib_base" ]; then + shlib_so_name=libgcc_s + else + shlib_so_name=libgcc_s_`echo $gcc_multilib_sup | sed s,/,_,g` + fi fi fi echo "" @@ -438,6 +434,7 @@ echo "" echo "install: $all" for ml in $MULTILIBS; do dir=`echo ${ml} | sed -e 's/;.*$//' -e 's/=/$(EQ)/g'` + flags=`echo ${ml} | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`; if [ $dir != . ]; then ldir='$(libsubdir)'/$dir echo " if [ -d $ldir ]; then true; else mkdir $ldir; chmod a+rx $ldir; fi;" @@ -460,39 +457,22 @@ for ml in $MULTILIBS; do shlib_so_name="$shlib_base_name" shlib_dir= shlib_slibdir_qual= - if [ -n "$SHLIB_SLIBDIR_SUFFIXES" ]; then - shlib_slibdir_qual=none + if [ -n "$MULTILIB_OSDIRNAMES" ]; then + gcc_multilib_dir=`./xgcc -B./ $flags --print-multi-directory` + os_multilib_dir=`./xgcc -B./ $flags --print-multi-os-directory` if [ "$dir" != . ]; then shlib_dir="$dir"/ - for suffix_pair in $SHLIB_SLIBDIR_SUFFIXES ; do - base_ml_dir=`echo ${suffix_pair} | sed -e 's/:.*$//' -e 's/=/$(EQ)/g'` - if [ "$dir" = "$base_ml_dir" ]; then - shlib_so_name=libgcc_s - shlib_slibdir_qual=`echo ${suffix_pair} | sed -e 's/^[^:]*://'` - break - else - canon_dir=`echo $dir | sed -n -e "s:$base_ml_dir/::p"` - if [ -n "$canon_dir" ]; then - shlib_so_name=libgcc_s_`echo $canon_dir | sed s,/,_,g` - shlib_slibdir_qual=`echo ${suffix_pair} | sed -e 's/^[^:]*://'` - break - fi - fi - done fi - if [ "$shlib_slibdir_qual" = none ]; then - for suffix_pair in $SHLIB_SLIBDIR_SUFFIXES ; do - base_ml_dir=`echo ${suffix_pair} | sed -e 's/:.*$//' -e 's/=/$(EQ)/g'` - shlib_slibdir_qual=`echo ${suffix_pair} | sed -e 's/^[^:]*://'` - for ml2 in $MULTILIBS; do - dir2=`echo ${ml2} | sed -e 's/;.*$//' -e 's/=/$(EQ)/g'` - if [ "$base_ml_dir" = "$dir2" ]; then - shlib_slibdir_qual= - break - fi - done - if [ -n "$shlib_slibdir_qual" ]; then break; fi - done + gcc_multilib_sup=`echo $gcc_multilib_dir | sed 's~^[^/]*/~~'` + os_multilib_base=`echo $os_multilib_dir | sed -n "s~/${gcc_multilib_sup}\$~~p"` + if [ -z "$os_multilib_base" ]; then + shlib_so_name=libgcc_s + if [ "$os_multilib_dir" != "." ]; then + shlib_slibdir_qual="/$os_multilib_dir" + fi + else + shlib_so_name=libgcc_s_`echo $gcc_multilib_sup | sed s,/,_,g` + shlib_slibdir_qual="/$os_multilib_base" fi fi echo " $SHLIB_INSTALL" \ diff --git a/contrib/gcc/reload.c b/contrib/gcc/reload.c index 5880dfb..80678d0 100644 --- a/contrib/gcc/reload.c +++ b/contrib/gcc/reload.c @@ -1283,12 +1283,17 @@ push_reload (in, out, inloc, outloc, class, So add an additional reload. */ #ifdef SECONDARY_MEMORY_NEEDED - /* If a memory location is needed for the copy, make one. */ - if (in != 0 && GET_CODE (in) == REG - && REGNO (in) < FIRST_PSEUDO_REGISTER - && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)), - class, inmode)) - get_secondary_mem (in, inmode, opnum, type); + { + 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); + } #endif i = n_reloads; @@ -1314,11 +1319,16 @@ push_reload (in, out, inloc, outloc, class, n_reloads++; #ifdef SECONDARY_MEMORY_NEEDED - if (out != 0 && GET_CODE (out) == REG - && REGNO (out) < FIRST_PSEUDO_REGISTER - && SECONDARY_MEMORY_NEEDED (class, REGNO_REG_CLASS (REGNO (out)), - outmode)) - get_secondary_mem (out, outmode, opnum, type); + { + 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); + } #endif } else diff --git a/contrib/gcc/reload1.c b/contrib/gcc/reload1.c index 0ce10c4..9782f3a 100644 --- a/contrib/gcc/reload1.c +++ b/contrib/gcc/reload1.c @@ -7354,6 +7354,9 @@ gen_reload (out, in, opnum, type) { rtx last = get_last_insn (); rtx tem; +#ifdef SECONDARY_MEMORY_NEEDED + int in_regnum, out_regnum; +#endif /* If IN is a paradoxical SUBREG, remove it and try to put the opposite SUBREG on OUT. Likewise for a paradoxical SUBREG on OUT. */ @@ -7516,20 +7519,22 @@ gen_reload (out, in, opnum, type) #ifdef SECONDARY_MEMORY_NEEDED /* If we need a memory location to do the move, do it that way. */ - else if (GET_CODE (in) == REG && REGNO (in) < FIRST_PSEUDO_REGISTER - && GET_CODE (out) == REG && REGNO (out) < FIRST_PSEUDO_REGISTER - && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)), - REGNO_REG_CLASS (REGNO (out)), + else if ((in_regnum = true_regnum (in)) >= 0 + && in_regnum < FIRST_PSEUDO_REGISTER + && (out_regnum = true_regnum (out)) >= 0 + && out_regnum < FIRST_PSEUDO_REGISTER + && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (in_regnum), + REGNO_REG_CLASS (out_regnum), GET_MODE (out))) { /* Get the memory to use and rewrite both registers to its mode. */ rtx loc = get_secondary_mem (in, GET_MODE (out), opnum, type); if (GET_MODE (loc) != GET_MODE (out)) - out = gen_rtx_REG (GET_MODE (loc), REGNO (out)); + out = gen_rtx_REG (GET_MODE (loc), out_regnum); if (GET_MODE (loc) != GET_MODE (in)) - in = gen_rtx_REG (GET_MODE (loc), REGNO (in)); + in = gen_rtx_REG (GET_MODE (loc), in_regnum); gen_reload (loc, in, opnum, type); gen_reload (out, loc, opnum, type); @@ -7581,6 +7586,11 @@ delete_output_reload (insn, j, last_reload_reg) rtx i1; rtx substed; + /* It is possible that this reload has been only used to set another reload + we eliminated earlier and thus deleted this instruction too. */ + if (INSN_DELETED_P (output_reload_insn)) + return; + /* Get the raw pseudo-register referred to. */ while (GET_CODE (reg) == SUBREG) diff --git a/contrib/gcc/rtl.h b/contrib/gcc/rtl.h index 12f994b..63b9f58 100644 --- a/contrib/gcc/rtl.h +++ b/contrib/gcc/rtl.h @@ -1811,6 +1811,7 @@ extern int invert_jump_1 PARAMS ((rtx, rtx)); extern int invert_jump PARAMS ((rtx, rtx, int)); extern int rtx_renumbered_equal_p PARAMS ((rtx, rtx)); extern int true_regnum PARAMS ((rtx)); +extern unsigned int reg_or_subregno PARAMS ((rtx)); extern int redirect_jump_1 PARAMS ((rtx, rtx)); extern int redirect_jump PARAMS ((rtx, rtx, int)); extern void rebuild_jump_labels PARAMS ((rtx)); diff --git a/contrib/gcc/sched-deps.c b/contrib/gcc/sched-deps.c index f2f64d3..4e14ee2 100644 --- a/contrib/gcc/sched-deps.c +++ b/contrib/gcc/sched-deps.c @@ -923,7 +923,15 @@ sched_analyze_insn (deps, x, insn, loop_notes) code = GET_CODE (x); } if (code == SET || code == CLOBBER) - sched_analyze_1 (deps, x, insn); + { + sched_analyze_1 (deps, x, insn); + + /* Bare clobber insns are used for letting life analysis, reg-stack + and others know that a value is dead. Depend on the last call + instruction so that reg-stack won't get confused. */ + if (code == CLOBBER) + add_dependence_list (insn, deps->last_function_call, REG_DEP_OUTPUT); + } else if (code == PARALLEL) { int i; diff --git a/contrib/gcc/sibcall.c b/contrib/gcc/sibcall.c index 6e753fa..fca451f 100644 --- a/contrib/gcc/sibcall.c +++ b/contrib/gcc/sibcall.c @@ -574,8 +574,8 @@ optimize_sibling_and_tail_recursive_calls () rtx insn, insns; basic_block alternate_exit = EXIT_BLOCK_PTR; bool no_sibcalls_this_function = false; - int successful_sibling_call = 0; - int replaced_call_placeholder = 0; + bool successful_replacement = false; + bool replaced_call_placeholder = false; edge e; insns = get_insns (); @@ -715,10 +715,11 @@ optimize_sibling_and_tail_recursive_calls () /* Select a set of insns to implement the call and emit them. Tail recursion is the most efficient, so select it over a tail/sibling call. */ - if (sibcall) - successful_sibling_call = 1; - replaced_call_placeholder = 1; + if (sibcall || tailrecursion) + successful_replacement = true; + replaced_call_placeholder = true; + replace_call_placeholder (insn, tailrecursion != 0 ? sibcall_use_tail_recursion @@ -728,7 +729,7 @@ optimize_sibling_and_tail_recursive_calls () } } - if (successful_sibling_call) + if (successful_replacement) { rtx insn; tree arg; diff --git a/contrib/gcc/toplev.c b/contrib/gcc/toplev.c index efc7c97..d2732ce 100644 --- a/contrib/gcc/toplev.c +++ b/contrib/gcc/toplev.c @@ -879,6 +879,10 @@ int align_labels_max_skip; int align_functions; int align_functions_log; +/* Like align_functions_log above, but used by front-ends to force the + minimum function alignment. Zero means no alignment is forced. */ +int force_align_functions_log; + /* Table of supported debugging formats. */ static const struct { @@ -3016,13 +3020,13 @@ rest_of_compilation (decl) block. The loop infrastructure does the real job for us. */ flow_loops_find (&loops, LOOP_TREE); + if (rtl_dump_file) + flow_loops_dump (&loops, rtl_dump_file, NULL, 0); + /* Estimate using heuristics if no profiling info is available. */ if (flag_guess_branch_prob) estimate_probability (&loops); - if (rtl_dump_file) - flow_loops_dump (&loops, rtl_dump_file, NULL, 0); - flow_loops_free (&loops); } life_analysis (insns, rtl_dump_file, PROP_FINAL); diff --git a/contrib/gcc/tree.h b/contrib/gcc/tree.h index 9346f7d..084c306 100644 --- a/contrib/gcc/tree.h +++ b/contrib/gcc/tree.h @@ -2052,6 +2052,33 @@ extern tree integer_types[itk_none]; #define long_long_unsigned_type_node integer_types[itk_unsigned_long_long] +/* A pointer-to-function member type looks like: + + struct { + __P __pfn; + ptrdiff_t __delta; + }; + + If __pfn is NULL, it is a NULL pointer-to-member-function. + + (Because the vtable is always the first thing in the object, we + don't need its offset.) If the function is virtual, then PFN is + one plus twice the index into the vtable; otherwise, it is just a + pointer to the function. + + Unfortunately, using the lowest bit of PFN doesn't work in + architectures that don't impose alignment requirements on function + addresses, or that use the lowest bit to tell one ISA from another, + for example. For such architectures, we use the lowest bit of + DELTA instead of the lowest bit of the PFN, and DELTA will be + multiplied by 2. */ + +enum ptrmemfunc_vbit_where_t +{ + ptrmemfunc_vbit_in_pfn, + ptrmemfunc_vbit_in_delta +}; + #define NULL_TREE (tree) NULL /* Approximate positive square root of a host double. This is for diff --git a/contrib/gcc/unroll.c b/contrib/gcc/unroll.c index 032d675..83327c7 100644 --- a/contrib/gcc/unroll.c +++ b/contrib/gcc/unroll.c @@ -1188,6 +1188,9 @@ unroll_loop (loop, insn_count, strength_reduce_p) /* Keep track of the unroll factor for the loop. */ loop_info->unroll_number = unroll_number; + /* And whether the loop has been preconditioned. */ + loop_info->preconditioned = loop_preconditioned; + /* For each biv and giv, determine whether it can be safely split into a different variable for each unrolled copy of the loop body. We precalculate and save this info here, since computing it is @@ -2868,7 +2871,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number) value = tem; } - splittable_regs[REGNO (v->new_reg)] = value; + splittable_regs[reg_or_subregno (v->new_reg)] = value; } else { @@ -3047,21 +3050,21 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number) itself does not have to be splittable. */ if (v->same && v->same->giv_type == DEST_REG) - addr_combined_regs[REGNO (v->same->new_reg)] = v->same; + addr_combined_regs[reg_or_subregno (v->same->new_reg)] = v->same; if (GET_CODE (v->new_reg) == REG) { /* This giv maybe hasn't been combined with any others. Make sure that it's giv is marked as splittable here. */ - splittable_regs[REGNO (v->new_reg)] = value; + splittable_regs[reg_or_subregno (v->new_reg)] = value; /* Make it appear to depend upon itself, so that the giv will be properly split in the main loop above. */ if (! v->same) { v->same = v; - addr_combined_regs[REGNO (v->new_reg)] = v; + addr_combined_regs[reg_or_subregno (v->new_reg)] = v; } } @@ -3098,7 +3101,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number) if (! v->ignore) count = REG_IV_CLASS (ivs, REGNO (v->src_reg))->biv_count; - splittable_regs_updates[REGNO (v->new_reg)] = count; + splittable_regs_updates[reg_or_subregno (v->new_reg)] = count; } result++; diff --git a/contrib/gcc/varasm.c b/contrib/gcc/varasm.c index 4c27011..9e683a5 100644 --- a/contrib/gcc/varasm.c +++ b/contrib/gcc/varasm.c @@ -1194,6 +1194,8 @@ assemble_start_function (decl, fnname) /* Tell assembler to move to target machine's alignment for functions. */ align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT); + if (align < force_align_functions_log) + align = force_align_functions_log; if (align > 0) { ASM_OUTPUT_ALIGN (asm_out_file, align); diff --git a/contrib/gcc/version.c b/contrib/gcc/version.c index 696fa5a..0ca60de 100644 --- a/contrib/gcc/version.c +++ b/contrib/gcc/version.c @@ -1,4 +1,4 @@ #include "ansidecl.h" #include "version.h" -const char *const version_string = "3.2.1 20020916 (prerelease)"; +const char *const version_string = "3.2.1 20021009 (prerelease)"; -- cgit v1.1