Gcc 3.2.1-prerelease from the FSF anoncvs repo gcc-3_2-branch on October 9th 2002 20:15 EST.
This commit is contained in:
parent
bfa62e8fad
commit
ef578bad03
@ -1,3 +1,335 @@
|
||||
2002-10-09 Zack Weinberg <zack@codesourcery.com>
|
||||
|
||||
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 <rth@redhat.com>
|
||||
|
||||
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 <jh@suse.cz>
|
||||
|
||||
PR opt/7912
|
||||
PR opt/7390
|
||||
* i386.c (athlon_cost): Fix the move costs.
|
||||
|
||||
2002-10-09 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* libgcc2.c (__floatdisf): Properly cure double rounding.
|
||||
|
||||
2002-10-09 Gabriel Dos Reis <gdr@integrable-solutions.net>
|
||||
|
||||
PR doc/7484
|
||||
* doc/invoke.texi (Option Summary): List
|
||||
-Wmissing-declarations as a C only option.
|
||||
|
||||
2002-10-08 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* 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 <ebotcazou@libertysurf.fr>
|
||||
Volker Reichelt <reichelt@igpm.rwth-aachen.de>
|
||||
|
||||
PR c/7411
|
||||
* expr.c (expand_expr) [PLUS]: Simplify after the operands
|
||||
have been expanded in EXPAND_NORMAL mode.
|
||||
|
||||
2002-10-06 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* config/rs6000/rs6000.md (load_toc_v4_PIC_2): Fix base constraint.
|
||||
|
||||
2002-10-06 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
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 <neil@daikokuya.co.uk>
|
||||
|
||||
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 <fche@redhat.com>
|
||||
|
||||
* cppinit.c (init_standard_includes, parse_option): Use strncmp.
|
||||
|
||||
2002-10-05 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* 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 <neil@daikokuya.co.uk>
|
||||
|
||||
PR preprocessor/8120
|
||||
* doc/cpp.texi: Update documentation of bad use of ##.
|
||||
|
||||
Thu Oct 3 23:15:15 CEST 2002 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* i386.h (CPP_SPECS): fix defines for -msse, -msse2, -mpentium2,3.
|
||||
|
||||
Thu Oct 3 21:35:36 CEST 2002 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* 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 <rsandifo@redhat.com>:
|
||||
|
||||
* expr.c (force_operand): Fix reversed move.
|
||||
|
||||
Andreas Jaeger <aj@suse.de>:
|
||||
|
||||
* config/i386/linux64.h (STARTFILE_PREFIX_SPEC): New.
|
||||
|
||||
Janis Johnson <janis187@us.ibm.com>:
|
||||
|
||||
* loop.c (emit_prefetch_instructions): Several small fixes.
|
||||
|
||||
Thu Sep 5 00:34:33 2002 J"orn Rennecke <joern.rennecke@superh.com>
|
||||
|
||||
* 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 <davem@redhat.com>
|
||||
|
||||
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 <davem@redhat.com>
|
||||
Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* reload1.c (gen_reload:SECONDARY_MEMORY_NEEDED): Handle SUBREG.
|
||||
* reload.c (push_reload:SECONDARY_MEMORY_NEEDED): Likewise.
|
||||
|
||||
2002-09-30 Bob Wilson <bob.wilson@acm.org>
|
||||
|
||||
* 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 <dave@hiauly1.hia.nrc.ca>
|
||||
|
||||
* cppinit.c (remove_dup_nonsys_dirs): Fix warning and return value.
|
||||
|
||||
2002-08-20 John David Anglin <dave@hiauly1.hia.nrc.ca>
|
||||
|
||||
* 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 <rearnsha@arm.com>
|
||||
|
||||
* 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 <davem@redhat.com>
|
||||
|
||||
* config/sparc/linux64.h (STARTFILE_SPEC32, ENDFILE_SPEC32): Kill
|
||||
hardcoded paths.
|
||||
|
||||
2002-09-27 Alexander N. Kabaev <ak03@gte.com>
|
||||
|
||||
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 <davem@redhat.com>
|
||||
|
||||
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 <rth@redhat.com>
|
||||
|
||||
PR c/7160
|
||||
* sched-deps.c (sched_analyze_insn): Make clobber insns depend
|
||||
on call insns.
|
||||
|
||||
2002-09-27 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* doloop.c (doloop_modify_runtime <biv skips initial incr>): Adjust
|
||||
by absolute loop increment, not loop increment.
|
||||
|
||||
2002-09-25 David S. Miller <davem@redhat.com>
|
||||
|
||||
PR target/7842
|
||||
* config/sparc/sparc.c (set_extends): SImode ASHIFT does not
|
||||
extend.
|
||||
|
||||
2002-09-20 Jeroen Dobbelaere <jeroen.dobbelaere@acunia.com>
|
||||
|
||||
* 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 <rth@redhat.com>
|
||||
|
||||
* sibcall.c (optimize_sibling_and_tail_recursive_call): Also remove
|
||||
RTX_UNCHANGING_P markers for successful tail-recursive replacement.
|
||||
|
||||
2002-09-16 Richard Henderson <rth@redhat.com>
|
||||
|
||||
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 <amodra@bigpond.net.au>
|
||||
|
||||
Merge from mainline.
|
||||
2002-07-20 Alan Modra <amodra@bigpond.net.au>
|
||||
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 <amodra@bigpond.net.au>
|
||||
PR optimization/6984
|
||||
* doloop.c (doloop_valid_p): Correct comment.
|
||||
(doloop_modify_runtime <abs_inc != 1>): Simplify.
|
||||
(doloop_modify_runtime <do-while>): Don't emit code when NE.
|
||||
|
||||
2002-09-16 Jeff Law <law@redhat.com>
|
||||
|
||||
* libgcc2.c: Do not include machmode.h.
|
||||
|
||||
2002-09-16 Jason Merrill <jason@redhat.com>
|
||||
Danny Smith <dannysmith@users.sourceforge.net>
|
||||
|
||||
* 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 <stcarrez@nerim.fr>
|
||||
|
||||
* config/m68hc11/m68hc11.md ("movdi_internal"): Allow any offsetable
|
||||
@ -185,7 +517,7 @@
|
||||
2002-08-27 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* doc/invoke.texi: Document -Wabi.
|
||||
|
||||
|
||||
2002-08-23 David Edelsohn <edelsohn@gnu.org>
|
||||
|
||||
* 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 <amodra@bigpond.net.au>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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]));
|
||||
|
@ -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))
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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" }
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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))]
|
||||
"
|
||||
{
|
||||
|
@ -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`
|
||||
|
@ -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:
|
||||
|
@ -1,3 +1,54 @@
|
||||
2002-10-09 Zack Weinberg <zack@codesourcery.com>
|
||||
|
||||
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 <mark@codesourcery.com>
|
||||
|
||||
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 <rth@redhat.com>
|
||||
|
||||
* decl2.c: Complete reversion of c++/7754.
|
||||
|
||||
2002-10-06 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
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 <mark@codesourcery.com>
|
||||
|
||||
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 <mark@codesourcery.com>
|
||||
|
||||
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 <jakub@redhat.com>
|
||||
|
||||
* decl.c (start_cleanup_fn): Clear interface_only before
|
||||
@ -336,7 +387,7 @@
|
||||
2002-04-29 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
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 <Franz.Sirl-kernel@lauterbach.com>
|
||||
@ -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 <mark@codesourcery.com>
|
||||
|
||||
* 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 <rsandifo@redhat.com>
|
||||
|
||||
* 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 <jason@redhat.com>
|
||||
@ -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 <nathan@codesourcery.com>
|
||||
|
||||
PR c++/5682
|
||||
@ -630,7 +681,7 @@
|
||||
|
||||
2002-03-18 Ashif Harji <asharji@uwaterloo.ca>
|
||||
|
||||
* 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 <jason@redhat.com>
|
||||
@ -747,7 +798,7 @@
|
||||
with pointer to member conversions.
|
||||
|
||||
2002-03-08 Craig Rodrigues <rodrigc@gcc.gnu.org>
|
||||
|
||||
|
||||
* 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 <rodrigc@gcc.gnu.org>
|
||||
2002-02-24 Craig Rodrigues <rodrigc@gcc.gnu.org>
|
||||
|
||||
PR c++/4093
|
||||
* cp-tree.h (SET_BINFO_MARKED): Cast false part of condition
|
||||
@ -835,7 +886,7 @@
|
||||
|
||||
2002-02-19 Jason Merrill <jason@redhat.com>
|
||||
|
||||
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 <jason@redhat.com>
|
||||
|
||||
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.
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
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));
|
||||
}
|
||||
else
|
||||
add_decl_stmt (anon_union_decl);
|
||||
add_decl_stmt (anon_union_decl);
|
||||
}
|
||||
|
||||
/* Finish processing a builtin type TYPE. It's name is NAME,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 <? j;}} instead.
|
||||
the smaller counter twice. The GNU C @code{typeof} extension allows you
|
||||
to write safe macros that avoid this kind of problem (@pxref{Typeof}).
|
||||
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 <? j;}}
|
||||
instead.
|
||||
|
||||
Since @code{<?} and @code{>?} are built into the compiler, they properly
|
||||
handle expressions with side-effects; @w{@samp{int min = i++ <? j++;}}
|
||||
|
@ -222,7 +222,7 @@ in the following sections.
|
||||
-Werror-implicit-function-declaration @gol
|
||||
-Wimport -Winline @gol
|
||||
-Wlarger-than-@var{len} -Wlong-long @gol
|
||||
-Wmain -Wmissing-braces -Wmissing-declarations @gol
|
||||
-Wmain -Wmissing-braces @gol
|
||||
-Wmissing-format-attribute -Wmissing-noreturn @gol
|
||||
-Wmultichar -Wno-format-extra-args -Wno-format-y2k @gol
|
||||
-Wno-import -Wpacked -Wpadded @gol
|
||||
@ -236,8 +236,8 @@ in the following sections.
|
||||
|
||||
@item C-only Warning Options
|
||||
@gccoptlist{
|
||||
-Wbad-function-cast -Wmissing-prototypes -Wnested-externs @gol
|
||||
-Wstrict-prototypes -Wtraditional}
|
||||
-Wbad-function-cast -Wmissing-declarations -Wmissing-prototypes @gol
|
||||
-Wnested-externs -Wstrict-prototypes -Wtraditional}
|
||||
|
||||
@item Debugging Options
|
||||
@xref{Debugging Options,,Options for Debugging Your Program or GCC}.
|
||||
@ -4246,15 +4246,13 @@ one @option{-I} option, the directories are scanned in left-to-right
|
||||
order; the standard system directories come after.
|
||||
|
||||
If a standard system include directory, or a directory specified with
|
||||
@option{-isystem}, is also specified with @option{-I}, it will be
|
||||
searched only in the position requested by @option{-I}. Also, it will
|
||||
not be considered a system include directory. If that directory really
|
||||
does contain system headers, there is a good chance that they will
|
||||
break. For instance, if GCC's installation procedure edited the headers
|
||||
in @file{/usr/include} to fix bugs, @samp{-I/usr/include} will cause the
|
||||
original, buggy headers to be found instead of the corrected ones. GCC
|
||||
will issue a warning when a system include directory is hidden in this
|
||||
way.
|
||||
@option{-isystem}, is also specified with @option{-I}, the @option{-I}
|
||||
option will be ignored. The directory will still be searched but as a
|
||||
system directory at its normal position in the system include chain.
|
||||
This is to ensure that GCC's procedure to fix buggy system headers and
|
||||
the ordering for the include_next directive are not inadvertantly changed.
|
||||
If you really need to change the search order for system directories,
|
||||
use the @option{-nostdinc} and/or @option{-isystem} options.
|
||||
|
||||
@item -I-
|
||||
@opindex I-
|
||||
|
@ -552,6 +552,7 @@ doloop_modify_runtime (loop, iterations_max,
|
||||
{
|
||||
const struct loop_info *loop_info = LOOP_INFO (loop);
|
||||
HOST_WIDE_INT abs_inc;
|
||||
HOST_WIDE_INT abs_loop_inc;
|
||||
int neg_inc;
|
||||
rtx diff;
|
||||
rtx sequence;
|
||||
@ -591,13 +592,22 @@ doloop_modify_runtime (loop, iterations_max,
|
||||
n = abs (final - initial) / abs_inc;
|
||||
n += (abs (final - initial) % abs_inc) != 0;
|
||||
|
||||
If the loop has been unrolled, then the loop body has been
|
||||
preconditioned to iterate a multiple of unroll_number times. If
|
||||
abs_inc is != 1, the full calculation is
|
||||
But when abs_inc is a power of two, the summation won't overflow
|
||||
except in cases where the loop never terminates. So we don't
|
||||
need to use this more costly calculation.
|
||||
|
||||
t1 = abs_inc * unroll_number;
|
||||
n = abs (final - initial) / t1;
|
||||
n += (abs (final - initial) % t1) > 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 (!loop_info->preconditioned)
|
||||
diff = expand_simple_binop (GET_MODE (diff), PLUS,
|
||||
diff, GEN_INT (abs_loop_inc - 1),
|
||||
diff, 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);
|
||||
|
||||
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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
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. */
|
||||
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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
@ -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)";
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,<options> Pass comma-separated <options> on to the assembler\n"), stdout);
|
||||
fputs (_(" -Wp,<options> Pass comma-separated <options> on to the preprocessor\n"), stdout);
|
||||
fputs (_(" -Wl,<options> Pass comma-separated <options> 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 @@ validate_switches (start)
|
||||
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;
|
||||
int i;
|
||||
|
||||
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;
|
||||
|
||||
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 (';');
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
else
|
||||
{
|
||||
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++)
|
||||
{
|
||||
rtx x = XVECEXP (PATTERN (p), 0, i);
|
||||
if (GET_CODE (x) == USE)
|
||||
dependencies = gen_rtx_EXPR_LIST (VOIDmode, XEXP (x, 0), dependencies);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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))
|
||||
{
|
||||
/* 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 = (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)
|
||||
{
|
||||
/* 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)))
|
||||
src = XEXP (temp, 0), move_insn = 1;
|
||||
if (temp && find_reg_note (p, REG_RETVAL, NULL_RTX))
|
||||
{
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
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)
|
||||
|
||||
/* 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++)
|
||||
{
|
||||
rtx x = XVECEXP (PATTERN (p), 0, i);
|
||||
if (GET_CODE (x) == USE)
|
||||
dependencies
|
||||
= gen_rtx_EXPR_LIST (VOIDmode, XEXP (x, 0),
|
||||
dependencies);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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))
|
||||
{
|
||||
/* 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 = (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),
|
||||
|
@ -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. */
|
||||
|
@ -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" \
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -2051,6 +2051,33 @@ extern tree integer_types[itk_none];
|
||||
#define long_long_integer_type_node integer_types[itk_long_long]
|
||||
#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
|
||||
|
||||
|
@ -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++;
|
||||
|
@ -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);
|
||||
|
@ -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)";
|
||||
|
Loading…
Reference in New Issue
Block a user