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:
kan 2002-10-10 04:40:18 +00:00
parent bfa62e8fad
commit ef578bad03
52 changed files with 1718 additions and 937 deletions

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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]));

View File

@ -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))

View File

@ -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. */

View File

@ -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" }

View File

@ -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:

View File

@ -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);

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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. */

View File

@ -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))]
"
{

View File

@ -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`

View File

@ -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:

View File

@ -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.

View File

@ -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. */

View File

@ -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;
}

View File

@ -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,

View File

@ -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;

View File

@ -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;
}

View File

@ -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, &quote);
qtail->next = brack;
qtail = remove_dup_nonsys_dirs (pfile, &quote, 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, &quote);
}
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;

View File

@ -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. */

View File

@ -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);

View File

@ -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

View File

@ -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++;}}

View File

@ -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-

View File

@ -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();

View File

@ -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);

View File

@ -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)";

View File

@ -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;

View File

@ -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 (';');
}

View File

@ -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

View File

@ -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 ();
}

View File

@ -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);

View File

@ -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),

View File

@ -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. */

View File

@ -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" \

View File

@ -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

View File

@ -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)

View File

@ -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));

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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++;

View File

@ -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);

View File

@ -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)";