diff options
author | Andrew Pinski <andrew_pinski@playstation.sony.com> | 2007-05-11 20:46:18 +0000 |
---|---|---|
committer | Andrew Pinski <andrew_pinski@playstation.sony.com> | 2007-05-11 20:46:18 +0000 |
commit | 322f830eb13616c511cd94486bf5361cf2853f8a (patch) | |
tree | f29f6ed0338b106f5da9b42ef37f19373d5c6e0c | |
parent | 86bb2a5d2067811c919ea01703adab99e15e8616 (diff) |
2007-05-10 Andrew Pinski <andrew_pinski@playstation.sony.com>
Merge mainline, revision 124602.
* fold-const.c (extract_array_ref): Make sure the offset
is converted to sizetype.
(try_move_mult_to_index): Strip the NOPs from the offset.
(fold_binary <case POINTER_PLUS_EXPR>): Convert the second
operand to sizetype before calling try_move_mult_to_index.
* tree-ssa-loop-niter.c (number_of_iterations_lt_to_ne):
For pointer types, use sizetype when
creating MINUS_EXPR/PLUS_EXPRs.
* tree-ssa-ccp.c (maybe_fold_stmt_indirect): Make sure
the offset is converted to sizetype.
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/pointer_plus@124625 138bc75d-0d04-0410-961f-82ee72b054a4
104 files changed, 2446 insertions, 363 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7453266e865..40867e98cdf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,214 @@ +2007-05-10 Zdenek Dvorak <dvorakz@suse.cz> + + PR tree-optimization/31885 + * tree-chrec.c (chrec_contains_undetermined): Do not consider NULL_TREE + to be undetermined. + (automatically_generated_chrec_p): Return false for NULL. + +2007-05-08 Bernd Schmidt <bernd.schmidt@analog.com> + + * config/bfin/bfin.h (MOVE_RATIO): Define. + +2007-05-10 Richard Sandiford <richard@codesourcery.com> + + * config.gcc (sparc-wrs-vxworks): New target. + * config/sparc/vxworks.h, config/sparc/t-vxworks: New files. + * config/sparc/sparc-protos.h (sparc_emit_call_insn): Declare. + * config/sparc/sparc.h: Include vxworks-dummy.h. + (PRINT_OPERAND_ADDRESS): Extend SYMBOL_REF handling to + include LABEL_REFs too. + * config/sparc/sparc.c (sparc_expand_move): Don't assume that + _GLOBAL_OFFSET_TABLE_ - label_ref is a link-time constant on + VxWorks. + (legitimize_pic_address): Handle LABEL_REFs like SYMBOL_REFs + on VxWorks. + (load_pic_register): Use gen_vxworks_load_got for VxWorks. + (sparc_emit_call_insn): New function. + (sparc_function_ok_for_sibcall): Restrict sibcalls to locally-binding + functions when generating VxWorks PIC. + * config/sparc/sparc.md (vxworks_load_got): New pattern. + (call, call_value): Use sparc_emit_call_insn instead of + emit_call_insn. + +2007-05-09 Bob Wilson <bob.wilson@acm.org> + + * config/xtensa/xtensa.c (xtensa_output_literal): Don't use #if. + +2007-05-09 Bob Wilson <bob.wilson@acm.org> + + * config/xtensa/xtensa.c (xtensa_output_literal): Mask out high bits + for floating-point values if HOST_BITS_PER_LONG > 32. Use split_double + instead of operand_subword. + +2007-05-08 Bernd Schmidt <bernd.schmidt@analog.com> + + * config/bfin/bfin.h (LOCAL_ALIGNMENT): Define. + * config/bfin/bfin.c (bfin_local_alignment): New function. + * config/bfin/bfin-protos.h (bfin_local_alignment): Declare it. + +2007-05-08 Chao-ying Fu <fu@mips.com> + + * doc/md.texi (msub@var{m}@var{n}4, usub@var{m}@var{n}4): Document. + * optabs.h (OTI_smsub_widen, OTI_umsub_widen): New optab_indexes. + (smsub_widen_optab, umsub_widen_optab): Define. + * optabs.c (init_optabs): Initialize smsub_widen_optab and + umsub_widen_optab. + * genopinit.c (optabs): Fill in smsub_widen_optab and + umsub_widen_optab. + * expr.c (expand_expr_real_1): Try to use smsub_widen_optab + and umsub_widen_optab to implement multiply-subtract sequences. + * config/mips/mips.md (*msac<u>_di): Rename to... + (<u>msubsidi4): ...this. Extend condition to include + GENERATE_MADD_MSUB and TARGET_DSPR2. Change the constraint + of operand 0 to "ka" and use the three-operand form of msub<u> + for TARGET_DSPR2. + * config/mips/mips-dspr2.md (mips_msub, mips_msubu): Convert + to define_expands. + +2007-05-08 Kaz Kojima <kkojima@gcc.gnu.org> + + PR rtl-optimization/28011 + * reload.c (push_reload): Set dont_share if IN appears in OUT + also when IN is a PLUS rtx. + (reg_overlap_mentioned_for_reload_p): Return true if X and IN + are same PLUS rtx. + +2007-05-08 Kazu Hirata <kazu@codesourcery.com> + + * emit-rtl.c (unshare_all_rtl_1): Don't copy DECL_RTL. Don't + call unshare_all_decls. + (unshare_all_rtl): Adjust the call to unshare_all_rtl_1. + (unshare_all_decls): Remove. + +2007-05-08 Simon Martin <simartin@users.sourceforge.net> + + PR 31847 + * tree-dump.c (dump_options): Don't use TDF_DIAGNOSTIC in "*-all" tree + dumps. + +2007-05-08 Sandra Loosemore <sandra@codesourcery.com> + Nigel Stephens <nigel@mips.com> + + * config/mips/mips.h (MAX_FPRS_PER_FMT): Renamed from FP_INC. + Update comments and all uses. + (MIN_FPRS_PER_FMT): Define. + * config/mips/mips.c (function_arg): Fix to correctly handle + the -mips32r2 -mfp64 -mabi=32 case. + (override_options): Enable use of odd-numbered registers for + SFmode values on MIPS32. + (mips_save_reg_p): Save whole floating-point register pair if + either half is used. + (compute_frame_size): Fix comment. + +2007-05-08 Jie Zhang <jie.zhang@analog.com> + + * config/bfin/bfin-protos.h (bfin_expand_epilogue): Add a third + argument of type bool. + * config/bfin/bfin.c (add_to_reg): Add epilogue_p as a fourth + argument. Safely select temporary P register according to it. + (do_link): Change call site of add_to_reg accordingly. + (do_unlink): Add epilogue_p as a fourth argument and pass it + to add_to_reg. + (expand_interrupt_handler_epilogue): Change call of do_unlink + accordingly. + (bfin_expand_prologue): Add a third argument sibcall_p. + * config/bfin/bfin.md (epilogue): Change call of + bfin_expand_epilogue accordingly. + (sibcall_epilogue): Likewise. + (eh_return_internal): Likewise. + + * config/bfin/bfin-protos.h (enum bfin_cpu): Add + BFIN_CPU_BF534, BFIN_CPU_BF536 and BFIN_CPU_BF561. + * config/bfin/bfin.c (bfin_handle_option): Handle + -mcpu=bf534, -mcpu=bf536 and -mcpu=bf561. + * config/bfin/bfin.h (TARGET_CPU_CPP_BUILTINS): + Support bf534, bf536 and bf561. + * doc/invoke.texi (Blackfin Options): Document -mcpu and -msim. + +2007-05-08 Uros Bizjak <ubizjak@gmail.com> + + PR target/31854 + * config/i386/i386.c (ix86_function_regparm): Process local + functions only when TREE_CODE (decl) equals FUNCTION_DECL. + +2007-05-07 Mike Stump <mrs@apple.com> + + * doc/invoke.texi (Warning Options): Document that -Wempty-body + also checks for and while statements in C++. + +2007-05-07 Nathan Froyd <froydnj@codesourcery.com> + + * gcc.c (at_file_supplied): New variable. + (main): Set it if we expanded argv. + (do_spec_1): Pass an @-file to the linker if we were called with + an @-file argument and HAVE_GNU_LD. + * collect2.c (at_file_supplied): New variable. + (response_file): New variable. + (collect_exit): Unlink response_file if necessary. + (handler): Likewise. + (do_wait): Likewise. + (main): Set at_file_supplied if we expanded argv. + (collect_execute): Pass an @-file to subprocesses if we were called + with an @-file argument. + * configure.ac: Add define for HAVE_GNU_LD. + * configure: Regenerate. + * config.in: Regenerate. + +2007-05-07 Naveen.H.S <naveen.hs@kpitcummins.com> + + * config/m32c/muldiv.md (mulhisi3_c): Limit the mode of the 2nd + operand to HI mode. + (mulsi3): New. + (divsi3): New. + (udivsi3): New. + +2007-05-07 Jayant Sonar <jayants@kpitcummins.com> + + * config/m32c/m32c.c (SYMBOL_FLAG_FUNCVEC_FUNCTION): Define. + (TARGET_ENCODE_SECTION_INFO): Re-define. + (m32c_encode_section_info): New + (function_vector_handler): New + (current_function_special_page_vector): New + (m32c_special_page_vector_p): New. + * config/m32c/m32c-protos.h (m32c_special_page_vector_p): + Prototype. + * config/m32c/jump.md: Added instruction JSRS for functions + with attribute "function_vector". + * doc/extend.texi (function_vector): Added description + for M16C, M32C targets. + +2007-05-07 DJ Delorie <dj@redhat.com> + + PR 31794 + * config/m32c/shift.md (ashlpsi3_i, ashrpsi3_i, ashlpsi3, + ashrpsi3, lshrpsi3): Update shift count constraint. + +2007-05-07 Danny Smith <dannysmith@users.sourceforge.net> + Nathan Froyd <froydnj@codesourcery.com> + + PR 22133 + * c-incpath.c (add_path): Strip trailing path separators. + +2007-05-07 Eric Botcazou <ebotcazou@adacore.com> + + * tree-ssa-dom.c (tree_ssa_dominator_optimize): Reset cfg_altered. + Free dominance info before purging EH edges. + (eliminate_degenerate_phis): Likewise. + (propagate_rhs_into_lhs): Set cfg_altered to true instead of 1. + +2007-05-07 Jan Hubicka <jh@suse.cz> + + * gimplify.c (gimplify_expr): Do not crash when folding + (void *)(int)&a + 4. + +2007-05-07 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR driver/31694 + * c-opts.c (lang_fortran): Make it non static. + * c-common.h (lang_fortran): New prototype. + * c-cppbuiltin.c (c_cpp_builtins): Create a __GFORTRAN__ if the + -lang-fortran option was passed by the driver. + 2007-05-06 Eric Botcazou <ebotcazou@adacore.com> * timevar.c (timevar_print): Test ENABLE_ASSERT_CHECKING instead @@ -194,7 +405,7 @@ 2007-05-03 Ian Lance Taylor <iant@google.com> - * config/rs6000/rs6000.c (rs6000_override_options): Don't se + * config/rs6000/rs6000.c (rs6000_override_options): Don't set MASK_PPC_GFXOPT for 8540 or 8548. 2007-05-03 Uros Bizjak <ubizjak@gmail.com> diff --git a/gcc/ChangeLog.ptr b/gcc/ChangeLog.ptr index 2e960d312cd..95d1c1a18a7 100644 --- a/gcc/ChangeLog.ptr +++ b/gcc/ChangeLog.ptr @@ -1,3 +1,18 @@ +2007-05-10 Andrew Pinski <andrew_pinski@playstation.sony.com> + + Merge mainline, revision 124602. + + * fold-const.c (extract_array_ref): Make sure the offset + is converted to sizetype. + (try_move_mult_to_index): Strip the NOPs from the offset. + (fold_binary <case POINTER_PLUS_EXPR>): Convert the second + operand to sizetype before calling try_move_mult_to_index. + * tree-ssa-loop-niter.c (number_of_iterations_lt_to_ne): + For pointer types, use sizetype when + creating MINUS_EXPR/PLUS_EXPRs. + * tree-ssa-ccp.c (maybe_fold_stmt_indirect): Make sure + the offset is converted to sizetype. + 2007-05-11 Andrew Pinski <andrew_pinski@playstation.sony.com> * config/spu/spu.c (spu_va_start): Create POINTER_PLUS_EXPR diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index f8b17cf886e..37fbc507602 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20070505 +20070510 diff --git a/gcc/c-common.h b/gcc/c-common.h index d4afaec4535..5e97211cb17 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -254,6 +254,8 @@ extern c_language_kind c_language; #define c_dialect_cxx() (c_language & clk_cxx) #define c_dialect_objc() (c_language & clk_objc) +extern bool lang_fortran; + /* Information about a statement tree. */ struct stmt_tree_s GTY(()) { diff --git a/gcc/c-cppbuiltin.c b/gcc/c-cppbuiltin.c index c36b038bc77..cc19ce5dd7d 100644 --- a/gcc/c-cppbuiltin.c +++ b/gcc/c-cppbuiltin.c @@ -569,6 +569,9 @@ c_cpp_builtins (cpp_reader *pfile) if (flag_openmp) cpp_define (pfile, "_OPENMP=200505"); + if (lang_fortran) + cpp_define (pfile, "__GFORTRAN__=1"); + builtin_define_type_sizeof ("__SIZEOF_INT__", integer_type_node); builtin_define_type_sizeof ("__SIZEOF_LONG__", long_integer_type_node); builtin_define_type_sizeof ("__SIZEOF_LONG_LONG__", diff --git a/gcc/c-incpath.c b/gcc/c-incpath.c index 3e819cec838..8b6512c8e0f 100644 --- a/gcc/c-incpath.c +++ b/gcc/c-incpath.c @@ -389,13 +389,18 @@ add_path (char *path, int chain, int cxx_aware, bool user_supplied_p) cpp_dir *p; #if defined (HAVE_DOS_BASED_FILE_SYSTEM) - /* Convert all backslashes to slashes. The native CRT stat() - function does not recognize a directory that ends in a backslash - (unless it is a drive root dir, such "c:\"). Forward slashes, - trailing or otherwise, cause no problems for stat(). */ - char* c; - for (c = path; *c; c++) - if (*c == '\\') *c = '/'; + /* Remove unnecessary trailing slashes. On some versions of MS + Windows, trailing _forward_ slashes cause no problems for stat(). + On newer versions, stat() does not recognise a directory that ends + in a '\\' or '/', unless it is a drive root dir, such as "c:/", + where it is obligatory. */ + int pathlen = strlen (path); + char* end = path + pathlen - 1; + /* Preserve the lead '/' or lead "c:/". */ + char* start = path + (pathlen > 2 && path[1] == ':' ? 3 : 1); + + for (; end > start && IS_DIR_SEPARATOR (*end); end--) + *end = 0; #endif p = XNEW (cpp_dir); diff --git a/gcc/c-opts.c b/gcc/c-opts.c index e378f377a0c..a41362a9829 100644 --- a/gcc/c-opts.c +++ b/gcc/c-opts.c @@ -73,7 +73,7 @@ static bool deps_seen; static bool verbose; /* If -lang-fortran seen. */ -static bool lang_fortran = false; +bool lang_fortran = false; /* Dependency output file. */ static const char *deps_file; diff --git a/gcc/collect2.c b/gcc/collect2.c index c6c1f3f4a2c..1ef174f534e 100644 --- a/gcc/collect2.c +++ b/gcc/collect2.c @@ -1,7 +1,7 @@ /* Collect static initialization info into data structures that can be traversed by C++ initialization and finalization routines. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. Contributed by Chris Smith (csmith@convex.com). Heavily modified by Michael Meissner (meissner@cygnus.com), Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com). @@ -202,6 +202,9 @@ static struct head exports; /* list of exported symbols */ #endif static struct head frame_tables; /* list of frame unwind info tables */ +static bool at_file_supplied; /* Whether to use @file arguments */ +static char *response_file; /* Name of any current response file */ + struct obstack temporary_obstack; char * temporary_firstobj; @@ -302,6 +305,9 @@ collect_exit (int status) if (status != 0 && output_file != 0 && output_file[0]) maybe_unlink (output_file); + if (response_file) + maybe_unlink (response_file); + exit (status); } @@ -393,6 +399,9 @@ handler (int signo) maybe_unlink (export_file); #endif + if (response_file) + maybe_unlink (response_file); + signal (signo, SIG_DFL); raise (signo); } @@ -793,7 +802,15 @@ main (int argc, char **argv) char **object_lst; const char **object; int first_file; - int num_c_args = argc+9; + int num_c_args; + char **old_argv; + + old_argv = argv; + expandargv (&argc, &argv); + if (argv != old_argv) + at_file_supplied = 1; + + num_c_args = argc + 9; no_demangle = !! getenv ("COLLECT_NO_DEMANGLE"); @@ -1513,6 +1530,12 @@ do_wait (const char *prog, struct pex_obj *pex) error ("%s returned %d exit status", prog, ret); collect_exit (ret); } + + if (response_file) + { + unlink (response_file); + response_file = NULL; + } } @@ -1525,6 +1548,47 @@ collect_execute (const char *prog, char **argv, const char *outname, struct pex_obj *pex; const char *errmsg; int err; + char *response_arg = NULL; + char *response_argv[3] ATTRIBUTE_UNUSED; + + if (HAVE_GNU_LD && at_file_supplied && argv[0] != NULL) + { + /* If using @file arguments, create a temporary file and put the + contents of argv into it. Then change argv to an array corresponding + to a single argument @FILE, where FILE is the temporary filename. */ + + char **current_argv = argv + 1; + char *argv0 = argv[0]; + int status; + FILE *f; + + /* Note: we assume argv contains at least one element; this is + checked above. */ + + response_file = make_temp_file (""); + + f = fopen (response_file, "w"); + + if (f == NULL) + fatal ("could not open response file %s", response_file); + + status = writeargv (current_argv, f); + + if (status) + fatal ("could not write to response file %s", response_file); + + status = fclose (f); + + if (EOF == status) + fatal ("could not close response file %s", response_file); + + response_arg = concat ("@", response_file, NULL); + response_argv[0] = argv0; + response_argv[1] = response_arg; + response_argv[2] = NULL; + + argv = response_argv; + } if (vflag || debug) { @@ -1568,6 +1632,9 @@ collect_execute (const char *prog, char **argv, const char *outname, fatal (errmsg); } + if (response_arg) + free (response_arg); + return pex; } diff --git a/gcc/config.gcc b/gcc/config.gcc index 31b10d4b5e1..a26f3ddd933 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -2370,6 +2370,10 @@ sparc-*-sysv4*) extra_parts="crtbegin.o crtend.o" use_fixproto=yes ;; +sparc-wrs-vxworks) + tm_file="${tm_file} elfos.h svr4.h sparc/sysv4.h vx-common.h vxworks.h sparc/vxworks.h" + tmake_file="${tmake_file} sparc/t-vxworks" + ;; sparc64-*-elf*) tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/sp64-elf.h" extra_options="${extra_options} sparc/little-endian.opt" diff --git a/gcc/config.in b/gcc/config.in index 7e60a3ef347..7864d8c066f 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -869,6 +869,12 @@ #endif +/* Define if using GNU ld. */ +#ifndef USED_FOR_TARGET +#undef HAVE_GNU_LD +#endif + + /* Define if you have the iconv() function. */ #ifndef USED_FOR_TARGET #undef HAVE_ICONV diff --git a/gcc/config/bfin/bfin-protos.h b/gcc/config/bfin/bfin-protos.h index 99151fa9bfd..525ecd32558 100644 --- a/gcc/config/bfin/bfin-protos.h +++ b/gcc/config/bfin/bfin-protos.h @@ -29,7 +29,10 @@ typedef enum bfin_cpu BFIN_CPU_BF531, BFIN_CPU_BF532, BFIN_CPU_BF533, - BFIN_CPU_BF537 + BFIN_CPU_BF534, + BFIN_CPU_BF536, + BFIN_CPU_BF537, + BFIN_CPU_BF561 } bfin_cpu_t; /* Value of -mcpu= */ @@ -83,13 +86,14 @@ extern void override_options (void); extern void asm_conditional_branch (rtx, rtx *, int, int); extern rtx bfin_gen_compare (rtx, Mmode); +extern int bfin_local_alignment (tree, int); extern int bfin_return_in_memory (tree); extern void initialize_trampoline (rtx, rtx, rtx); extern bool bfin_legitimate_address_p (Mmode, rtx, int); extern rtx bfin_va_arg (tree, tree); extern void bfin_expand_prologue (void); -extern void bfin_expand_epilogue (int, int); +extern void bfin_expand_epilogue (int, int, bool); extern int push_multiple_operation (rtx, Mmode); extern int pop_multiple_operation (rtx, Mmode); extern void output_push_multiple (rtx, rtx *); diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c index 727f2ca9b81..94849ce225b 100644 --- a/gcc/config/bfin/bfin.c +++ b/gcc/config/bfin/bfin.c @@ -569,12 +569,14 @@ frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related) RTX_FRAME_RELATED_P (insn) = 1; } -/* Generate efficient code to add a value to a P register. We can use - P1 as a scratch register. Set RTX_FRAME_RELATED_P on the generated - insns if FRAME is nonzero. */ +/* Generate efficient code to add a value to a P register. + Set RTX_FRAME_RELATED_P on the generated insns if FRAME is nonzero. + EPILOGUE_P is zero if this function is called for prologue, + otherwise it's nonzero. And it's less than zero if this is for + sibcall epilogue. */ static void -add_to_reg (rtx reg, HOST_WIDE_INT value, int frame) +add_to_reg (rtx reg, HOST_WIDE_INT value, int frame, int epilogue_p) { if (value == 0) return; @@ -584,9 +586,41 @@ add_to_reg (rtx reg, HOST_WIDE_INT value, int frame) in one instruction. */ if (value > 120 || value < -120) { - rtx tmpreg = gen_rtx_REG (SImode, REG_P1); + rtx tmpreg; + rtx tmpreg2; rtx insn; + tmpreg2 = NULL_RTX; + + /* For prologue or normal epilogue, P1 can be safely used + as the temporary register. For sibcall epilogue, we try to find + a call used P register, which will be restored in epilogue. + If we cannot find such a P register, we have to use one I register + to help us. */ + + if (epilogue_p >= 0) + tmpreg = gen_rtx_REG (SImode, REG_P1); + else + { + int i; + for (i = REG_P0; i <= REG_P5; i++) + if ((regs_ever_live[i] && ! call_used_regs[i]) + || (!TARGET_FDPIC + && i == PIC_OFFSET_TABLE_REGNUM + && (current_function_uses_pic_offset_table + || (TARGET_ID_SHARED_LIBRARY + && ! current_function_is_leaf)))) + break; + if (i <= REG_P5) + tmpreg = gen_rtx_REG (SImode, i); + else + { + tmpreg = gen_rtx_REG (SImode, REG_P1); + tmpreg2 = gen_rtx_REG (SImode, REG_I0); + emit_move_insn (tmpreg2, tmpreg); + } + } + if (frame) frame_related_constant_load (tmpreg, value, TRUE); else @@ -595,6 +629,9 @@ add_to_reg (rtx reg, HOST_WIDE_INT value, int frame) insn = emit_insn (gen_addsi3 (reg, reg, tmpreg)); if (frame) RTX_FRAME_RELATED_P (insn) = 1; + + if (tmpreg2 != NULL_RTX) + emit_move_insn (tmpreg, tmpreg2); } else do @@ -702,14 +739,17 @@ do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all) rtx insn = emit_insn (pat); RTX_FRAME_RELATED_P (insn) = 1; } - add_to_reg (spreg, -frame_size, 1); + add_to_reg (spreg, -frame_size, 1, 0); } } -/* Like do_link, but used for epilogues to deallocate the stack frame. */ +/* Like do_link, but used for epilogues to deallocate the stack frame. + EPILOGUE_P is zero if this function is called for prologue, + otherwise it's nonzero. And it's less than zero if this is for + sibcall epilogue. */ static void -do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all) +do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p) { frame_size += arg_area_size (); @@ -719,7 +759,7 @@ do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all) { rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg)); - add_to_reg (spreg, frame_size, 0); + add_to_reg (spreg, frame_size, 0, epilogue_p); if (must_save_fp_p ()) { rtx fpreg = gen_rtx_REG (Pmode, REG_FP); @@ -842,7 +882,7 @@ expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind) insns. */ MEM_VOLATILE_P (postinc) = 1; - do_unlink (spreg, get_frame_size (), all); + do_unlink (spreg, get_frame_size (), all, 1); if (lookup_attribute ("nesting", attrs)) { @@ -968,7 +1008,7 @@ bfin_expand_prologue (void) { if (lim != p2reg) emit_move_insn (p2reg, lim); - add_to_reg (p2reg, offset, 0); + add_to_reg (p2reg, offset, 0, 0); lim = p2reg; } emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim)); @@ -987,13 +1027,15 @@ bfin_expand_prologue (void) /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero if this is for a sibcall. EH_RETURN is nonzero if we're expanding an - eh_return pattern. */ + eh_return pattern. SIBCALL_P is true if this is a sibcall epilogue, + false otherwise. */ void -bfin_expand_epilogue (int need_return, int eh_return) +bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p) { rtx spreg = gen_rtx_REG (Pmode, REG_SP); e_funkind fkind = funkind (TREE_TYPE (current_function_decl)); + int e = sibcall_p ? -1 : 1; if (fkind != SUBROUTINE) { @@ -1001,7 +1043,7 @@ bfin_expand_epilogue (int need_return, int eh_return) return; } - do_unlink (spreg, get_frame_size (), false); + do_unlink (spreg, get_frame_size (), false, e); expand_epilogue_reg_restore (spreg, false, false); @@ -2077,8 +2119,17 @@ bfin_handle_option (size_t code, const char *arg, int value) bfin_cpu_type = BFIN_CPU_BF532; else if (strcmp (arg, "bf533") == 0) bfin_cpu_type = BFIN_CPU_BF533; + else if (strcmp (arg, "bf534") == 0) + bfin_cpu_type = BFIN_CPU_BF534; + else if (strcmp (arg, "bf536") == 0) + bfin_cpu_type = BFIN_CPU_BF536; else if (strcmp (arg, "bf537") == 0) bfin_cpu_type = BFIN_CPU_BF537; + else if (strcmp (arg, "bf561") == 0) + { + warning (0, "bf561 support is incomplete yet."); + bfin_cpu_type = BFIN_CPU_BF561; + } else return false; return true; @@ -2994,6 +3045,24 @@ bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp) return false; } +/* Compute the alignment for a local variable. + TYPE is the data type, and ALIGN is the alignment that + the object would ordinarily have. The value of this macro is used + instead of that alignment to align the object. */ + +int +bfin_local_alignment (tree type, int align) +{ + /* Increasing alignment for (relatively) big types allows the builtin + memcpy can use 32 bit loads/stores. */ + if (TYPE_SIZE (type) + && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST + && (TREE_INT_CST_LOW (TYPE_SIZE (type)) > 8 + || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 32) + return 32; + return align; +} + /* Implement TARGET_SCHED_ISSUE_RATE. */ static int diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h index c600af395d6..b78ecb2c84a 100644 --- a/gcc/config/bfin/bfin.h +++ b/gcc/config/bfin/bfin.h @@ -59,9 +59,18 @@ extern int target_flags; case BFIN_CPU_BF533: \ builtin_define ("__ADSPBF533__"); \ break; \ + case BFIN_CPU_BF534: \ + builtin_define ("__ADSPBF534__"); \ + break; \ + case BFIN_CPU_BF536: \ + builtin_define ("__ADSPBF536__"); \ + break; \ case BFIN_CPU_BF537: \ builtin_define ("__ADSPBF537__"); \ break; \ + case BFIN_CPU_BF561: \ + builtin_define ("__ADSPBF561__"); \ + break; \ } \ \ if (TARGET_FDPIC) \ @@ -218,6 +227,18 @@ extern const char *bfin_library_id_string; /*#define DATA_ALIGNMENT(TYPE, BASIC-ALIGN) for arrays.. */ +/* If defined, a C expression to compute the alignment for a local + variable. TYPE is the data type, and ALIGN is the alignment that + the object would ordinarily have. The value of this macro is used + instead of that alignment to align the object. + + If this macro is not defined, then ALIGN is used. + + One use of this macro is to increase alignment of medium-size + data to make it all fit in fewer cache lines. */ + +#define LOCAL_ALIGNMENT(TYPE, ALIGN) bfin_local_alignment ((TYPE), (ALIGN)) + /* Make strings word-aligned so strcpy from constants will be faster. */ #define CONSTANT_ALIGNMENT(EXP, ALIGN) \ (TREE_CODE (EXP) == STRING_CST \ @@ -913,6 +934,10 @@ do { \ in one reasonably fast instruction. */ #define MOVE_MAX UNITS_PER_WORD +/* If a memory-to-memory move would take MOVE_RATIO or more simple + move-instruction pairs, we will do a movmem or libcall instead. */ + +#define MOVE_RATIO 5 /* STORAGE LAYOUT: target machine storage layout Define this macro as a C expression which is nonzero if accessing diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md index 7b238c64982..630694a0f9c 100644 --- a/gcc/config/bfin/bfin.md +++ b/gcc/config/bfin/bfin.md @@ -2668,12 +2668,12 @@ (define_expand "epilogue" [(const_int 1)] "" - "bfin_expand_epilogue (1, 0); DONE;") + "bfin_expand_epilogue (1, 0, 0); DONE;") (define_expand "sibcall_epilogue" [(const_int 1)] "" - "bfin_expand_epilogue (0, 0); DONE;") + "bfin_expand_epilogue (0, 0, 1); DONE;") (define_expand "eh_return" [(unspec_volatile [(match_operand:SI 0 "register_operand" "")] @@ -2693,7 +2693,7 @@ "#" "reload_completed" [(const_int 1)] - "bfin_expand_epilogue (1, 1); DONE;") + "bfin_expand_epilogue (1, 1, 0); DONE;") (define_insn "link" [(set (mem:SI (plus:SI (reg:SI REG_SP) (const_int -4))) (reg:SI REG_RETS)) diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index a3936546d7b..7e2accf4625 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -2792,7 +2792,8 @@ ix86_function_regparm (tree type, tree decl) return 2; /* Use register calling convention for local functions when possible. */ - if (decl && flag_unit_at_a_time && !profile_flag) + if (decl && TREE_CODE (decl) == FUNCTION_DECL + && flag_unit_at_a_time && !profile_flag) { struct cgraph_local_info *i = cgraph_local_info (decl); if (i && i->local) diff --git a/gcc/config/m32c/jump.md b/gcc/config/m32c/jump.md index 4a358eac40f..f0983d1532d 100644 --- a/gcc/config/m32c/jump.md +++ b/gcc/config/m32c/jump.md @@ -69,7 +69,18 @@ "" "* switch (which_alternative) { - case 0: return \"jsr.a\t%0\"; + case 0: + { + HOST_WIDE_INT func_vect_num = + current_function_special_page_vector(XEXP (operands[0], 0)); + if (func_vect_num) + { + operands[3] = gen_rtx_CONST_INT (VOIDmode, func_vect_num); + return \"jsrs\t%3\"; + } + else + return \"jsr.a\t%0\"; + } case 1: return TARGET_A16 ? \"push.w %a0 | jsr.a\tm32c_jsri16\" : \"jsri.a\t%a0\"; case 2: return \"jsri.a\t%a0\"; }" @@ -84,7 +95,18 @@ switch (which_alternative) { "" "* switch (which_alternative) { - case 0: return \"jsr.a\t%1\"; + case 0: + { + HOST_WIDE_INT func_vect_num = + current_function_special_page_vector(XEXP (operands[1], 0)); + if (func_vect_num) + { + operands[4] = gen_rtx_CONST_INT (VOIDmode, func_vect_num); + return \"jsrs\t%4\"; + } + else + return \"jsr.a\t%1\"; + } case 1: return TARGET_A16 ? \"push.w %a1 | jsr.a\tm32c_jsri16\" : \"jsri.a\t%a1\"; case 2: return \"jsri.a\t%a1\"; }" diff --git a/gcc/config/m32c/m32c-protos.h b/gcc/config/m32c/m32c-protos.h index 5735ee75867..5bbc67cbb32 100644 --- a/gcc/config/m32c/m32c-protos.h +++ b/gcc/config/m32c/m32c-protos.h @@ -112,6 +112,7 @@ void m32c_function_arg_advance (CUMULATIVE_ARGS *, MM, tree, int); tree m32c_gimplify_va_arg_expr (tree, tree, tree *, tree *); void m32c_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int); bool m32c_promote_function_return (tree); +int m32c_special_page_vector_p (tree); #endif diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c index de7ce9d7a0f..dd0bce33299 100644 --- a/gcc/config/m32c/m32c.c +++ b/gcc/config/m32c/m32c.c @@ -61,6 +61,7 @@ typedef enum } Push_Pop_Type; static tree interrupt_handler (tree *, tree, tree, int, bool *); +static tree function_vector_handler (tree *, tree, tree, int, bool *); static int interrupt_p (tree node); static bool m32c_asm_integer (rtx, unsigned int, int); static int m32c_comp_type_attributes (tree, tree); @@ -75,6 +76,9 @@ static bool m32c_strict_argument_naming (CUMULATIVE_ARGS *); static rtx m32c_struct_value_rtx (tree, int); static rtx m32c_subreg (enum machine_mode, rtx, enum machine_mode, int); static int need_to_save (int); +int current_function_special_page_vector (rtx); + +#define SYMBOL_FLAG_FUNCVEC_FUNCTION (SYMBOL_FLAG_MACH_DEP << 0) #define streq(a,b) (strcmp ((a), (b)) == 0) @@ -2721,10 +2725,104 @@ interrupt_handler (tree * node ATTRIBUTE_UNUSED, return NULL_TREE; } +/* Returns TRUE if given tree has the "function_vector" attribute. */ +int +m32c_special_page_vector_p (tree func) +{ + if (TREE_CODE (func) != FUNCTION_DECL) + return 0; + + tree list = M32C_ATTRIBUTES (func); + while (list) + { + if (is_attribute_p ("function_vector", TREE_PURPOSE (list))) + return 1; + list = TREE_CHAIN (list); + } + return 0; +} + +static tree +function_vector_handler (tree * node ATTRIBUTE_UNUSED, + tree name ATTRIBUTE_UNUSED, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool * no_add_attrs ATTRIBUTE_UNUSED) +{ + if (TARGET_R8C) + { + /* The attribute is not supported for R8C target. */ + warning (OPT_Wattributes, + "`%s' attribute is not supported for R8C target", + IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + else if (TREE_CODE (*node) != FUNCTION_DECL) + { + /* The attribute must be applied to functions only. */ + warning (OPT_Wattributes, + "`%s' attribute applies only to functions", + IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + else if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST) + { + /* The argument must be a constant integer. */ + warning (OPT_Wattributes, + "`%s' attribute argument not an integer constant", + IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + else if (TREE_INT_CST_LOW (TREE_VALUE (args)) < 18 + || TREE_INT_CST_LOW (TREE_VALUE (args)) > 255) + { + /* The argument value must be between 18 to 255. */ + warning (OPT_Wattributes, + "`%s' attribute argument should be between 18 to 255", + IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + return NULL_TREE; +} + +/* If the function is assigned the attribute 'function_vector', it + returns the function vector number, otherwise returns zero. */ +int +current_function_special_page_vector (rtx x) +{ + int num; + + if ((GET_CODE(x) == SYMBOL_REF) + && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_FUNCVEC_FUNCTION)) + { + tree t = SYMBOL_REF_DECL (x); + + if (TREE_CODE (t) != FUNCTION_DECL) + return 0; + + tree list = M32C_ATTRIBUTES (t); + while (list) + { + if (is_attribute_p ("function_vector", TREE_PURPOSE (list))) + { + num = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (list))); + return num; + } + + list = TREE_CHAIN (list); + } + + return 0; + } + else + return 0; +} + #undef TARGET_ATTRIBUTE_TABLE #define TARGET_ATTRIBUTE_TABLE m32c_attribute_table static const struct attribute_spec m32c_attribute_table[] = { {"interrupt", 0, 0, false, false, false, interrupt_handler}, + {"function_vector", 1, 1, true, false, false, function_vector_handler}, {0, 0, 0, 0, 0, 0, 0} }; @@ -3751,6 +3849,23 @@ m32c_scc_pattern(rtx *operands, RTX_CODE code) return buf; } +/* Encode symbol attributes of a SYMBOL_REF into its + SYMBOL_REF_FLAGS. */ +static void +m32c_encode_section_info (tree decl, rtx rtl, int first) +{ + int extra_flags = 0; + + default_encode_section_info (decl, rtl, first); + if (TREE_CODE (decl) == FUNCTION_DECL + && m32c_special_page_vector_p (decl)) + + extra_flags = SYMBOL_FLAG_FUNCVEC_FUNCTION; + + if (extra_flags) + SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= extra_flags; +} + /* Returns TRUE if the current function is a leaf, and thus we can determine which registers an interrupt function really needs to save. The logic below is mostly about finding the insn sequence @@ -4164,6 +4279,9 @@ m32c_output_compare (rtx insn, rtx *operands) return template + 1; } +#undef TARGET_ENCODE_SECTION_INFO +#define TARGET_ENCODE_SECTION_INFO m32c_encode_section_info + /* The Global `targetm' Variable. */ struct gcc_target targetm = TARGET_INITIALIZER; diff --git a/gcc/config/m32c/muldiv.md b/gcc/config/m32c/muldiv.md index 6913ea9a729..b6c6565baa5 100644 --- a/gcc/config/m32c/muldiv.md +++ b/gcc/config/m32c/muldiv.md @@ -82,7 +82,7 @@ (define_insn "mulhisi3_c" [(set (match_operand:SI 0 "ra_operand" "=Rsi") (mult:SI (sign_extend:SI (match_operand:HI 1 "mra_operand" "%0")) - (match_operand 2 "immediate_operand" "i")))] + (match_operand:HI 2 "immediate_operand" "i")))] "" "mul.w\t%2,%1" [(set_attr "flags" "o")] @@ -159,7 +159,14 @@ }" ) - +(define_insn "mulsi3" + [(set (match_operand:SI 0 "r0123_operand" "=R02,R02") + (mult:SI (match_operand:SI 1 "r0123_operand" "%0,0") + (match_operand:SI 2 "mra_operand" "RsiSd,?Rmm")))] + "TARGET_M32C" + "mul.l\t%2,%1" + [(set_attr "flags" "o")] +) (define_expand "divmodqi4" [(set (match_dup 4) @@ -260,3 +267,23 @@ "divu.w\t%2" [(set_attr "flags" "o")] ) + +(define_insn "divsi3" + [(set (match_operand:SI 0 "r0123_operand" "=R02,R02") + (div:SI (match_operand:SI 1 "r0123_operand" "0,0") + (match_operand:SI 2 "mra_operand" "RsiSd,?Rmm")))] + "TARGET_M32C" + "div.l\t%2" + [(set_attr "flags" "o")] +) + +(define_insn "udivsi3" + [(set (match_operand:SI 0 "r0123_operand" "=R02,R02") + (udiv:SI (match_operand:SI 1 "r0123_operand" "0,0") + (match_operand:SI 2 "mra_operand" "RsiSd,?Rmm")))] + "TARGET_M32C" + "divu.l\t%2" + [(set_attr "flags" "o")] +) + + diff --git a/gcc/config/m32c/shift.md b/gcc/config/m32c/shift.md index 6679f38ffe7..6b8a4835883 100644 --- a/gcc/config/m32c/shift.md +++ b/gcc/config/m32c/shift.md @@ -175,7 +175,7 @@ (define_insn "ashlpsi3_i" [(set (match_operand:PSI 0 "mra_operand" "=R02RaaSd*Rmm,R02RaaSd*Rmm") (ashift:PSI (match_operand:PSI 1 "mra_operand" "0,0") - (match_operand:QI 2 "mrai_operand" "In4,RqiSd"))) + (match_operand:QI 2 "shiftcount_operand" "In4,RqiSd"))) (clobber (match_scratch:HI 3 "=X,R1w"))] "TARGET_A24" "@ @@ -187,7 +187,7 @@ (define_insn "ashrpsi3_i" [(set (match_operand:PSI 0 "mra_operand" "=R02RaaSd*Rmm,R02RaaSd*Rmm") (ashiftrt:PSI (match_operand:PSI 1 "mra_operand" "0,0") - (neg:QI (match_operand:QI 2 "mrai_operand" "In4,RqiSd")))) + (neg:QI (match_operand:QI 2 "shiftcount_operand" "In4,RqiSd")))) (clobber (match_scratch:HI 3 "=X,R1w"))] "TARGET_A24" "@ @@ -212,7 +212,7 @@ (define_expand "ashlpsi3" [(parallel [(set (match_operand:PSI 0 "mra_operand" "") (ashift:PSI (match_operand:PSI 1 "mra_operand" "") - (match_operand:QI 2 "mrai_operand" ""))) + (match_operand:QI 2 "shiftcount_operand" ""))) (clobber (match_scratch:HI 3 ""))])] "TARGET_A24" "if (m32c_prepare_shift (operands, 1, ASHIFT)) @@ -222,7 +222,7 @@ (define_expand "ashrpsi3" [(parallel [(set (match_operand:PSI 0 "mra_operand" "") (ashiftrt:PSI (match_operand:PSI 1 "mra_operand" "") - (neg:QI (match_operand:QI 2 "mrai_operand" "")))) + (neg:QI (match_operand:QI 2 "shiftcount_operand" "")))) (clobber (match_scratch:HI 3 ""))])] "TARGET_A24" "if (m32c_prepare_shift (operands, -1, ASHIFTRT)) @@ -232,7 +232,7 @@ (define_expand "lshrpsi3" [(parallel [(set (match_operand:PSI 0 "mra_operand" "") (lshiftrt:PSI (match_operand:PSI 1 "mra_operand" "") - (neg:QI (match_operand:QI 2 "mrai_operand" "")))) + (neg:QI (match_operand:QI 2 "shiftcount_operand" "")))) (clobber (match_scratch:HI 3 ""))])] "TARGET_A24" "if (m32c_prepare_shift (operands, -1, LSHIFTRT)) diff --git a/gcc/config/mips/mips-dspr2.md b/gcc/config/mips/mips-dspr2.md index dd0aab553a1..20190085177 100644 --- a/gcc/config/mips/mips-dspr2.md +++ b/gcc/config/mips/mips-dspr2.md @@ -162,31 +162,13 @@ (match_operand:DI 1 "register_operand")))] "TARGET_DSPR2 && !TARGET_64BIT") -(define_insn "mips_msub" - [(set (match_operand:DI 0 "register_operand" "=a") - (minus:DI - (match_operand:DI 1 "register_operand" "0") - (mult:DI (sign_extend:DI - (match_operand:SI 2 "register_operand" "d")) - (sign_extend:DI - (match_operand:SI 3 "register_operand" "d")))))] - "TARGET_DSPR2 && !TARGET_64BIT" - "msub\t%q0,%2,%3" - [(set_attr "type" "imadd") - (set_attr "mode" "SI")]) - -(define_insn "mips_msubu" - [(set (match_operand:DI 0 "register_operand" "=a") +(define_expand "mips_msub<u>" + [(set (match_operand:DI 0 "register_operand") (minus:DI - (match_operand:DI 1 "register_operand" "0") - (mult:DI (zero_extend:DI - (match_operand:SI 2 "register_operand" "d")) - (zero_extend:DI - (match_operand:SI 3 "register_operand" "d")))))] - "TARGET_DSPR2 && !TARGET_64BIT" - "msubu\t%q0,%2,%3" - [(set_attr "type" "imadd") - (set_attr "mode" "SI")]) + (match_operand:DI 1 "register_operand") + (mult:DI (any_extend:DI (match_operand:SI 2 "register_operand")) + (any_extend:DI (match_operand:SI 3 "register_operand")))))] + "TARGET_DSPR2 && !TARGET_64BIT") (define_insn "mulv2hi3" [(parallel diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 55bacf7bb19..a719a1020dd 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -3528,7 +3528,7 @@ mips_emit_fcc_reload (rtx dest, rtx src, rtx scratch) src = gen_rtx_REG (SFmode, true_regnum (src)); fp1 = gen_rtx_REG (SFmode, REGNO (scratch)); - fp2 = gen_rtx_REG (SFmode, REGNO (scratch) + FP_INC); + fp2 = gen_rtx_REG (SFmode, REGNO (scratch) + MAX_FPRS_PER_FMT); emit_move_insn (copy_rtx (fp1), src); emit_move_insn (copy_rtx (fp2), CONST0_RTX (SFmode)); @@ -3872,7 +3872,7 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, if (mips_abi != ABI_EABI || !info.fpr_p) cum->num_gprs = info.reg_offset + info.reg_words; else if (info.reg_words > 0) - cum->num_fprs += FP_INC; + cum->num_fprs += MAX_FPRS_PER_FMT; if (info.stack_words > 0) cum->stack_words = info.stack_offset + info.stack_words; @@ -4006,10 +4006,11 @@ function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, if (!info.fpr_p) return gen_rtx_REG (mode, GP_ARG_FIRST + info.reg_offset); - else if (info.reg_offset == 1) - /* This code handles the special o32 case in which the second word - of the argument structure is passed in floating-point registers. */ - return gen_rtx_REG (mode, FP_ARG_FIRST + FP_INC); + else if (mips_abi == ABI_32 && TARGET_DOUBLE_FLOAT && info.reg_offset > 0) + /* In o32, the second argument is always passed in $f14 + for TARGET_DOUBLE_FLOAT, regardless of whether the + first argument was a word or doubleword. */ + return gen_rtx_REG (mode, FP_ARG_FIRST + 2); else return gen_rtx_REG (mode, FP_ARG_FIRST + info.reg_offset); } @@ -4150,7 +4151,8 @@ mips_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode, mode = TARGET_SINGLE_FLOAT ? SFmode : DFmode; - for (i = local_cum.num_fprs; i < MAX_ARGS_IN_REGISTERS; i += FP_INC) + for (i = local_cum.num_fprs; i < MAX_ARGS_IN_REGISTERS; + i += MAX_FPRS_PER_FMT) { rtx ptr, mem; @@ -5098,7 +5100,9 @@ override_options (void) temp = ((regno & 1) == 0 || size <= UNITS_PER_WORD); else if (FP_REG_P (regno)) - temp = ((regno % FP_INC) == 0) + temp = ((((regno % MAX_FPRS_PER_FMT) == 0) + || (MIN_FPRS_PER_FMT == 1 + && size <= UNITS_PER_FPREG)) && (((class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT || class == MODE_VECTOR_FLOAT) && size <= UNITS_PER_FPVALUE) @@ -5112,7 +5116,7 @@ override_options (void) && size >= MIN_UNITS_PER_WORD && size <= UNITS_PER_FPREG) /* Allow TFmode for CCmode reloads. */ - || (ISA_HAS_8CC && mode == TFmode)); + || (ISA_HAS_8CC && mode == TFmode))); else if (ACC_REG_P (regno)) temp = (INTEGRAL_MODE_P (mode) @@ -6285,6 +6289,15 @@ mips_save_reg_p (unsigned int regno) if (regs_ever_live[regno] && !call_used_regs[regno]) return true; + /* Save both registers in an FPR pair if either one is used. This is + needed for the case when MIN_FPRS_PER_FMT == 1, which allows the odd + register to be used without the even register. */ + if (FP_REG_P (regno) + && MAX_FPRS_PER_FMT == 2 + && regs_ever_live[regno + 1] + && !call_used_regs[regno + 1]) + return true; + /* We need to save the old frame pointer before setting up a new one. */ if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) return true; @@ -6437,15 +6450,15 @@ compute_frame_size (HOST_WIDE_INT size) } /* This loop must iterate over the same space as its companion in - save_restore_insns. */ - for (regno = (FP_REG_LAST - FP_INC + 1); + mips_for_each_saved_reg. */ + for (regno = (FP_REG_LAST - MAX_FPRS_PER_FMT + 1); regno >= FP_REG_FIRST; - regno -= FP_INC) + regno -= MAX_FPRS_PER_FMT) { if (mips_save_reg_p (regno)) { - fp_reg_size += FP_INC * UNITS_PER_FPREG; - fmask |= ((1 << FP_INC) - 1) << (regno - FP_REG_FIRST); + fp_reg_size += MAX_FPRS_PER_FMT * UNITS_PER_FPREG; + fmask |= ((1 << MAX_FPRS_PER_FMT) - 1) << (regno - FP_REG_FIRST); } } @@ -6467,7 +6480,8 @@ compute_frame_size (HOST_WIDE_INT size) cfun->machine->frame.fmask = fmask; cfun->machine->frame.initialized = reload_completed; cfun->machine->frame.num_gp = gp_reg_size / UNITS_PER_WORD; - cfun->machine->frame.num_fp = fp_reg_size / (FP_INC * UNITS_PER_FPREG); + cfun->machine->frame.num_fp = (fp_reg_size + / (MAX_FPRS_PER_FMT * UNITS_PER_FPREG)); if (mask) { @@ -6490,7 +6504,7 @@ compute_frame_size (HOST_WIDE_INT size) offset = (args_size + cprestore_size + var_size + gp_reg_rounded + fp_reg_size - - FP_INC * UNITS_PER_FPREG); + - MAX_FPRS_PER_FMT * UNITS_PER_FPREG); cfun->machine->frame.fp_sp_offset = offset; cfun->machine->frame.fp_save_offset = offset - total_size; } @@ -6593,9 +6607,9 @@ mips_for_each_saved_reg (HOST_WIDE_INT sp_offset, mips_save_restore_fn fn) compute_frame_size. */ offset = cfun->machine->frame.fp_sp_offset - sp_offset; fpr_mode = (TARGET_SINGLE_FLOAT ? SFmode : DFmode); - for (regno = (FP_REG_LAST - FP_INC + 1); + for (regno = (FP_REG_LAST - MAX_FPRS_PER_FMT + 1); regno >= FP_REG_FIRST; - regno -= FP_INC) + regno -= MAX_FPRS_PER_FMT) if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST)) { mips_save_restore_reg (fpr_mode, regno, offset, fn); @@ -7507,7 +7521,7 @@ mips_return_fpr_pair (enum machine_mode mode, { int inc; - inc = (TARGET_NEWABI ? 2 : FP_INC); + inc = (TARGET_NEWABI ? 2 : MAX_FPRS_PER_FMT); return gen_rtx_PARALLEL (mode, gen_rtvec (2, @@ -7645,7 +7659,7 @@ mips_cannot_change_mode_class (enum machine_mode from, registers, the first register always holds the low word. We therefore can't allow FPRs to change between single-word and multi-word modes. */ - if (FP_INC > 1 && reg_classes_intersect_p (FP_REGS, class)) + if (MAX_FPRS_PER_FMT > 1 && reg_classes_intersect_p (FP_REGS, class)) return true; } else diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index e3c631e087e..fff2e660400 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -1021,13 +1021,19 @@ extern const struct mips_rtx_cost_data *mips_cost; /* For MIPS, width of a floating point register. */ #define UNITS_PER_FPREG (TARGET_FLOAT64 ? 8 : 4) -/* If register $f0 holds a floating-point value, $f(0 + FP_INC) is - the next available register. */ -#define FP_INC (TARGET_FLOAT64 || TARGET_SINGLE_FLOAT ? 1 : 2) +/* The number of consecutive floating-point registers needed to store the + largest format supported by the FPU. */ +#define MAX_FPRS_PER_FMT (TARGET_FLOAT64 || TARGET_SINGLE_FLOAT ? 1 : 2) + +/* The number of consecutive floating-point registers needed to store the + smallest format supported by the FPU. */ +#define MIN_FPRS_PER_FMT \ + (ISA_MIPS32 || ISA_MIPS32R2 || ISA_MIPS64 ? 1 : MAX_FPRS_PER_FMT) /* The largest size of value that can be held in floating-point registers and moved with a single instruction. */ -#define UNITS_PER_HWFPVALUE (TARGET_SOFT_FLOAT ? 0 : FP_INC * UNITS_PER_FPREG) +#define UNITS_PER_HWFPVALUE \ + (TARGET_SOFT_FLOAT ? 0 : MAX_FPRS_PER_FMT * UNITS_PER_FPREG) /* The largest size of value that can be held in floating-point registers. */ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index e44b919ccb9..de592b9adc7 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -1649,16 +1649,18 @@ [(set_attr "type" "imul") (set_attr "mode" "SI")]) -(define_insn "*msac<u>_di" - [(set (match_operand:DI 0 "register_operand" "=x") +(define_insn "<u>msubsidi4" + [(set (match_operand:DI 0 "register_operand" "=ka") (minus:DI (match_operand:DI 3 "register_operand" "0") (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) (any_extend:DI (match_operand:SI 2 "register_operand" "d")))))] - "!TARGET_64BIT && ISA_HAS_MSAC" + "!TARGET_64BIT && (ISA_HAS_MSAC || GENERATE_MADD_MSUB || TARGET_DSPR2)" { - if (TARGET_MIPS5500) + if (TARGET_DSPR2) + return "msub<u>\t%q0,%1,%2"; + else if (TARGET_MIPS5500 || GENERATE_MADD_MSUB) return "msub<u>\t%1,%2"; else return "msac<u>\t$0,%1,%2"; diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h index 4fb862cc908..c1b2813a3b3 100644 --- a/gcc/config/sparc/sparc-protos.h +++ b/gcc/config/sparc/sparc-protos.h @@ -73,6 +73,7 @@ extern int legitimate_address_p (enum machine_mode, rtx, int); extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx); extern rtx legitimize_tls_address (rtx); extern rtx legitimize_address (rtx, rtx, enum machine_mode); +extern void sparc_emit_call_insn (rtx, rtx); extern void sparc_defer_case_vector (rtx, rtx, int); extern bool sparc_expand_move (enum machine_mode, rtx *); extern void sparc_emit_set_const32 (rtx, rtx); diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index be07ce7d3d0..f94af2ac5d1 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -980,17 +980,27 @@ sparc_expand_move (enum machine_mode mode, rtx *operands) if (pic_address_needs_scratch (operands[1])) operands[1] = legitimize_pic_address (operands[1], mode, 0); - if (GET_CODE (operands[1]) == LABEL_REF && mode == SImode) - { - emit_insn (gen_movsi_pic_label_ref (operands[0], operands[1])); - return true; - } + /* VxWorks does not impose a fixed gap between segments; the run-time + gap can be different from the object-file gap. We therefore can't + assume X - _GLOBAL_OFFSET_TABLE_ is a link-time constant unless we + are absolutely sure that X is in the same segment as the GOT. + Unfortunately, the flexibility of linker scripts means that we + can't be sure of that in general, so assume that _G_O_T_-relative + accesses are never valid on VxWorks. */ + if (GET_CODE (operands[1]) == LABEL_REF && !TARGET_VXWORKS_RTP) + { + if (mode == SImode) + { + emit_insn (gen_movsi_pic_label_ref (operands[0], operands[1])); + return true; + } - if (GET_CODE (operands[1]) == LABEL_REF && mode == DImode) - { - gcc_assert (TARGET_ARCH64); - emit_insn (gen_movdi_pic_label_ref (operands[0], operands[1])); - return true; + if (mode == DImode) + { + gcc_assert (TARGET_ARCH64); + emit_insn (gen_movdi_pic_label_ref (operands[0], operands[1])); + return true; + } } if (symbolic_operand (operands[1], mode)) @@ -3212,7 +3222,9 @@ rtx legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED, rtx reg) { - if (GET_CODE (orig) == SYMBOL_REF) + if (GET_CODE (orig) == SYMBOL_REF + /* See the comment in sparc_expand_move. */ + || (TARGET_VXWORKS_RTP && GET_CODE (orig) == LABEL_REF)) { rtx pic_ref, address; rtx insn; @@ -3377,6 +3389,13 @@ load_pic_register (bool delay_pic_helper) { int orig_flag_pic = flag_pic; + if (TARGET_VXWORKS_RTP) + { + emit_insn (gen_vxworks_load_got ()); + emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx)); + return; + } + /* If we haven't initialized the special PIC symbols, do so now. */ if (!pic_helper_symbol_name[0]) { @@ -3405,6 +3424,29 @@ load_pic_register (bool delay_pic_helper) since we may not fall out the bottom. */ emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx)); } + +/* Emit a call instruction with the pattern given by PAT. ADDR is the + address of the call target. */ + +void +sparc_emit_call_insn (rtx pat, rtx addr) +{ + rtx insn; + + insn = emit_call_insn (pat); + + /* The PIC register is live on entry to VxWorks PIC PLT entries. */ + if (TARGET_VXWORKS_RTP + && flag_pic + && GET_CODE (addr) == SYMBOL_REF + && (SYMBOL_REF_DECL (addr) + ? !targetm.binds_local_p (SYMBOL_REF_DECL (addr)) + : !SYMBOL_REF_LOCAL_P (addr))) + { + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); + current_function_uses_pic_offset_table = 1; + } +} /* Return 1 if RTX is a MEM which is known to be aligned to at least a DESIRED byte boundary. */ @@ -7771,13 +7813,19 @@ sparc_elf_asm_named_section (const char *name, unsigned int flags, the sibling call right? Well, in the C++ case we can end up passing the pointer to the struct return area to a constructor (which returns void) and then nothing else happens. Such a sibling call would look - valid without the added check here. */ + valid without the added check here. + + VxWorks PIC PLT entries require the global pointer to be initialized + on entry. We therefore can't emit sibling calls to them. */ static bool sparc_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) { return (decl && flag_delayed_branch - && (TARGET_ARCH64 || ! current_function_returns_struct)); + && (TARGET_ARCH64 || ! current_function_returns_struct) + && !(TARGET_VXWORKS_RTP + && flag_pic + && !targetm.binds_local_p (decl))); } /* libfunc renaming. */ diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index db0e34e516d..1a4805bb7d3 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -22,6 +22,8 @@ along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "config/vxworks-dummy.h" + /* Note that some other tm.h files include this one and then override whatever definitions are necessary. */ @@ -2409,6 +2411,7 @@ extern int sparc_indent_opcode; else if (GET_CODE (index) == REG) \ fprintf (FILE, "+%s", reg_names[REGNO (index)]); \ else if (GET_CODE (index) == SYMBOL_REF \ + || GET_CODE (index) == LABEL_REF \ || GET_CODE (index) == CONST) \ fputc ('+', FILE), output_addr_const (FILE, index); \ else gcc_unreachable (); \ diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 387b3405db5..6d5797dbe2b 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -1874,6 +1874,22 @@ "flag_pic" "or\t%1, %%lo(%a3-(%a2-.)), %0") +;; Set up the PIC register for VxWorks. + +(define_expand "vxworks_load_got" + [(set (match_dup 0) + (high:SI (match_dup 1))) + (set (match_dup 0) + (mem:SI (lo_sum:SI (match_dup 0) (match_dup 1)))) + (set (match_dup 0) + (mem:SI (lo_sum:SI (match_dup 0) (match_dup 2))))] + "TARGET_VXWORKS_RTP" +{ + operands[0] = pic_offset_table_rtx; + operands[1] = gen_rtx_SYMBOL_REF (SImode, VXWORKS_GOTT_BASE); + operands[2] = gen_rtx_SYMBOL_REF (SImode, VXWORKS_GOTT_INDEX); +}) + (define_expand "movdi" [(set (match_operand:DI 0 "nonimmediate_operand" "") (match_operand:DI 1 "general_operand" ""))] @@ -6676,7 +6692,7 @@ { rtx fn_rtx; - gcc_assert (GET_MODE (operands[0]) == FUNCTION_MODE); + gcc_assert (MEM_P (operands[0]) && GET_MODE (operands[0]) == FUNCTION_MODE); gcc_assert (GET_CODE (operands[3]) == CONST_INT); @@ -6712,18 +6728,20 @@ /* We accept negative sizes for untyped calls. */ if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0) - emit_call_insn + sparc_emit_call_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (3, gen_rtx_CALL (VOIDmode, fn_rtx, const0_rtx), operands[3], - gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15))))); + gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))), + XEXP (fn_rtx, 0)); else - emit_call_insn + sparc_emit_call_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, gen_rtx_CALL (VOIDmode, fn_rtx, const0_rtx), - gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15))))); + gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))), + XEXP (fn_rtx, 0)); finish_call: @@ -6840,7 +6858,7 @@ rtx fn_rtx; rtvec vec; - gcc_assert (GET_MODE (operands[1]) == FUNCTION_MODE); + gcc_assert (MEM_P (operands[1]) && GET_MODE (operands[1]) == FUNCTION_MODE); fn_rtx = operands[1]; @@ -6849,7 +6867,7 @@ gen_rtx_CALL (VOIDmode, fn_rtx, const0_rtx)), gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15))); - emit_call_insn (gen_rtx_PARALLEL (VOIDmode, vec)); + sparc_emit_call_insn (gen_rtx_PARALLEL (VOIDmode, vec), XEXP (fn_rtx, 0)); DONE; }) diff --git a/gcc/config/sparc/t-vxworks b/gcc/config/sparc/t-vxworks new file mode 100644 index 00000000000..2aabf1a43cd --- /dev/null +++ b/gcc/config/sparc/t-vxworks @@ -0,0 +1,5 @@ +# Multilibs for VxWorks. + +MULTILIB_OPTIONS = mrtp fPIC +MULTILIB_MATCHES = fPIC=fpic +MULTILIB_EXCEPTIONS = fPIC diff --git a/gcc/config/sparc/vxworks.h b/gcc/config/sparc/vxworks.h new file mode 100644 index 00000000000..7faacea53ab --- /dev/null +++ b/gcc/config/sparc/vxworks.h @@ -0,0 +1,64 @@ +/* Definitions of target machine for GNU compiler, + for SPARC targeting the VxWorks run time environment. + Copyright (C) 2007 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define TARGET_OS_CPP_BUILTINS() \ + do \ + { \ + builtin_define ("__sparc"); \ + builtin_define ("CPU=SIMSPARCSOLARIS"); \ + VXWORKS_OS_CPP_BUILTINS (); \ + } \ + while (0) + +#undef OVERRIDE_OPTIONS +#define OVERRIDE_OPTIONS \ + do \ + { \ + VXWORKS_OVERRIDE_OPTIONS; \ + sparc_override_options (); \ + } \ + while (0) + +#undef CPP_SUBTARGET_SPEC +#define CPP_SUBTARGET_SPEC VXWORKS_ADDITIONAL_CPP_SPEC + +#undef LIB_SPEC +#define LIB_SPEC VXWORKS_LIB_SPEC +#undef LINK_SPEC +#define LINK_SPEC VXWORKS_LINK_SPEC +#undef STARTFILE_SPEC +#define STARTFILE_SPEC VXWORKS_STARTFILE_SPEC +#undef ENDFILE_SPEC +#define ENDFILE_SPEC VXWORKS_ENDFILE_SPEC + +#undef TARGET_VERSION +#define TARGET_VERSION fputs (" (SPARC/VxWorks)", stderr); + +#undef FUNCTION_PROFILER +#define FUNCTION_PROFILER VXWORKS_FUNCTION_PROFILER + +/* Use standard numbered ctors/dtors sections. */ +#undef CTORS_SECTION_ASM_OP +#undef DTORS_SECTION_ASM_OP + +/* We cannot use PC-relative accesses for VxWorks PIC because there is no + fixed gap between segments. */ +#undef ASM_PREFERRED_EH_DATA_FORMAT diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index 43bcc584856..c331a7f27ad 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -1939,6 +1939,7 @@ xtensa_output_literal (FILE *file, rtx x, enum machine_mode mode, int labelno) long value_long[2]; REAL_VALUE_TYPE r; int size; + rtx first, second; fprintf (file, "\t.literal .LC%u, ", (unsigned) labelno); @@ -1952,11 +1953,18 @@ xtensa_output_literal (FILE *file, rtx x, enum machine_mode mode, int labelno) { case SFmode: REAL_VALUE_TO_TARGET_SINGLE (r, value_long[0]); + if (HOST_BITS_PER_LONG > 32) + value_long[0] &= 0xffffffff; fprintf (file, "0x%08lx\n", value_long[0]); break; case DFmode: REAL_VALUE_TO_TARGET_DOUBLE (r, value_long); + if (HOST_BITS_PER_LONG > 32) + { + value_long[0] &= 0xffffffff; + value_long[1] &= 0xffffffff; + } fprintf (file, "0x%08lx, 0x%08lx\n", value_long[0], value_long[1]); break; @@ -1978,9 +1986,10 @@ xtensa_output_literal (FILE *file, rtx x, enum machine_mode mode, int labelno) break; case 8: - output_addr_const (file, operand_subword (x, 0, 0, DImode)); + split_double (x, &first, &second); + output_addr_const (file, first); fputs (", ", file); - output_addr_const (file, operand_subword (x, 1, 0, DImode)); + output_addr_const (file, second); fputs ("\n", file); break; diff --git a/gcc/configure b/gcc/configure index 17e4fdc7663..b3aa2b09ce7 100755 --- a/gcc/configure +++ b/gcc/configure @@ -1767,6 +1767,13 @@ _ACEOF fi +gnu_ld=`if test x"$gnu_ld_flag" = x"yes"; then echo 1; else echo 0; fi` + +cat >>confdefs.h <<_ACEOF +#define HAVE_GNU_LD $gnu_ld +_ACEOF + + echo "$as_me:$LINENO: checking whether a default linker was specified" >&5 echo $ECHO_N "checking whether a default linker was specified... $ECHO_C" >&6 if test x"${DEFAULT_LINKER+set}" = x"set"; then @@ -7665,7 +7672,7 @@ if test "${gcc_cv_prog_makeinfo_modern+set}" = set; then else ac_prog_version=`$MAKEINFO --version 2>&1 | sed -n 's/^.*GNU texinfo.* \([0-9][0-9.]*\).*$/\1/p'` - echo "configure:7668: version of makeinfo is $ac_prog_version" >&5 + echo "configure:7675: version of makeinfo is $ac_prog_version" >&5 case $ac_prog_version in '') gcc_cv_prog_makeinfo_modern=no;; 4.[4-9]*) diff --git a/gcc/configure.ac b/gcc/configure.ac index 9a7c563ec7b..708ce1681a3 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -206,6 +206,9 @@ if test x"${DEFAULT_LINKER+set}" = x"set"; then [Define to enable the use of a default linker.]) fi +gnu_ld=`if test x"$gnu_ld_flag" = x"yes"; then echo 1; else echo 0; fi` +AC_DEFINE_UNQUOTED(HAVE_GNU_LD, $gnu_ld, [Define if using GNU ld.]) + AC_MSG_CHECKING([whether a default linker was specified]) if test x"${DEFAULT_LINKER+set}" = x"set"; then if test x"$gnu_ld_flag" = x"no"; then diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b4a1c9a1b0a..708da19eeef 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2007-05-07 Andrew Pinski <andrew_pinski@playstation.sony.com> + + * typeck.c (build_unary_op): Remove code that used to + handle non lvalue increments/decrements. + +2007-05-07 Mike Stump <mrs@apple.com> + + * parser.c (check_empty_body): Add. + (cp_parser_iteration_statement): Add call to check_empty_body. + 2007-05-05 Geoffrey Keating <geoffk@apple.com> PR 31775 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 63f7fec0169..4599aca0166 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -7065,6 +7065,51 @@ cp_parser_condition (cp_parser* parser) return cp_parser_expression (parser, /*cast_p=*/false); } +/* We check for a ) immediately followed by ; with no whitespacing + between. This is used to issue a warning for: + + while (...); + + and: + + for (...); + + as the semicolon is probably extraneous. + + On parse errors, the next token might not be a ), so do nothing in + that case. */ + +static void +check_empty_body (cp_parser* parser, const char* type) +{ + cp_token *token; + cp_token *close_paren; + expanded_location close_loc; + expanded_location semi_loc; + + close_paren = cp_lexer_peek_token (parser->lexer); + if (close_paren->type != CPP_CLOSE_PAREN) + return; + + close_loc = expand_location (close_paren->location); + token = cp_lexer_peek_nth_token (parser->lexer, 2); + + if (token->type != CPP_SEMICOLON + || (token->flags & PREV_WHITE)) + return; + + semi_loc = expand_location (token->location); + if (close_loc.line == semi_loc.line +#ifdef USE_MAPPED_LOCATION + && close_loc.column+1 == semi_loc.column +#endif + ) + warning (OPT_Wempty_body, + "suggest a space before %<;%> or explicit braces around empty " + "body in %<%s%> statement", + type); +} + /* Parse an iteration-statement. iteration-statement: @@ -7107,6 +7152,7 @@ cp_parser_iteration_statement (cp_parser* parser) /* Parse the condition. */ condition = cp_parser_condition (parser); finish_while_stmt_cond (condition, statement); + check_empty_body (parser, "while"); /* Look for the `)'. */ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); /* Parse the dependent statement. */ @@ -7168,6 +7214,7 @@ cp_parser_iteration_statement (cp_parser* parser) if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)) expression = cp_parser_expression (parser, /*cast_p=*/false); finish_for_expr (expression, statement); + check_empty_body (parser, "for"); /* Look for the `)'. */ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 45a632493de..1069892a50c 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -1972,7 +1972,7 @@ is used. @xref{C Dialect Options,,Options Controlling C Dialect}. @item function_vector -@cindex calling functions through the function vector on the H8/300 processors +@cindex calling functions through the function vector on H8/300, M16C, and M32C processors Use this attribute on the H8/300, H8/300H, and H8S to indicate that the specified function should be called through the function vector. Calling a function through the function vector will reduce code size, however; @@ -1982,6 +1982,40 @@ and 64 entries on the H8/300H and H8S) and shares space with the interrupt vecto You must use GAS and GLD from GNU binutils version 2.7 or later for this attribute to work correctly. +On M16C/M32C targets, the @code{function_vector} attribute declares a +special page subroutine call function. Use of this attribute reduces +the code size by 2 bytes for each call generated to the +subroutine. The argument to the attribute is the vector number entry +from the special page vector table which contains the 16 low-order +bits of the subroutine's entry address. Each vector table has special +page number (18 to 255) which are used in @code{jsrs} instruction. +Jump addresses of the routines are generated by adding 0x0F0000 (in +case of M16C targets) or 0xFF0000 (in case of M32C targets), to the 2 +byte addresses set in the vector table. Therefore you need to ensure +that all the special page vector routines should get mapped within the +address range 0x0F0000 to 0x0FFFFF (for M16C) and 0xFF0000 to 0xFFFFFF +(for M32C). + +In the following example 2 bytes will be saved for each call to +function @code{foo}. + +@smallexample +void foo (void) __attribute__((function_vector(0x18))); +void foo (void) +@{ +@} + +void bar (void) +@{ + foo(); +@} +@end smallexample + +If functions are defined in one file and are called in another file, +then be sure to write this declaration in both files. + +This attribute is ignored for R8C target. + @item interrupt @cindex interrupt handler functions Use this attribute on the ARM, AVR, C4x, CRX, M32C, M32R/D, MS1, and Xstormy16 diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index e608dbc017e..9e76394146c 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -439,12 +439,13 @@ Objective-C and Objective-C++ Dialects}. -mcall-prologues -mno-tablejump -mtiny-stack -mint8} @emph{Blackfin Options} -@gccoptlist{-momit-leaf-frame-pointer -mno-omit-leaf-frame-pointer @gol --mspecld-anomaly -mno-specld-anomaly -mcsync-anomaly -mno-csync-anomaly @gol --mlow-64k -mno-low64k -mstack-check-l1 -mid-shared-library @gol --mno-id-shared-library -mshared-library-id=@var{n} @gol --mleaf-id-shared-library -mno-leaf-id-shared-library @gol --msep-data -mno-sep-data -mlong-calls -mno-long-calls} +@gccoptlist{-mcpu=@var{cpu} -msim -momit-leaf-frame-pointer @gol +-mno-omit-leaf-frame-pointer -mspecld-anomaly -mno-specld-anomaly @gol +-mcsync-anomaly -mno-csync-anomaly -mlow-64k -mno-low64k @gol +-mstack-check-l1 -mid-shared-library -mno-id-shared-library @gol +-mshared-library-id=@var{n} -mleaf-id-shared-library @gol +-mno-leaf-id-shared-library -msep-data -mno-sep-data -mlong-calls @gol +-mno-long-calls} @emph{CRIS Options} @gccoptlist{-mcpu=@var{cpu} -march=@var{cpu} -mtune=@var{cpu} @gol @@ -3157,6 +3158,11 @@ An empty body occurs in an @samp{if}, @samp{else} or @samp{do while} statement. This warning can be independently controlled by @option{-Wempty-body}. +@item @r{(C++ only)} +An empty body occurs in a @samp{while} or @samp{for} statement with no +whitespacing before the semicolon. This warning can be independently +controlled by @option{-Wempty-body}. + @item A pointer is compared against integer zero with @samp{<}, @samp{<=}, @samp{>}, or @samp{>=}. @@ -3421,8 +3427,10 @@ to them. @item -Wempty-body @opindex Wempty-body -An empty body occurs in an @samp{if}, @samp{else} or @samp{do while} -statement. This warning is also enabled by @option{-Wextra}. +Warn if an empty body occurs in an @samp{if}, @samp{else} or @samp{do +while} statement. Additionally, in C++, warn when an empty body occurs +in a @samp{while} or @samp{for} statement with no whitespacing before +the semicolon. This warning is also enabled by @option{-Wextra}. @item -Wsign-compare @opindex Wsign-compare @@ -8342,6 +8350,23 @@ size. @cindex Blackfin Options @table @gcctabopt +@item -mcpu=@var{cpu} +@opindex mcpu= +Specifies the name of the target Blackfin processor. Currently, @var{cpu} +can be one of @samp{bf531}, @samp{bf532}, @samp{bf533}, +@samp{bf534}, @samp{bf536}, @samp{bf537}, @samp{bf561}. +Without this option, @samp{bf532} is used as the processor by default. +The corresponding predefined processor macros for @var{cpu} is to +be defined. For the @samp{bfin-elf} toolchain, this causes the hardware +BSP provided by libgloss to be linked in if @samp{-msim} is not given. +Support for @samp{bf561} is incomplete; only the processor macro is defined. + +@item -msim +@opindex msim +Specifies that the program will be run on the simulator. This causes +the simulator BSP provided by libgloss to be linked in. This option +has effect only for @samp{bfin-elf} toolchain. + @item -momit-leaf-frame-pointer @opindex momit-leaf-frame-pointer Don't keep the frame pointer in a register for leaf functions. This diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 56cc60f2e1e..53c5769f788 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -3687,6 +3687,25 @@ These instructions are not allowed to @code{FAIL}. Like @code{madd@var{m}@var{n}4}, but zero-extend the multiplication operands instead of sign-extending them. +@cindex @code{msub@var{m}@var{n}4} instruction pattern +@item @samp{msub@var{m}@var{n}4} +Multiply operands 1 and 2, sign-extend them to mode @var{n}, subtract the +result from operand 3, and store the result in operand 0. Operands 1 and 2 +have mode @var{m} and operands 0 and 3 have mode @var{n}. +Both modes must be integer modes and @var{n} must be twice +the size of @var{m}. + +In other words, @code{msub@var{m}@var{n}4} is like +@code{mul@var{m}@var{n}3} except that it also subtracts the result +from operand 3. + +These instructions are not allowed to @code{FAIL}. + +@cindex @code{umsub@var{m}@var{n}4} instruction pattern +@item @samp{umsub@var{m}@var{n}4} +Like @code{msub@var{m}@var{n}4}, but zero-extend the multiplication +operands instead of sign-extending them. + @cindex @code{divmod@var{m}4} instruction pattern @item @samp{divmod@var{m}4} Signed division that produces both a quotient and a remainder. diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index e816026a3d4..cd6bf24d611 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -167,7 +167,6 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def))) static rtx make_call_insn_raw (rtx); static rtx change_address_1 (rtx, enum machine_mode, rtx, int); -static void unshare_all_decls (tree); static void reset_used_decls (tree); static void mark_label_nuses (rtx); static hashval_t const_int_htab_hash (const void *); @@ -2115,17 +2114,8 @@ set_new_first_and_last_insn (rtx first, rtx last) structure. This routine should only be called once. */ static void -unshare_all_rtl_1 (tree fndecl, rtx insn) +unshare_all_rtl_1 (rtx insn) { - tree decl; - - /* Make sure that virtual parameters are not shared. */ - for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl)) - SET_DECL_RTL (decl, copy_rtx_if_shared (DECL_RTL (decl))); - - /* Make sure that virtual stack slots are not shared. */ - unshare_all_decls (DECL_INITIAL (fndecl)); - /* Unshare just about everything else. */ unshare_all_rtl_in_chain (insn); @@ -2166,13 +2156,13 @@ unshare_all_rtl_again (rtx insn) reset_used_flags (stack_slot_list); - unshare_all_rtl_1 (cfun->decl, insn); + unshare_all_rtl_1 (insn); } unsigned int unshare_all_rtl (void) { - unshare_all_rtl_1 (current_function_decl, get_insns ()); + unshare_all_rtl_1 (get_insns ()); return 0; } @@ -2358,23 +2348,6 @@ unshare_all_rtl_in_chain (rtx insn) } } -/* Go through all virtual stack slots of a function and copy any - shared structure. */ -static void -unshare_all_decls (tree blk) -{ - tree t; - - /* Copy shared decls. */ - for (t = BLOCK_VARS (blk); t; t = TREE_CHAIN (t)) - if (DECL_RTL_SET_P (t)) - SET_DECL_RTL (t, copy_rtx_if_shared (DECL_RTL (t))); - - /* Now process sub-blocks. */ - for (t = BLOCK_SUBBLOCKS (blk); t; t = TREE_CHAIN (t)) - unshare_all_decls (t); -} - /* Go through all virtual stack slots of a function and mark them as not shared. */ static void diff --git a/gcc/expr.c b/gcc/expr.c index ed7d8d77bfe..8c18e66a5c4 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -8139,6 +8139,47 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, return REDUCE_BIT_FIELD (simplify_gen_binary (PLUS, mode, op0, op1)); case MINUS_EXPR: + /* Check if this is a case for multiplication and subtraction. */ + if (TREE_CODE (type) == INTEGER_TYPE + && TREE_CODE (TREE_OPERAND (exp, 1)) == MULT_EXPR) + { + tree subsubexp0, subsubexp1; + enum tree_code code0, code1; + + subexp1 = TREE_OPERAND (exp, 1); + subsubexp0 = TREE_OPERAND (subexp1, 0); + subsubexp1 = TREE_OPERAND (subexp1, 1); + code0 = TREE_CODE (subsubexp0); + code1 = TREE_CODE (subsubexp1); + if (code0 == NOP_EXPR && code1 == NOP_EXPR + && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0))) + < TYPE_PRECISION (TREE_TYPE (subsubexp0))) + && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0))) + == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp1, 0)))) + && (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp0, 0))) + == TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp1, 0))))) + { + tree op0type = TREE_TYPE (TREE_OPERAND (subsubexp0, 0)); + enum machine_mode innermode = TYPE_MODE (op0type); + bool zextend_p = TYPE_UNSIGNED (op0type); + this_optab = zextend_p ? umsub_widen_optab : smsub_widen_optab; + if (mode == GET_MODE_2XWIDER_MODE (innermode) + && (this_optab->handlers[(int) mode].insn_code + != CODE_FOR_nothing)) + { + expand_operands (TREE_OPERAND (subsubexp0, 0), + TREE_OPERAND (subsubexp1, 0), + NULL_RTX, &op0, &op1, EXPAND_NORMAL); + op2 = expand_expr (TREE_OPERAND (exp, 0), subtarget, + VOIDmode, 0); + temp = expand_ternary_op (mode, this_optab, op0, op1, op2, + target, unsignedp); + gcc_assert (temp); + return REDUCE_BIT_FIELD (temp); + } + } + } + /* For initializers, we are allowed to return a MINUS of two symbolic constants. Here we handle all cases when both operands are constant. */ diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 1413b9eb18a..3232c93a09c 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -6008,11 +6008,10 @@ extract_array_ref (tree expr, tree *base, tree *offset) if (extract_array_ref (op0, &inner_base, &dummy1)) { *base = inner_base; - if (dummy1 == NULL_TREE) - *offset = TREE_OPERAND (expr, 1); - else + *offset = fold_convert (sizetype, TREE_OPERAND (expr, 1)); + if (dummy1 != NULL_TREE) *offset = fold_build2 (PLUS_EXPR, sizetype, - dummy1, TREE_OPERAND (expr, 1)); + dummy1, *offset); return true; } } @@ -6030,6 +6029,7 @@ extract_array_ref (tree expr, tree *base, tree *offset) *base = TREE_OPERAND (op0, 0); *offset = fold_build2 (MULT_EXPR, TREE_TYPE (idx), idx, array_ref_element_size (op0)); + *offset = fold_convert (sizetype, *offset); } else { @@ -6879,6 +6879,7 @@ try_move_mult_to_index (tree addr, tree op1) tree ret, pos; tree itype; bool mdim = false; + STRIP_NOPS (op1); /* Canonicalize op1 into a possibly non-constant delta and an INTEGER_CST s. */ @@ -9119,7 +9120,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) expressions. */ if (TREE_CODE (arg0) == ADDR_EXPR) { - tem = try_move_mult_to_index (arg0, arg1); + tem = try_move_mult_to_index (arg0, fold_convert (sizetype, arg1)); if (tem) return fold_convert (type, tem); } diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 361ffcc04be..36137451ec6 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,60 @@ +2007-05-08 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/31630 + * resolve.c (resolve_symbol): Remove the flagging mechanism from the + formal namespace resolution and instead check that the formal + namespace is not the current namespace. + +2007-05-08 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/31692 + * trans-array.c (gfc_conv_array_parameter): Convert full array + references to the result of the procedure enclusing the call. + +2007-05-08 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/29397 + PR fortran/29400 + * decl.c (add_init_expr_to_sym): Expand a scalar initializer + for a parameter array into an array expression with the right + shape. + * array.c (spec_dimen_size): Remove static attribute. + * gfortran.h : Prototype for spec_dimen_size. + +2007-05-07 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR fortran/31399 + * trans-stmt.c (gfc_trans_do): Handle large loop counts. + +2007-05-07 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR fortran/31764 + * simplify.c (gfc_simplify_new_line): NEW_LINE can be simplified + even for non constant arguments. + +2007-05-06 Jerry DeLisle <jvdelisle@gcc.gnu.org> + Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR fortran/31201 + * gfortran.h: Add runtime error codes from libgfortran.h. Define + MAX_UNIT_NUMBER. + * trans.c (gfc_trans_runtime_check): Update the format of runtime error + messages to match library runtime errors. Use call to new library + function runtime_error_at(). + * trans.h: Add prototype for new function gfc_trans_io_runtime_check. + Add declaration for library functions runtime_error_at and + generate_error. + * trans_io.c (gfc_trans_io_runtime_check): New function. + (set_parameter_value): Add error checking for UNIT numbers. + (set_parameter_ref): Initialize the users variable to zero. + (gfc_trans_open): Move setting of unit number to after setting of common + flags so that runtime error trapping can be detected. + (gfc_trans_close): Likewise. (build_filepos): Likewise. + (gfc_trans_inquire): Likewise. (build_dt): Likewise. + * trans-decl.c: Add declarations for runtime_error_at and + generate_error. (gfc_build_builtin_function_decls): Build function + declarations for runtime_error_at and generate_error. + 2007-05-06 Paul Thomas <pault@gcc.gnu.org> PR fortran/31540 diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c index 895bccc14d1..9359624efec 100644 --- a/gcc/fortran/array.c +++ b/gcc/fortran/array.c @@ -1714,7 +1714,7 @@ gfc_get_array_element (gfc_expr *array, int element) /* Get the size of single dimension of an array specification. The array is guaranteed to be one dimensional. */ -static try +try spec_dimen_size (gfc_array_spec *as, int dimen, mpz_t *result) { if (as == NULL) diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index 1dcc53dd067..0071f905611 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -974,7 +974,44 @@ add_init_expr_to_sym (const char *name, gfc_expr **initp, /* Add initializer. Make sure we keep the ranks sane. */ if (sym->attr.dimension && init->rank == 0) - init->rank = sym->as->rank; + { + mpz_t size; + gfc_expr *array; + gfc_constructor *c; + int n; + if (sym->attr.flavor == FL_PARAMETER + && init->expr_type == EXPR_CONSTANT + && spec_size (sym->as, &size) == SUCCESS + && mpz_cmp_si (size, 0) > 0) + { + array = gfc_start_constructor (init->ts.type, init->ts.kind, + &init->where); + + array->value.constructor = c = NULL; + for (n = 0; n < (int)mpz_get_si (size); n++) + { + if (array->value.constructor == NULL) + { + array->value.constructor = c = gfc_get_constructor (); + c->expr = init; + } + else + { + c->next = gfc_get_constructor (); + c = c->next; + c->expr = gfc_copy_expr (init); + } + } + + array->shape = gfc_get_shape (sym->as->rank); + for (n = 0; n < sym->as->rank; n++) + spec_dimen_size (sym->as, n, &array->shape[n]); + + init = array; + mpz_clear (size); + } + init->rank = sym->as->rank; + } sym->value = init; *initp = NULL; diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 039c1ee9c20..2030ec29bb2 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -472,6 +472,39 @@ enum gfc_generic_isym_id }; typedef enum gfc_generic_isym_id gfc_generic_isym_id; +/* Runtime errors. The EOR and EOF errors are required to be negative. + These codes must be kept synchronized with their equivalents in + libgfortran/libgfortran.h . */ + +typedef enum +{ + IOERROR_FIRST = -3, /* Marker for the first error. */ + IOERROR_EOR = -2, + IOERROR_END = -1, + IOERROR_OK = 0, /* Indicates success, must be zero. */ + IOERROR_OS = 5000, /* Operating system error, more info in errno. */ + IOERROR_OPTION_CONFLICT, + IOERROR_BAD_OPTION, + IOERROR_MISSING_OPTION, + IOERROR_ALREADY_OPEN, + IOERROR_BAD_UNIT, + IOERROR_FORMAT, + IOERROR_BAD_ACTION, + IOERROR_ENDFILE, + IOERROR_BAD_US, + IOERROR_READ_VALUE, + IOERROR_READ_OVERFLOW, + IOERROR_INTERNAL, + IOERROR_INTERNAL_UNIT, + IOERROR_ALLOCATION, + IOERROR_DIRECT_EOR, + IOERROR_SHORT_RECORD, + IOERROR_CORRUPT_FILE, + IOERROR_LAST /* Not a real error, the last error # + 1. */ +} +ioerror_codes; + + /************************* Structures *****************************/ /* Used for keeping things in balanced binary trees. */ @@ -2088,6 +2121,7 @@ void gfc_insert_constructor (gfc_expr *, gfc_constructor *); gfc_constructor *gfc_get_constructor (void); tree gfc_conv_array_initializer (tree type, gfc_expr * expr); try spec_size (gfc_array_spec *, mpz_t *); +try spec_dimen_size (gfc_array_spec *, int, mpz_t *); int gfc_is_compile_time_shape (gfc_array_spec *); /* interface.c -- FIXME: some of these should be in symbol.c */ diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 4ec9a921c4a..5c5d40bf6d5 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -6136,9 +6136,7 @@ resolve_fl_parameter (gfc_symbol *sym) static void resolve_symbol (gfc_symbol *sym) { - /* Zero if we are checking a formal namespace. */ - static int formal_ns_flag = 1; - int formal_ns_save, check_constant, mp_flag; + int check_constant, mp_flag; gfc_symtree *symtree; gfc_symtree *this_symtree; gfc_namespace *ns; @@ -6345,18 +6343,9 @@ resolve_symbol (gfc_symbol *sym) formal_arg_flag = 0; - /* Resolve formal namespaces. The symbols in formal namespaces that - themselves are from procedures in formal namespaces will not stand - resolution, except when they are use associated. - TODO: Fix the symbols in formal namespaces so that resolution can - be done unconditionally. */ - if (formal_ns_flag && sym != NULL && sym->formal_ns != NULL) - { - formal_ns_save = formal_ns_flag; - formal_ns_flag = sym->attr.use_assoc ? 1 : 0; - gfc_resolve (sym->formal_ns); - formal_ns_flag = formal_ns_save; - } + /* Resolve formal namespaces. */ + if (sym->formal_ns && sym->formal_ns != gfc_current_ns) + gfc_resolve (sym->formal_ns); /* Check threadprivate restrictions. */ if (sym->attr.threadprivate && !sym->attr.save diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c index 9df2e812c1d..ed62ee34da4 100644 --- a/gcc/fortran/simplify.c +++ b/gcc/fortran/simplify.c @@ -2641,13 +2641,8 @@ gfc_simplify_new_line (gfc_expr *e) { gfc_expr *result; - if (e->expr_type != EXPR_CONSTANT) - return NULL; - result = gfc_constant_result (BT_CHARACTER, e->ts.kind, &e->where); - result->value.character.string = gfc_getmem (2); - result->value.character.length = 1; result->value.character.string[0] = '\n'; result->value.character.string[1] = '\0'; /* For debugger */ diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index 92fd67cccf5..4997673904f 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -4748,14 +4748,25 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77) tree desc; tree tmp; tree stmt; + tree parent = DECL_CONTEXT (current_function_decl); + bool full_array_var, this_array_result; gfc_symbol *sym; stmtblock_t block; + full_array_var = (expr->expr_type == EXPR_VARIABLE + && expr->ref->u.ar.type == AR_FULL); + sym = full_array_var ? expr->symtree->n.sym : NULL; + + /* Is this the result of the enclosing procedure? */ + this_array_result = (full_array_var && sym->attr.flavor == FL_PROCEDURE); + if (this_array_result + && (sym->backend_decl != current_function_decl) + && (sym->backend_decl != parent)) + this_array_result = false; + /* Passing address of the array if it is not pointer or assumed-shape. */ - if (expr->expr_type == EXPR_VARIABLE - && expr->ref->u.ar.type == AR_FULL && g77) + if (full_array_var && g77 && !this_array_result) { - sym = expr->symtree->n.sym; tmp = gfc_get_symbol_decl (sym); if (sym->ts.type == BT_CHARACTER) @@ -4784,8 +4795,25 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77) } } - se->want_pointer = 1; - gfc_conv_expr_descriptor (se, expr, ss); + if (this_array_result) + { + /* Result of the enclosing function. */ + gfc_conv_expr_descriptor (se, expr, ss); + se->expr = build_fold_addr_expr (se->expr); + + if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE + && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr)))) + se->expr = gfc_conv_array_data (build_fold_indirect_ref (se->expr)); + + return; + } + else + { + /* Every other type of array. */ + se->want_pointer = 1; + gfc_conv_expr_descriptor (se, expr, ss); + } + /* Deallocate the allocatable components of structures that are not variable. */ diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index ccf46852761..835e515e628 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -90,6 +90,8 @@ tree gfor_fndecl_stop_numeric; tree gfor_fndecl_stop_string; tree gfor_fndecl_select_string; tree gfor_fndecl_runtime_error; +tree gfor_fndecl_runtime_error_at; +tree gfor_fndecl_generate_error; tree gfor_fndecl_set_fpe; tree gfor_fndecl_set_std; tree gfor_fndecl_set_convert; @@ -2335,6 +2337,18 @@ gfc_build_builtin_function_decls (void) /* The runtime_error function does not return. */ TREE_THIS_VOLATILE (gfor_fndecl_runtime_error) = 1; + gfor_fndecl_runtime_error_at = + gfc_build_library_function_decl (get_identifier (PREFIX("runtime_error_at")), + void_type_node, 2, pchar_type_node, + pchar_type_node); + /* The runtime_error_at function does not return. */ + TREE_THIS_VOLATILE (gfor_fndecl_runtime_error_at) = 1; + + gfor_fndecl_generate_error = + gfc_build_library_function_decl (get_identifier (PREFIX("generate_error")), + void_type_node, 3, pvoid_type_node, + gfc_c_int_type_node, pchar_type_node); + gfor_fndecl_set_fpe = gfc_build_library_function_decl (get_identifier (PREFIX("set_fpe")), void_type_node, 1, gfc_c_int_type_node); diff --git a/gcc/fortran/trans-io.c b/gcc/fortran/trans-io.c index 856938c9fdd..4b87bcba241 100644 --- a/gcc/fortran/trans-io.c +++ b/gcc/fortran/trans-io.c @@ -212,6 +212,62 @@ gfc_build_st_parameter (enum ioparam_type ptype, tree *types) st_parameter[ptype].type = t; } + +/* Build code to test an error condition and call generate_error if needed. + Note: This builds calls to generate_error in the runtime library function. + The function generate_error is dependent on certain parameters in the + st_parameter_common flags to be set. (See libgfortran/runtime/error.c) + Therefore, the code to set these flags must be generated before + this function is used. */ + +void +gfc_trans_io_runtime_check (tree cond, tree var, int error_code, + const char * msgid, stmtblock_t * pblock) +{ + stmtblock_t block; + tree body; + tree tmp; + tree arg1, arg2, arg3; + char *message; + + if (integer_zerop (cond)) + return; + + /* The code to generate the error. */ + gfc_start_block (&block); + + arg1 = build_fold_addr_expr (var); + + arg2 = build_int_cst (integer_type_node, error_code), + + asprintf (&message, "%s", _(msgid)); + arg3 = gfc_build_addr_expr (pchar_type_node, gfc_build_cstring_const(message)); + gfc_free(message); + + tmp = build_call_expr (gfor_fndecl_generate_error, 3, arg1, arg2, arg3); + + gfc_add_expr_to_block (&block, tmp); + + body = gfc_finish_block (&block); + + if (integer_onep (cond)) + { + gfc_add_expr_to_block (pblock, body); + } + else + { + /* Tell the compiler that this isn't likely. */ + cond = fold_convert (long_integer_type_node, cond); + tmp = build_int_cst (long_integer_type_node, 0); + cond = build_call_expr (built_in_decls[BUILT_IN_EXPECT], 2, cond, tmp); + cond = fold_convert (boolean_type_node, cond); + + tmp = build3_v (COND_EXPR, cond, body, build_empty_stmt ()); + gfc_add_expr_to_block (pblock, tmp); + } +} + + /* Create function decls for IO library functions. */ void @@ -396,16 +452,49 @@ set_parameter_value (stmtblock_t *block, tree var, enum iofield type, gfc_se se; tree tmp; gfc_st_parameter_field *p = &st_parameter_field[type]; + tree dest_type = TREE_TYPE (p->field); gfc_init_se (&se, NULL); - gfc_conv_expr_type (&se, e, TREE_TYPE (p->field)); + gfc_conv_expr_val (&se, e); + + /* If we're storing a UNIT number, we need to check it first. */ + if (type == IOPARM_common_unit && e->ts.kind != 4) + { + tree cond, max; + ioerror_codes bad_unit; + int i; + + bad_unit = IOERROR_BAD_UNIT; + + /* Don't evaluate the UNIT number multiple times. */ + se.expr = gfc_evaluate_now (se.expr, &se.pre); + + /* UNIT numbers should be nonnegative. */ + cond = fold_build2 (LT_EXPR, boolean_type_node, se.expr, + build_int_cst (TREE_TYPE (se.expr),0)); + gfc_trans_io_runtime_check (cond, var, bad_unit, + "Negative unit number in I/O statement", + &se.pre); + + /* UNIT numbers should be less than the max. */ + i = gfc_validate_kind (BT_INTEGER, 4, false); + max = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, 4); + cond = fold_build2 (GT_EXPR, boolean_type_node, se.expr, + fold_convert (TREE_TYPE (se.expr), max)); + gfc_trans_io_runtime_check (cond, var, bad_unit, + "Unit number in I/O statement too large", + &se.pre); + + } + + se.expr = convert (dest_type, se.expr); gfc_add_block_to_block (block, &se.pre); if (p->param_type == IOPARM_ptype_common) var = build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type, var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE); - tmp = build3 (COMPONENT_REF, TREE_TYPE (p->field), var, p->field, - NULL_TREE); + + tmp = build3 (COMPONENT_REF, dest_type, var, p->field, NULL_TREE); gfc_add_modify_expr (block, tmp, se.expr); return p->mask; } @@ -430,20 +519,42 @@ set_parameter_ref (stmtblock_t *block, stmtblock_t *postblock, if (TYPE_MODE (TREE_TYPE (se.expr)) == TYPE_MODE (TREE_TYPE (TREE_TYPE (p->field)))) - addr = convert (TREE_TYPE (p->field), - build_fold_addr_expr (se.expr)); + { + addr = convert (TREE_TYPE (p->field), build_fold_addr_expr (se.expr)); + + /* If this is for the iostat variable initialize the + user variable to IOERROR_OK which is zero. */ + if (type == IOPARM_common_iostat) + { + ioerror_codes ok; + ok = IOERROR_OK; + gfc_add_modify_expr (block, se.expr, + build_int_cst (TREE_TYPE (se.expr), ok)); + } + } else { /* The type used by the library has different size - from the type of the variable supplied by the user. - Need to use a temporary. */ - tree tmpvar - = gfc_create_var (TREE_TYPE (TREE_TYPE (p->field)), - st_parameter_field[type].name); + from the type of the variable supplied by the user. + Need to use a temporary. */ + tree tmpvar = gfc_create_var (TREE_TYPE (TREE_TYPE (p->field)), + st_parameter_field[type].name); + + /* If this is for the iostat variable, initialize the + user variable to IOERROR_OK which is zero. */ + if (type == IOPARM_common_iostat) + { + ioerror_codes ok; + ok = IOERROR_OK; + gfc_add_modify_expr (block, tmpvar, + build_int_cst (TREE_TYPE (tmpvar), ok)); + } + addr = build_fold_addr_expr (tmpvar); + /* After the I/O operation, we set the variable from the temporary. */ tmp = convert (TREE_TYPE (se.expr), tmpvar); gfc_add_modify_expr (postblock, se.expr, tmp); - } + } if (p->param_type == IOPARM_ptype_common) var = build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type, @@ -776,10 +887,16 @@ gfc_trans_open (gfc_code * code) set_error_locus (&block, var, &code->loc); p = code->ext.open; - if (p->unit) - set_parameter_value (&block, var, IOPARM_common_unit, p->unit); - else - set_parameter_const (&block, var, IOPARM_common_unit, 0); + if (p->iomsg) + mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg, + p->iomsg); + + if (p->iostat) + mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat, + p->iostat); + + if (p->err) + mask |= IOPARM_common_err; if (p->file) mask |= set_string (&block, &post_block, var, IOPARM_open_file, p->file); @@ -817,23 +934,17 @@ gfc_trans_open (gfc_code * code) if (p->pad) mask |= set_string (&block, &post_block, var, IOPARM_open_pad, p->pad); - if (p->iomsg) - mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg, - p->iomsg); - - if (p->iostat) - mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat, - p->iostat); - - if (p->err) - mask |= IOPARM_common_err; - if (p->convert) mask |= set_string (&block, &post_block, var, IOPARM_open_convert, p->convert); set_parameter_const (&block, var, IOPARM_common_flags, mask); + if (p->unit) + set_parameter_value (&block, var, IOPARM_common_unit, p->unit); + else + set_parameter_const (&block, var, IOPARM_common_unit, 0); + tmp = build_fold_addr_expr (var); tmp = build_call_expr (iocall[IOCALL_OPEN], 1, tmp); gfc_add_expr_to_block (&block, tmp); @@ -864,15 +975,6 @@ gfc_trans_close (gfc_code * code) set_error_locus (&block, var, &code->loc); p = code->ext.close; - if (p->unit) - set_parameter_value (&block, var, IOPARM_common_unit, p->unit); - else - set_parameter_const (&block, var, IOPARM_common_unit, 0); - - if (p->status) - mask |= set_string (&block, &post_block, var, IOPARM_close_status, - p->status); - if (p->iomsg) mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg, p->iomsg); @@ -884,8 +986,17 @@ gfc_trans_close (gfc_code * code) if (p->err) mask |= IOPARM_common_err; + if (p->status) + mask |= set_string (&block, &post_block, var, IOPARM_close_status, + p->status); + set_parameter_const (&block, var, IOPARM_common_flags, mask); + if (p->unit) + set_parameter_value (&block, var, IOPARM_common_unit, p->unit); + else + set_parameter_const (&block, var, IOPARM_common_unit, 0); + tmp = build_fold_addr_expr (var); tmp = build_call_expr (iocall[IOCALL_CLOSE], 1, tmp); gfc_add_expr_to_block (&block, tmp); @@ -918,11 +1029,6 @@ build_filepos (tree function, gfc_code * code) set_error_locus (&block, var, &code->loc); - if (p->unit) - set_parameter_value (&block, var, IOPARM_common_unit, p->unit); - else - set_parameter_const (&block, var, IOPARM_common_unit, 0); - if (p->iomsg) mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg, p->iomsg); @@ -936,6 +1042,11 @@ build_filepos (tree function, gfc_code * code) set_parameter_const (&block, var, IOPARM_common_flags, mask); + if (p->unit) + set_parameter_value (&block, var, IOPARM_common_unit, p->unit); + else + set_parameter_const (&block, var, IOPARM_common_unit, 0); + tmp = build_fold_addr_expr (var); tmp = build_call_expr (function, 1, tmp); gfc_add_expr_to_block (&block, tmp); @@ -1003,19 +1114,6 @@ gfc_trans_inquire (gfc_code * code) set_error_locus (&block, var, &code->loc); p = code->ext.inquire; - /* Sanity check. */ - if (p->unit && p->file) - gfc_error ("INQUIRE statement at %L cannot contain both FILE and UNIT specifiers", &code->loc); - - if (p->unit) - set_parameter_value (&block, var, IOPARM_common_unit, p->unit); - else - set_parameter_const (&block, var, IOPARM_common_unit, 0); - - if (p->file) - mask |= set_string (&block, &post_block, var, IOPARM_inquire_file, - p->file); - if (p->iomsg) mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg, p->iomsg); @@ -1024,6 +1122,17 @@ gfc_trans_inquire (gfc_code * code) mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat, p->iostat); + if (p->err) + mask |= IOPARM_common_err; + + /* Sanity check. */ + if (p->unit && p->file) + gfc_error ("INQUIRE statement at %L cannot contain both FILE and UNIT specifiers", &code->loc); + + if (p->file) + mask |= set_string (&block, &post_block, var, IOPARM_inquire_file, + p->file); + if (p->exist) mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_exist, p->exist); @@ -1108,9 +1217,6 @@ gfc_trans_inquire (gfc_code * code) mask |= set_string (&block, &post_block, var, IOPARM_inquire_pad, p->pad); - if (p->err) - mask |= IOPARM_common_err; - if (p->convert) mask |= set_string (&block, &post_block, var, IOPARM_inquire_convert, p->convert); @@ -1121,6 +1227,11 @@ gfc_trans_inquire (gfc_code * code) set_parameter_const (&block, var, IOPARM_common_flags, mask); + if (p->unit) + set_parameter_value (&block, var, IOPARM_common_unit, p->unit); + else + set_parameter_const (&block, var, IOPARM_common_unit, 0); + tmp = build_fold_addr_expr (var); tmp = build_call_expr (iocall[IOCALL_INQUIRE], 1, tmp); gfc_add_expr_to_block (&block, tmp); @@ -1419,14 +1530,29 @@ build_dt (tree function, gfc_code * code) var, dt->io_unit); set_parameter_const (&block, var, IOPARM_common_unit, 0); } - else - set_parameter_value (&block, var, IOPARM_common_unit, dt->io_unit); } else set_parameter_const (&block, var, IOPARM_common_unit, 0); if (dt) { + if (dt->iomsg) + mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg, + dt->iomsg); + + if (dt->iostat) + mask |= set_parameter_ref (&block, &post_end_block, var, + IOPARM_common_iostat, dt->iostat); + + if (dt->err) + mask |= IOPARM_common_err; + + if (dt->eor) + mask |= IOPARM_common_eor; + + if (dt->end) + mask |= IOPARM_common_end; + if (dt->rec) mask |= set_parameter_value (&block, var, IOPARM_dt_rec, dt->rec); @@ -1447,27 +1573,10 @@ build_dt (tree function, gfc_code * code) dt->format_label->format); } - if (dt->iomsg) - mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg, - dt->iomsg); - - if (dt->iostat) - mask |= set_parameter_ref (&block, &post_end_block, var, - IOPARM_common_iostat, dt->iostat); - if (dt->size) mask |= set_parameter_ref (&block, &post_end_block, var, IOPARM_dt_size, dt->size); - if (dt->err) - mask |= IOPARM_common_err; - - if (dt->eor) - mask |= IOPARM_common_eor; - - if (dt->end) - mask |= IOPARM_common_end; - if (dt->namelist) { if (dt->format_expr || dt->format_label) @@ -1491,6 +1600,9 @@ build_dt (tree function, gfc_code * code) } else set_parameter_const (&block, var, IOPARM_common_flags, mask); + + if (dt->io_unit && dt->io_unit->ts.type == BT_INTEGER) + set_parameter_value (&block, var, IOPARM_common_unit, dt->io_unit); } else set_parameter_const (&block, var, IOPARM_common_flags, mask); diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c index cdc8dc6c669..92462cbad75 100644 --- a/gcc/fortran/trans-stmt.c +++ b/gcc/fortran/trans-stmt.c @@ -809,22 +809,22 @@ gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar, to: [evaluate loop bounds and step] - count = (to + step - from) / step; + empty = (step > 0 ? to < from : to > from); + countm1 = (to - from) / step; dovar = from; + if (empty) goto exit_label; for (;;) { body; cycle_label: dovar += step - count--; - if (count <=0) goto exit_label; + countm1--; + if (countm1 ==0) goto exit_label; } exit_label: - TODO: Large loop counts - The code above assumes the loop count fits into a signed integer kind, - i.e. Does not work for loop counts > 2^31 for integer(kind=4) variables - We must support the full range. */ + countm1 is an unsigned integer. It is equal to the loop count minus one, + because the loop count itself can overflow. */ tree gfc_trans_do (gfc_code * code) @@ -834,13 +834,15 @@ gfc_trans_do (gfc_code * code) tree from; tree to; tree step; - tree count; - tree count_one; + tree empty; + tree countm1; tree type; + tree utype; tree cond; tree cycle_label; tree exit_label; tree tmp; + tree pos_step; stmtblock_t block; stmtblock_t body; @@ -874,48 +876,59 @@ gfc_trans_do (gfc_code * code) || tree_int_cst_equal (step, integer_minus_one_node))) return gfc_trans_simple_do (code, &block, dovar, from, to, step); - /* Initialize loop count. This code is executed before we enter the - loop body. We generate: count = (to + step - from) / step. */ + /* We need a special check for empty loops: + empty = (step > 0 ? to < from : to > from); */ + pos_step = fold_build2 (GT_EXPR, boolean_type_node, step, + fold_convert (type, integer_zero_node)); + empty = fold_build3 (COND_EXPR, boolean_type_node, pos_step, + fold_build2 (LT_EXPR, boolean_type_node, to, from), + fold_build2 (GT_EXPR, boolean_type_node, to, from)); - tmp = fold_build2 (MINUS_EXPR, type, step, from); - tmp = fold_build2 (PLUS_EXPR, type, to, tmp); + /* Initialize loop count. This code is executed before we enter the + loop body. We generate: countm1 = abs(to - from) / abs(step). */ if (TREE_CODE (type) == INTEGER_TYPE) { - tmp = fold_build2 (TRUNC_DIV_EXPR, type, tmp, step); - count = gfc_create_var (type, "count"); + tree ustep; + + utype = gfc_unsigned_type (type); + + /* tmp = abs(to - from) / abs(step) */ + ustep = fold_convert (utype, fold_build1 (ABS_EXPR, type, step)); + tmp = fold_build3 (COND_EXPR, type, pos_step, + fold_build2 (MINUS_EXPR, type, to, from), + fold_build2 (MINUS_EXPR, type, from, to)); + tmp = fold_build2 (TRUNC_DIV_EXPR, utype, fold_convert (utype, tmp), + ustep); } else { /* TODO: We could use the same width as the real type. This would probably cause more problems that it solves when we implement "long double" types. */ + utype = gfc_unsigned_type (gfc_array_index_type); + tmp = fold_build2 (MINUS_EXPR, type, to, from); tmp = fold_build2 (RDIV_EXPR, type, tmp, step); - tmp = fold_build1 (FIX_TRUNC_EXPR, gfc_array_index_type, tmp); - count = gfc_create_var (gfc_array_index_type, "count"); + tmp = fold_build1 (FIX_TRUNC_EXPR, utype, tmp); } - gfc_add_modify_expr (&block, count, tmp); + countm1 = gfc_create_var (utype, "countm1"); + gfc_add_modify_expr (&block, countm1, tmp); - count_one = build_int_cst (TREE_TYPE (count), 1); + /* Cycle and exit statements are implemented with gotos. */ + cycle_label = gfc_build_label_decl (NULL_TREE); + exit_label = gfc_build_label_decl (NULL_TREE); + TREE_USED (exit_label) = 1; /* Initialize the DO variable: dovar = from. */ gfc_add_modify_expr (&block, dovar, from); + /* If the loop is empty, go directly to the exit label. */ + tmp = fold_build3 (COND_EXPR, void_type_node, empty, + build1_v (GOTO_EXPR, exit_label), build_empty_stmt ()); + gfc_add_expr_to_block (&block, tmp); + /* Loop body. */ gfc_start_block (&body); - /* Cycle and exit statements are implemented with gotos. */ - cycle_label = gfc_build_label_decl (NULL_TREE); - exit_label = gfc_build_label_decl (NULL_TREE); - - /* Start with the loop condition. Loop until count <= 0. */ - cond = fold_build2 (LE_EXPR, boolean_type_node, count, - build_int_cst (TREE_TYPE (count), 0)); - tmp = build1_v (GOTO_EXPR, exit_label); - TREE_USED (exit_label) = 1; - tmp = fold_build3 (COND_EXPR, void_type_node, - cond, tmp, build_empty_stmt ()); - gfc_add_expr_to_block (&body, tmp); - /* Put these labels where they can be found later. We put the labels in a TREE_LIST node (because TREE_CHAIN is already used). cycle_label goes in TREE_PURPOSE (backend_decl), exit @@ -934,13 +947,21 @@ gfc_trans_do (gfc_code * code) gfc_add_expr_to_block (&body, tmp); } + /* End with the loop condition. Loop until countm1 == 0. */ + cond = fold_build2 (EQ_EXPR, boolean_type_node, countm1, + build_int_cst (utype, 0)); + tmp = build1_v (GOTO_EXPR, exit_label); + tmp = fold_build3 (COND_EXPR, void_type_node, + cond, tmp, build_empty_stmt ()); + gfc_add_expr_to_block (&body, tmp); + /* Increment the loop variable. */ tmp = build2 (PLUS_EXPR, type, dovar, step); gfc_add_modify_expr (&body, dovar, tmp); /* Decrement the loop count. */ - tmp = build2 (MINUS_EXPR, TREE_TYPE (count), count, count_one); - gfc_add_modify_expr (&body, count, tmp); + tmp = build2 (MINUS_EXPR, utype, countm1, build_int_cst (utype, 1)); + gfc_add_modify_expr (&body, countm1, tmp); /* End of loop body. */ tmp = gfc_finish_block (&body); diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c index 64dbb73a59e..5e717e4cbcf 100644 --- a/gcc/fortran/trans.c +++ b/gcc/fortran/trans.c @@ -318,8 +318,8 @@ gfc_trans_runtime_check (tree cond, const char * msgid, stmtblock_t * pblock, stmtblock_t block; tree body; tree tmp; - tree arg; - char * message; + tree arg, arg2; + char *message; int line; if (integer_zerop (cond)) @@ -335,17 +335,21 @@ gfc_trans_runtime_check (tree cond, const char * msgid, stmtblock_t * pblock, #else line = where->lb->linenum; #endif - asprintf (&message, "%s (in file '%s', at line %d)", _(msgid), - where->lb->file->filename, line); + asprintf (&message, "At line %d of file %s", line, + where->lb->file->filename); } else - asprintf (&message, "%s (in file '%s', around line %d)", _(msgid), + asprintf (&message, "In file '%s', around line %d", gfc_source_file, input_line + 1); arg = gfc_build_addr_expr (pchar_type_node, gfc_build_cstring_const(message)); gfc_free(message); + + asprintf (&message, "%s", _(msgid)); + arg2 = gfc_build_addr_expr (pchar_type_node, gfc_build_cstring_const(message)); + gfc_free(message); - tmp = build_call_expr (gfor_fndecl_runtime_error, 1, arg); + tmp = build_call_expr (gfor_fndecl_runtime_error_at, 2, arg, arg2); gfc_add_expr_to_block (&block, tmp); body = gfc_finish_block (&block); diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index 7ca396608bd..731045a2769 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -448,6 +448,7 @@ tree gfc_trans_pointer_assignment (gfc_expr *, gfc_expr *); /* Initialize function decls for library functions. */ void gfc_build_intrinsic_lib_fndecls (void); /* Create function decls for IO library functions. */ +void gfc_trans_io_runtime_check (tree, tree, int, const char *, stmtblock_t *); void gfc_build_io_library_fndecls (void); /* Build a function decl for a library function. */ tree gfc_build_library_function_decl (tree, tree, int, ...); @@ -487,6 +488,8 @@ extern GTY(()) tree gfor_fndecl_stop_numeric; extern GTY(()) tree gfor_fndecl_stop_string; extern GTY(()) tree gfor_fndecl_select_string; extern GTY(()) tree gfor_fndecl_runtime_error; +extern GTY(()) tree gfor_fndecl_runtime_error_at; +extern GTY(()) tree gfor_fndecl_generate_error; extern GTY(()) tree gfor_fndecl_set_fpe; extern GTY(()) tree gfor_fndecl_set_std; extern GTY(()) tree gfor_fndecl_ttynam; diff --git a/gcc/gcc.c b/gcc/gcc.c index 10468026939..5ed41bd66ff 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -127,6 +127,9 @@ static const char dir_separator_str[] = { DIR_SEPARATOR, 0 }; /* Flag set by cppspec.c to 1. */ int is_cpp_driver; +/* Flag set to non-zero if an @file argument has been supplied to gcc. */ +static bool at_file_supplied; + /* Flag saying to pass the greatest exit code returned by a sub-process to the calling program. */ static int pass_exit_codes; @@ -5009,9 +5012,63 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) int max = n_infiles; max += lang_specific_extra_outfiles; - for (i = 0; i < max; i++) - if (outfiles[i]) - store_arg (outfiles[i], 0, 0); + if (HAVE_GNU_LD && at_file_supplied) + { + /* We are going to expand `%o' to `@FILE', where FILE + is a newly-created temporary filename. The filenames + that would usually be expanded in place of %o will be + written to the temporary file. */ + + char *temp_file = make_temp_file (""); + char *at_argument; + char **argv; + int n_files, j, status; + FILE *f; + + at_argument = concat ("@", temp_file, NULL); + store_arg (at_argument, 0, 0); + + /* Convert OUTFILES into a form suitable for writeargv. */ + + /* Determine how many are non-NULL. */ + for (n_files = 0, i = 0; i < max; i++) + n_files += outfiles[i] != NULL; + + argv = alloca (sizeof (char *) * (n_files + 1)); + + /* Copy the strings over. */ + for (i = 0, j = 0; i < max; i++) + if (outfiles[i]) + { + argv[j] = (char *) outfiles[i]; + j++; + } + argv[j] = NULL; + + f = fopen (temp_file, "w"); + + if (f == NULL) + fatal ("could not open temporary response file %s", + temp_file); + + status = writeargv (argv, f); + + if (status) + fatal ("could not write to temporary response file %s", + temp_file); + + status = fclose (f); + + if (EOF == status) + fatal ("could not close temporary response file %s", + temp_file); + + record_temp_file (temp_file, !save_temps_flag, !save_temps_flag); + } + else + for (i = 0; i < max; i++) + if (outfiles[i]) + store_arg (outfiles[i], 0, 0); break; } @@ -6093,6 +6150,7 @@ main (int argc, char **argv) char *specs_file; const char *p; struct user_specs *uptr; + char **old_argv = argv; p = argv[0] + strlen (argv[0]); while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1])) @@ -6103,6 +6161,10 @@ main (int argc, char **argv) expandargv (&argc, &argv); + /* Determine if any expansions were made. */ + if (argv != old_argv) + at_file_supplied = true; + prune_options (&argc, &argv); #ifdef GCC_DRIVER_HOST_INITIALIZATION diff --git a/gcc/genopinit.c b/gcc/genopinit.c index 992981aa8c0..a137750f948 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -87,6 +87,8 @@ static const char * const optabs[] = "usmul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(usmul$a$b3$)$N", "smadd_widen_optab->handlers[$B].insn_code = CODE_FOR_$(madd$a$b4$)$N", "umadd_widen_optab->handlers[$B].insn_code = CODE_FOR_$(umadd$a$b4$)$N", + "smsub_widen_optab->handlers[$B].insn_code = CODE_FOR_$(msub$a$b4$)$N", + "umsub_widen_optab->handlers[$B].insn_code = CODE_FOR_$(umsub$a$b4$)$N", "sdiv_optab->handlers[$A].insn_code = CODE_FOR_$(div$a3$)", "sdivv_optab->handlers[$A].insn_code = CODE_FOR_$(div$V$I$a3$)", "udiv_optab->handlers[$A].insn_code = CODE_FOR_$(udiv$I$a3$)", diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 9f1b71bc47b..326d0f3e852 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -5895,6 +5895,8 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, /* Convert (void *)&a + 4 into (void *)&a[1]. */ if (TREE_CODE (TREE_OPERAND (*expr_p, 0)) == NOP_EXPR && TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST + && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p, + 0),0))) && (tmp = maybe_fold_offset_to_reference (TREE_OPERAND (TREE_OPERAND (*expr_p, 0), 0), TREE_OPERAND (*expr_p, 1), diff --git a/gcc/ipa-type-escape.c b/gcc/ipa-type-escape.c index 921284db667..1619c5e47c0 100644 --- a/gcc/ipa-type-escape.c +++ b/gcc/ipa-type-escape.c @@ -196,8 +196,9 @@ compare_type_brand (splay_tree_key sk1, splay_tree_key sk2) /* This is a trivial algorithm for removing duplicate types. This would not work for any language that used structural equivalence as the basis of its type system. */ -/* Return either TYPE if this is first time TYPE has been seen an - compatible TYPE that has already been processed. */ +/* Return TYPE if no type compatible with TYPE has been seen so far, + otherwise return a type compatible with TYPE that has already been + processed. */ static tree discover_unique_type (tree type) @@ -1662,7 +1663,7 @@ ipa_init (void) /* Check out the rhs of a static or global initialization VNODE to see if any of them contain addressof operations. Note that some of - these variables may not even be referenced in the code in this + these variables may not even be referenced in the code in this compilation unit but their right hand sides may contain references to variables defined within this unit. */ diff --git a/gcc/optabs.c b/gcc/optabs.c index 55e5a7b5ced..5ec2fbee8d2 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -5443,6 +5443,8 @@ init_optabs (void) usmul_widen_optab = init_optab (UNKNOWN); smadd_widen_optab = init_optab (UNKNOWN); umadd_widen_optab = init_optab (UNKNOWN); + smsub_widen_optab = init_optab (UNKNOWN); + umsub_widen_optab = init_optab (UNKNOWN); sdiv_optab = init_optab (DIV); sdivv_optab = init_optabv (DIV); sdivmod_optab = init_optab (UNKNOWN); diff --git a/gcc/optabs.h b/gcc/optabs.h index e5bbef89e4c..60dcc159729 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -92,6 +92,12 @@ enum optab_index /* Unigned multiply and add with the result and addend one machine mode wider than the multiplicand and multiplier. */ OTI_umadd_widen, + /* Signed multiply and subtract the result and minuend one machine mode + wider than the multiplicand and multiplier. */ + OTI_smsub_widen, + /* Unigned multiply and subtract the result and minuend one machine mode + wider than the multiplicand and multiplier. */ + OTI_umsub_widen, /* Signed divide */ OTI_sdiv, @@ -317,6 +323,8 @@ extern GTY(()) optab optab_table[OTI_MAX]; #define usmul_widen_optab (optab_table[OTI_usmul_widen]) #define smadd_widen_optab (optab_table[OTI_smadd_widen]) #define umadd_widen_optab (optab_table[OTI_umadd_widen]) +#define smsub_widen_optab (optab_table[OTI_smsub_widen]) +#define umsub_widen_optab (optab_table[OTI_umsub_widen]) #define sdiv_optab (optab_table[OTI_sdiv]) #define smulv_optab (optab_table[OTI_smulv]) #define sdivv_optab (optab_table[OTI_sdivv]) diff --git a/gcc/reload.c b/gcc/reload.c index 8ed2f4b3880..bf220ef6bc0 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -1180,7 +1180,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, /* If IN appears in OUT, we can't share any input-only reload for IN. */ if (in != 0 && out != 0 && MEM_P (out) - && (REG_P (in) || MEM_P (in)) + && (REG_P (in) || MEM_P (in) || GET_CODE (in) == PLUS) && reg_overlap_mentioned_for_reload_p (in, XEXP (out, 0))) dont_share = 1; @@ -6516,7 +6516,8 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in) if (REG_P (in)) return 0; else if (GET_CODE (in) == PLUS) - return (reg_overlap_mentioned_for_reload_p (x, XEXP (in, 0)) + return (rtx_equal_p (x, in) + || reg_overlap_mentioned_for_reload_p (x, XEXP (in, 0)) || reg_overlap_mentioned_for_reload_p (x, XEXP (in, 1))); else return (reg_overlap_mentioned_for_reload_p (XEXP (x, 0), in) || reg_overlap_mentioned_for_reload_p (XEXP (x, 1), in)); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2b74f7cc8f8..c0e3d1e2327 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,10 +1,114 @@ +2007-05-10 Zdenek Dvorak <dvorakz@suse.cz> + + PR tree-optimization/31885 + * gcc.dg/tree-ssa/loop-29.c: New test. + +2007-05-10 Dominique d'Humières <dominiq@lps.ens.fr> + + * assumed_dummy_1.f90: Fix dg directive. + * char_initialiser_actual.f90: Likewise. + * nested_modules_2.f90: Likewise. + * shift-alloc.f90: Likewise. + +2007-05-10 Andreas Krebbel <krebbel1@de.ibm.com> + + * gcc.dg/20070507-1.c: Disable for non-pic targets. + +2007-05-09 Jerry DeLisle <jvdelisle@gcc.gnu.org> + + PR libfortran/31880 + * gfortran.dg/unf_read_corrupted_2.f90: New test. + +2007-05-09 Mike Stump <mrs@apple.com> + + * g++.dg/other/first-global.C: Add -fpie for darwin. + * g++.dg/parse/attr-externally-visible-1.C: Likewise. + +2007-05-09 Andreas Krebbel <krebbel1@de.ibm.com> + + * gcc.dg/20070507-1.c: New testcase. + +2007-05-08 Chao-ying Fu <fu@mips.com> + + * gcc.target/mips/msub-1.c, gcc.target/mips/msub-2.c, + * gcc.target/mips/msub-3.c, gcc.target/mips/msub-4.c, + * gcc.target/mips/msubu-1.c, gcc.target/mips/msubu-2.c, + * gcc.target/mips/msubu-3.c, gcc.target/mips/msubu-4.c: New tests. + +2007-05-08 Simon Martin <simartin@users.sourceforge.net> + + PR 31847 + * gcc.dg/pr31847.c: New test. + +2007-05-08 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/31692 + * gfortran.dg/actual_array_result_1.f90: New test. + +2007-05-08 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/29397 + * gfortran.dg/parameter_array_init_1.f90: New test. + + PR fortran/29400 + * gfortran.dg/parameter_array_init_2.f90: New test. + +2007-05-08 Uros Bizjak <ubizjak@gmail.com> + + PR target/31854 + * gcc.target/i386/pr31854.c: New test. + +2007-05-07 Janis Johnson <janis187@us.ibm.com> + + * gcc.dg/pch/pch.exp: XFAIL largefile on Solaris 10 x86. + +2007-05-07 Mike Stump <mrs@apple.com> + + * g++.old-deja/g++.mike/empty.C: Add. + +2007-05-07 Eric Christopher <echristo@apple.com> + + * gcc.dg/invalid-call-1.c: Fix options for 32-bit x86. + +2007-05-07 Uros Bizjak <ubizjak@gmail.com> + + * gcc.dg/dfp/convert-bfp-fold.c: Remove extra assignment to 'sf' + variable. Rearrange conversions from binary float to decimal float. + +2007-05-07 Mark Mitchell <mark@codesourcery.com> + + * gcc.dg/special/gcsec-1.c: Don't link statically on Solaris 10 + x86. + +2007-05-07 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/opt1.ad[sb]: New testcase. + +2007-05-07 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR fortran/31399 + * gfortran.dg/do_3.F90: New test. + +2007-05-07 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR fortran/31764 + * gfortran.dg/new_line.f90: Add new checks. + +2007-05-06 Jerry DeLisle <jvdelisle@gcc.gnu.org> + + PR fortran/31201 + * gfortran.dg/large_unit_1.f90: New. + * gfortran.dg/large_unit_2.f90: New. + * gfortran.dg/iostat_4.f90: New + * gfortran.dg/bounds_check_fail_1.f90: Updated. + 2007-05-06 Paul Thomas <pault@gcc.gnu.org> PR fortran/31540 * gfortran.dg/char_result_4.f90: New test. 2007-06-05 Revital Eres <eres@il.ibm.com> - + PR 30957 * gcc.dg/pr30957-1.c: New test. @@ -32,9 +136,9 @@ * gfortran.dg/fseek.f90: New test. 2007-05-04 Bob Wilson <bob.wilson@acm.org> - + * g++.old-deja/g++.pt/static11.C: Remove xtensa-*-elf* xfail. - + 2007-05-04 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> PR libfortran/31210 @@ -67,7 +171,7 @@ 2007-05-03 Dorit Nuzman <dorit@il.ibm.com> PR tree-optimization/31699 - * lib/target-supports.exp (check_effective_target_vect_intfloat_cvt): + * lib/target-supports.exp (check_effective_target_vect_intfloat_cvt): New. (check_effective_target_vect_floatint_cvt): New. * gcc.dg/vect/vect-floatint-conversion-1.c: Use new keyword instead @@ -86,8 +190,8 @@ 2007-05-02 Seongbae Park <seongbae.park@gmail.com> PR C++/31663 - * g++.dg/warn/anonymous-namespace-2.C: New. - * g++.dg/warn/anonymous-namespace-2.h: New. + * g++.dg/warn/anonymous-namespace-2.C: New. + * g++.dg/warn/anonymous-namespace-2.h: New. 2007-05-02 Paul Brook <paul@codesourcery.com> diff --git a/gcc/testsuite/g++.dg/abi/forced.C b/gcc/testsuite/g++.dg/abi/forced.C new file mode 100644 index 00000000000..7a9c35964f7 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/forced.C @@ -0,0 +1,25 @@ +// This test only applies to glibc (NPTL) targets. +// { dg-do run { target *-*-linux* } } +// { dg-options "-pthread" } + +#include <pthread.h> +#include <cxxabi.h> +extern "C" int printf (const char *, ...); + +int main() +{ + try + { + pthread_exit (0); + } + catch (abi::__forced_unwind &) + { + printf ("caught forced unwind\n"); + throw; + } + catch (...) + { + printf ("caught ...\n"); + return 1; + } +} diff --git a/gcc/testsuite/g++.dg/other/first-global.C b/gcc/testsuite/g++.dg/other/first-global.C index b50f3266b5d..81e7a96e2e0 100644 --- a/gcc/testsuite/g++.dg/other/first-global.C +++ b/gcc/testsuite/g++.dg/other/first-global.C @@ -1,4 +1,6 @@ /* { dg-do compile } */ +/* { dg-options "-fpie" { target *-*-darwin* } } */ /* { dg-final { scan-assembler "_GLOBAL__I_foobar" } } */ + struct foo { foo (); }; foo foobar; diff --git a/gcc/testsuite/g++.dg/parse/attr-externally-visible-1.C b/gcc/testsuite/g++.dg/parse/attr-externally-visible-1.C index 9016bc4225a..98fec2b4a98 100644 --- a/gcc/testsuite/g++.dg/parse/attr-externally-visible-1.C +++ b/gcc/testsuite/g++.dg/parse/attr-externally-visible-1.C @@ -1,5 +1,6 @@ // { dg-do compile } // { dg-options "-O3 -fwhole-program" } +/* { dg-options "-O3 -fwhole-program -fpie" { target *-*-darwin* } } */ // { dg-final { scan-assembler "foo1" } } // { dg-final { scan-assembler "foo2" } } // { dg-final { scan-assembler "foo3" } } diff --git a/gcc/testsuite/g++.old-deja/g++.mike/empty.C b/gcc/testsuite/g++.old-deja/g++.mike/empty.C new file mode 100644 index 00000000000..d69f3ad6243 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.mike/empty.C @@ -0,0 +1,25 @@ +// { dg-options "-W" } + +#define NOPE + +void foo() { + while (1); /* { dg-error "suggest a space before " } */ + { + } + for (;;); /* { dg-error "suggest a space before " } */ + { + } + while (1) + ; + for (;;) + ; + while (1) ; + for (;;) ; + /* These two work when using mapped locations */ + while (1) NOPE; /* { dg-bogus "suggest a space before " "suggest" { xfail *-*-* } } */ + for (;;) NOPE; /* { dg-bogus "suggest a space before " "suggest" { xfail *-*-* } } */ + while (1) + NOPE; + for (;;) + NOPE; +} diff --git a/gcc/testsuite/g++.old-deja/g++.other/inline8.C b/gcc/testsuite/g++.old-deja/g++.other/inline8.C index b919ab5df3f..a46dc382a7d 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/inline8.C +++ b/gcc/testsuite/g++.old-deja/g++.other/inline8.C @@ -4,6 +4,7 @@ #include <map> #include <cstdlib> +#include <cstring> using namespace std; diff --git a/gcc/testsuite/gcc.dg/20070507-1.c b/gcc/testsuite/gcc.dg/20070507-1.c new file mode 100644 index 00000000000..2884d1aa8d8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/20070507-1.c @@ -0,0 +1,103 @@ +/* This failed on s390x due to bug in loop.c. + loop.c failed to remove a REG_EQUAL note when + hoisting an insn from a loop body. */ + +/* { dg-options "-O3 -fPIC" } */ +/* { dg-do run { target fpic } } */ + +typedef __SIZE_TYPE__ size_t; +int memcmp(const void *s1, const void *s2, size_t n); + +typedef struct +{ + char name[30]; + int a; +} LOCAL; + +int global = 0; +int sy = 1; +int subroutine_offset; + +LOCAL local = { "local", 0 }; +LOCAL keywords = { "keywords", 1 }; +int local_table = 0; +int keywords_table = 0; + +void __attribute__((noinline)) bar (char *p_buffer) +{ + p_buffer[255] = 1; +} + +int __attribute__((noinline)) foo (char *p_str1) +{ + global = 1; + return 1; +} + +int __attribute__((noinline)) loop_next (int *p_table, char *p_table_head) +{ + static loop_next = 0; + + if (loop_next == 1) + return 1; + + loop_next = 1; + return 0; +} + +int +main () +{ + char buffer[256]; + int ende = 0; + int index; + int local_base = 2; + + keywords.a = 1; + for (sy = 0;; sy++) + { + for (index = 1;;) + { + bar (buffer); + if (buffer[sy] != 0) + { + ende = 1; + break; + }; + if (foo (buffer)) + { + keywords.a += index - 1; + break; + } + index++; + } + if (ende) + break; + } + + subroutine_offset = 0; + + for (;;) + { + if (loop_next (&keywords_table, (char*)&keywords)) + break; + + if ((!memcmp (keywords.name, "+++", 3))) + local_base = 100; + else + local_base = 0; + + if ((!memcmp (keywords.name, "+++", 3))) + subroutine_offset += local_table; + + for (;;) + { + if (loop_next (&local_table, (char*)&local)) + break;; + if ((local.a == 0)) + continue;; + foo (local.name); + } + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/dfp/convert-bfp-fold.c b/gcc/testsuite/gcc.dg/dfp/convert-bfp-fold.c index 7724e1d2c82..c5504993480 100644 --- a/gcc/testsuite/gcc.dg/dfp/convert-bfp-fold.c +++ b/gcc/testsuite/gcc.dg/dfp/convert-bfp-fold.c @@ -62,43 +62,42 @@ main () /* Conversions from binary float to decimal float. */ sf = 30.0f; - d32 = sf; - if (d32 != 30.0df) + d128 = sf; + if (d128 != 30.0dl) link_error (); d64 = sf; if (d64 != 30.0dd) link_error (); + d32 = sf; + if (d32 != 30.0df) + link_error (); + df = -2.0; - d32 = df; - if (d32 != -2.0df) + d128 = df; + if (d128 != -2.0dl) link_error (); d64 = df; if (d64 != -2.0dd) link_error (); - d128 = df; - if (d128 != -2.0dl) - link_error (); - - sf = 30.0f; - d128 = sf; - if (d128 != 30.0dl) - link_error (); + d32 = df; + if (d32 != -2.0df) + link_error (); tf = -22.0l; - d32 = tf; - if (d32 != -22.0df) + d128 = tf; + if (d128 != -22.0dl) link_error (); d64 = tf; if (d64 != -22.0dd) link_error (); - d128 = tf; - if (d128 != -22.0dl) + d32 = tf; + if (d32 != -22.0df) link_error (); /* 2**(-11) = 0.00048828125. */ diff --git a/gcc/testsuite/gcc.dg/invalid-call-1.c b/gcc/testsuite/gcc.dg/invalid-call-1.c index 7474227fa52..4126b5a4ff0 100644 --- a/gcc/testsuite/gcc.dg/invalid-call-1.c +++ b/gcc/testsuite/gcc.dg/invalid-call-1.c @@ -3,7 +3,7 @@ /* { dg-do compile } */ /* { dg-options "-O2" } */ -/* { dg-options "-O2 -mtune=i586" { target i?86-*-* } } */ +/* { dg-options "-O2 -march=i586" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */ typedef void (*fp)(void); extern char* bar(void* a1, int a2); diff --git a/gcc/testsuite/gcc.dg/pch/pch.exp b/gcc/testsuite/gcc.dg/pch/pch.exp index 7e65e03e657..c2b309e194c 100644 --- a/gcc/testsuite/gcc.dg/pch/pch.exp +++ b/gcc/testsuite/gcc.dg/pch/pch.exp @@ -40,6 +40,7 @@ foreach test [lsort [glob -nocomplain $srcdir/$subdir/*.c]] { set test "largefile.c" set testh "largefile.hs" set f [open $test w] +puts $f "/* { dg-xfail-if \"PR 14940\" { \"i?86-*-solaris2.10\" } { \"*\" } { \"\" } } */" set v 0 for { set v 0 } { $v < 10000 } { incr v } { puts $f "#define MACRO_${v} \"1234567890\" \"$v\"" diff --git a/gcc/testsuite/gcc.dg/pr31847.c b/gcc/testsuite/gcc.dg/pr31847.c new file mode 100644 index 00000000000..4b945a994aa --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr31847.c @@ -0,0 +1,15 @@ +/* PR 31847 */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-all" } */ + +extern int bar(int); + +int foo() +{ + int a = 0; + return bar(a); +} + +/* { dg-final { scan-tree-dump-not "Created value for " "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/special/gcsec-1.c b/gcc/testsuite/gcc.dg/special/gcsec-1.c index 68d4066fa39..b76ad50aa78 100644 --- a/gcc/testsuite/gcc.dg/special/gcsec-1.c +++ b/gcc/testsuite/gcc.dg/special/gcsec-1.c @@ -5,7 +5,8 @@ /* { dg-options "-ffunction-sections -fdata-sections -Wl,--gc-sections -static" } */ /* { dg-options "-ffunction-sections -fdata-sections -Wl,--gc-sections -static" { target native } } */ -/* { dg-options "-ffunction-sections -fdata-sections -Wl,--gc-sections" { target *-*-netware* } } */ +/* Solaris 10 does not support static linking; there is no libc.a. */ +/* { dg-options "-ffunction-sections -fdata-sections -Wl,--gc-sections" { target *-*-netware* i?86-*-solaris2.1[0-9] } } */ #include <stdlib.h> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-29.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-29.c new file mode 100644 index 00000000000..13699aafd62 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-29.c @@ -0,0 +1,21 @@ +/* PR 31885 */ + +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-empty" } */ + +struct s { + int *blah; +}; + +static struct s array[] = { { 0 } }; + +void +foo (struct s *p) +{ + struct s *q = &array[1]; + while (p < q) + p++; +} + +/* { dg-final { scan-tree-dump-times "Removing empty loop" 1 "empty" } } */ +/* { dg-final { cleanup-tree-dump "empty" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr31854.c b/gcc/testsuite/gcc.target/i386/pr31854.c new file mode 100644 index 00000000000..d5dca57ea63 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr31854.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target dfp } } */ +/* { dg-options "-O -std=gnu99" } */ + +_Decimal128 d128; +long double tf; + +void foo (void) +{ + d128 = tf; +} diff --git a/gcc/testsuite/gcc.target/mips/msub-1.c b/gcc/testsuite/gcc.target/mips/msub-1.c new file mode 100644 index 00000000000..d27e6479ef5 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/msub-1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-mips-options "-O2 -march=vr5400 -mgp32" } */ +/* { dg-final { scan-assembler-times "\tmsac\t\\\$0," 2 } } */ + +long long +f1 (int x, int y, long long z) +{ + return z - (long long) y * x; +} + +long long +f2 (int x, int y, long long z) +{ + long long t = (long long) x * y; + int temp = 5; + if (temp == 5) + z -= t; + return z; +} diff --git a/gcc/testsuite/gcc.target/mips/msub-2.c b/gcc/testsuite/gcc.target/mips/msub-2.c new file mode 100644 index 00000000000..acb7efb2b43 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/msub-2.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-mips-options "-O2 -march=vr5500 -mgp32" } */ +/* { dg-final { scan-assembler-times "\tmsub\t" 2 } } */ + +long long +f1 (int x, int y, long long z) +{ + return z - (long long) y * x; +} + +long long +f2 (int x, int y, long long z) +{ + long long t = (long long) x * y; + int temp = 5; + if (temp == 5) + z -= t; + return z; +} diff --git a/gcc/testsuite/gcc.target/mips/msub-3.c b/gcc/testsuite/gcc.target/mips/msub-3.c new file mode 100644 index 00000000000..85cfed2febe --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/msub-3.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-mips-options "-O2 -mips32 -mgp32" } */ +/* { dg-final { scan-assembler-times "\tmsub\t" 2 } } */ + +long long +f1 (int x, int y, long long z) +{ + return z - (long long) y * x; +} + +long long +f2 (int x, int y, long long z) +{ + long long t = (long long) x * y; + int temp = 5; + if (temp == 5) + z -= t; + return z; +} diff --git a/gcc/testsuite/gcc.target/mips/msub-4.c b/gcc/testsuite/gcc.target/mips/msub-4.c new file mode 100644 index 00000000000..8a526f8f583 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/msub-4.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-mips-options "-O2 -mips32r2 -mdspr2 -mgp32" } */ +/* { dg-final { scan-assembler-times "\tmsub\t\\\$ac" 2 } } */ + +long long +f1 (int x, int y, long long z) +{ + return z - (long long) y * x; +} + +long long +f2 (int x, int y, long long z) +{ + long long t = (long long) x * y; + int temp = 5; + if (temp == 5) + z -= t; + return z; +} diff --git a/gcc/testsuite/gcc.target/mips/msubu-1.c b/gcc/testsuite/gcc.target/mips/msubu-1.c new file mode 100644 index 00000000000..9390c473f53 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/msubu-1.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-mips-options "-O2 -march=vr5400 -mgp32" } */ +/* { dg-final { scan-assembler-times "\tmsacu\t\\\$0," 2 } } */ + +typedef unsigned int ui; +typedef unsigned long long ull; + +ull +f1 (ui x, ui y, ull z) +{ + return z - (ull) y * x; +} + +ull +f2 (ui x, ui y, ull z) +{ + ull t = (ull) x * y; + int temp = 5; + if (temp == 5) + z -= t; + return z; +} diff --git a/gcc/testsuite/gcc.target/mips/msubu-2.c b/gcc/testsuite/gcc.target/mips/msubu-2.c new file mode 100644 index 00000000000..75fb404eb97 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/msubu-2.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-mips-options "-O2 -march=vr5500 -mgp32" } */ +/* { dg-final { scan-assembler-times "\tmsubu\t" 2 } } */ + +typedef unsigned int ui; +typedef unsigned long long ull; + +ull +f1 (ui x, ui y, ull z) +{ + return z - (ull) y * x; +} + +ull +f2 (ui x, ui y, ull z) +{ + ull t = (ull) x * y; + int temp = 5; + if (temp == 5) + z -= t; + return z; +} diff --git a/gcc/testsuite/gcc.target/mips/msubu-3.c b/gcc/testsuite/gcc.target/mips/msubu-3.c new file mode 100644 index 00000000000..055ba589a95 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/msubu-3.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-mips-options "-O2 -mips32 -mgp32" } */ +/* { dg-final { scan-assembler-times "\tmsubu\t" 2 } } */ + +typedef unsigned int ui; +typedef unsigned long long ull; + +ull +f1 (ui x, ui y, ull z) +{ + return z - (ull) y * x; +} + +ull +f2 (ui x, ui y, ull z) +{ + ull t = (ull) x * y; + int temp = 5; + if (temp == 5) + z -= t; + return z; +} diff --git a/gcc/testsuite/gcc.target/mips/msubu-4.c b/gcc/testsuite/gcc.target/mips/msubu-4.c new file mode 100644 index 00000000000..ea4adb1b080 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/msubu-4.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-mips-options "-O2 -mips32r2 -mdspr2 -mgp32" } */ +/* { dg-final { scan-assembler-times "\tmsubu\t\\\$ac" 2 } } */ + +typedef unsigned int ui; +typedef unsigned long long ull; + +ull +f1 (ui x, ui y, ull z) +{ + return z - (ull) y * x; +} + +ull +f2 (ui x, ui y, ull z) +{ + ull t = (ull) x * y; + int temp = 5; + if (temp == 5) + z -= t; + return z; +} diff --git a/gcc/testsuite/gfortran.dg/actual_array_result_1.f90 b/gcc/testsuite/gfortran.dg/actual_array_result_1.f90 new file mode 100644 index 00000000000..cf79315cbb7 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/actual_array_result_1.f90 @@ -0,0 +1,71 @@ +! { dg-do run } +! PR fortan/31692 +! Passing array valued results to procedures +! +! Test case contributed by rakuen_himawari@yahoo.co.jp +module one + integer :: flag = 0 +contains + function foo1 (n) + integer :: n + integer :: foo1(n) + if (flag == 0) then + call bar1 (n, foo1) + else + call bar2 (n, foo1) + end if + end function + + function foo2 (n) + implicit none + integer :: n + integer,ALLOCATABLE :: foo2(:) + allocate (foo2(n)) + if (flag == 0) then + call bar1 (n, foo2) + else + call bar2 (n, foo2) + end if + end function + + function foo3 (n) + implicit none + integer :: n + integer,ALLOCATABLE :: foo3(:) + allocate (foo3(n)) + foo3 = 0 + call bar2(n, foo3(2:(n-1))) ! Check that sections are OK + end function + + subroutine bar1 (n, array) ! Checks assumed size formal arg. + integer :: n + integer :: array(*) + integer :: i + do i = 1, n + array(i) = i + enddo + end subroutine + + subroutine bar2(n, array) ! Checks assumed shape formal arg. + integer :: n + integer :: array(:) + integer :: i + do i = 1, size (array, 1) + array(i) = i + enddo + end subroutine +end module + +program main + use one + integer :: n + n = 3 + if(any (foo1(n) /= [ 1,2,3 ])) call abort() + if(any (foo2(n) /= [ 1,2,3 ])) call abort() + flag = 1 + if(any (foo1(n) /= [ 1,2,3 ])) call abort() + if(any (foo2(n) /= [ 1,2,3 ])) call abort() + n = 5 + if(any (foo3(n) /= [ 0,1,2,3,0 ])) call abort() +end program +! { dg-final { cleanup-modules "one" } } diff --git a/gcc/testsuite/gfortran.dg/assumed_dummy_1.f90 b/gcc/testsuite/gfortran.dg/assumed_dummy_1.f90 index 97c163e8c6b..f0cf7750332 100644 --- a/gcc/testsuite/gfortran.dg/assumed_dummy_1.f90 +++ b/gcc/testsuite/gfortran.dg/assumed_dummy_1.f90 @@ -1,4 +1,4 @@ -! { dg do-run} +! { dg-do run} ! Tests the fix for PRs 19358, 19477, 21211 and 21622. ! ! Note that this tests only the valid cases with explicit interfaces. diff --git a/gcc/testsuite/gfortran.dg/bounds_check_fail_1.f90 b/gcc/testsuite/gfortran.dg/bounds_check_fail_1.f90 index 938d19a6409..8617456f1e0 100644 --- a/gcc/testsuite/gfortran.dg/bounds_check_fail_1.f90 +++ b/gcc/testsuite/gfortran.dg/bounds_check_fail_1.f90 @@ -4,4 +4,4 @@ integer x(1) x(2) = x(1) ! { dg-warning "out of bounds" } end -! { dg-output "out of bounds for array 'x', upper bound of dimension 1 exceeded.*at line 5" } +! { dg-output "out of bounds for array 'x', upper bound of dimension 1 exceeded." } diff --git a/gcc/testsuite/gfortran.dg/char_initialiser_actual.f90 b/gcc/testsuite/gfortran.dg/char_initialiser_actual.f90 index 3796f7ee21c..7975a7e424b 100644 --- a/gcc/testsuite/gfortran.dg/char_initialiser_actual.f90 +++ b/gcc/testsuite/gfortran.dg/char_initialiser_actual.f90 @@ -1,4 +1,4 @@ -! { dg do-run } +! { dg-do run } ! Tests passing of character array initialiser as actual argument. ! Fixes PR18109. ! Contributed by Paul Thomas pault@gcc.gnu.org diff --git a/gcc/testsuite/gfortran.dg/do_3.F90 b/gcc/testsuite/gfortran.dg/do_3.F90 new file mode 100644 index 00000000000..1e2e238bf7e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/do_3.F90 @@ -0,0 +1,110 @@ +! { dg-do run } +! { dg-options "-std=legacy -ffree-line-length-none" } +program test + integer :: count + integer :: i + integer(kind=1) :: i1 + real :: r + +#define TEST_LOOP(var,from,to,step,total,test) \ + count = 0 ; do var = from, to, step ; count = count + 1 ; end do ; \ + if (count /= total) call abort ; \ + if (test (from, to, step) /= total) call abort + + ! Integer loops + TEST_LOOP(i, 0, 0, 1, 1, test_i) + TEST_LOOP(i, 0, 0, 2, 1, test_i) + TEST_LOOP(i, 0, 0, -1, 1, test_i) + TEST_LOOP(i, 0, 0, -2, 1, test_i) + + TEST_LOOP(i, 0, 1, 1, 2, test_i) + TEST_LOOP(i, 0, 1, 2, 1, test_i) + TEST_LOOP(i, 0, 1, 3, 1, test_i) + TEST_LOOP(i, 0, 1, huge(0), 1, test_i) + TEST_LOOP(i, 0, 1, -1, 0, test_i) + TEST_LOOP(i, 0, 1, -2, 0, test_i) + TEST_LOOP(i, 0, 1, -3, 0, test_i) + TEST_LOOP(i, 0, 1, -huge(0), 0, test_i) + TEST_LOOP(i, 0, 1, -huge(0)-1, 0, test_i) + + TEST_LOOP(i, 1, 0, 1, 0, test_i) + TEST_LOOP(i, 1, 0, 2, 0, test_i) + TEST_LOOP(i, 1, 0, 3, 0, test_i) + TEST_LOOP(i, 1, 0, huge(0), 0, test_i) + TEST_LOOP(i, 1, 0, -1, 2, test_i) + TEST_LOOP(i, 1, 0, -2, 1, test_i) + TEST_LOOP(i, 1, 0, -3, 1, test_i) + TEST_LOOP(i, 1, 0, -huge(0), 1, test_i) + TEST_LOOP(i, 1, 0, -huge(0)-1, 1, test_i) + + TEST_LOOP(i, 0, 17, 1, 18, test_i) + TEST_LOOP(i, 0, 17, 2, 9, test_i) + TEST_LOOP(i, 0, 17, 3, 6, test_i) + TEST_LOOP(i, 0, 17, 4, 5, test_i) + TEST_LOOP(i, 0, 17, 5, 4, test_i) + TEST_LOOP(i, 17, 0, -1, 18, test_i) + TEST_LOOP(i, 17, 0, -2, 9, test_i) + TEST_LOOP(i, 17, 0, -3, 6, test_i) + TEST_LOOP(i, 17, 0, -4, 5, test_i) + TEST_LOOP(i, 17, 0, -5, 4, test_i) + + TEST_LOOP(i1, -huge(i1)-1_1, huge(i1), 1_1, int(huge(i1))*2+2, test_i1) + TEST_LOOP(i1, -huge(i1)-1_1, huge(i1), 2_1, int(huge(i1))+1, test_i1) + TEST_LOOP(i1, -huge(i1)-1_1, huge(i1), huge(i1), 3, test_i1) + + TEST_LOOP(i1, huge(i1), -huge(i1)-1_1, -1_1, int(huge(i1))*2+2, test_i1) + TEST_LOOP(i1, huge(i1), -huge(i1)-1_1, -2_1, int(huge(i1))+1, test_i1) + TEST_LOOP(i1, huge(i1), -huge(i1)-1_1, -huge(i1), 3, test_i1) + TEST_LOOP(i1, huge(i1), -huge(i1)-1_1, -huge(i1)-1_1, 2, test_i1) + + TEST_LOOP(i1, -2_1, 3_1, huge(i1), 1, test_i1) + TEST_LOOP(i1, -2_1, 3_1, -huge(i1), 0, test_i1) + TEST_LOOP(i1, 2_1, -3_1, -huge(i1), 1, test_i1) + TEST_LOOP(i1, 2_1, -3_1, huge(i1), 0, test_i1) + + ! Real loops + TEST_LOOP(r, 0.0, 1.0, 0.11, 1 + int(1.0/0.11), test_r) + TEST_LOOP(r, 0.0, 1.0, -0.11, 0, test_r) + TEST_LOOP(r, 0.0, -1.0, 0.11, 0, test_r) + TEST_LOOP(r, 0.0, -1.0, -0.11, 1 + int(1.0/0.11), test_r) + TEST_LOOP(r, 0.0, 0.0, 0.11, 1, test_r) + TEST_LOOP(r, 0.0, 0.0, -0.11, 1, test_r) + +#undef TEST_LOOP + +contains + + function test_i1 (from, to, step) result(res) + integer(kind=1), intent(in) :: from, to, step + integer(kind=1) :: i + integer :: res + + res = 0 + do i = from, to, step + res = res + 1 + end do + end function test_i1 + + function test_i (from, to, step) result(res) + integer, intent(in) :: from, to, step + integer :: i + integer :: res + + res = 0 + do i = from, to, step + res = res + 1 + end do + end function test_i + + function test_r (from, to, step) result(res) + real, intent(in) :: from, to, step + real :: i + integer :: res + + res = 0 + do i = from, to, step + res = res + 1 + end do + end function test_r + +end program test diff --git a/gcc/testsuite/gfortran.dg/iostat_4.f90 b/gcc/testsuite/gfortran.dg/iostat_4.f90 new file mode 100644 index 00000000000..34c25f962d4 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/iostat_4.f90 @@ -0,0 +1,9 @@ +! { dg-do run } +! PR31201 Too large unit number generates wrong code +! This tests initialization of the IOSTAT variable + integer :: i + character(len=50) :: str + write (2_8*int(huge(0_4),kind=8)+9_8, iostat=i, iomsg=str) 555 + if (i.ne.5005) call abort + if (str.ne."Unit number in I/O statement too large") call abort + end
\ No newline at end of file diff --git a/gcc/testsuite/gfortran.dg/large_unit_1.f90 b/gcc/testsuite/gfortran.dg/large_unit_1.f90 new file mode 100644 index 00000000000..60e2d1f17e8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/large_unit_1.f90 @@ -0,0 +1,17 @@ +! { dg-do run } +! { dg-shouldfail "Unit number in I/O statement too large" } +! PR31201 Unit number in I/O statement too large +! Test case from PR + integer(kind=8) :: k= 2_8**36 + 10 + integer(kind=4) :: j= 10 + logical ex,op + INQUIRE(unit=k, exist=ex,opened=op) + print *, ex, op + IF (ex) THEN + OPEN(unit=k) + INQUIRE(unit=j, opened=op) + IF (op) CALL ABORT() + ENDIF + print *, k + close(k) + end diff --git a/gcc/testsuite/gfortran.dg/large_unit_2.f90 b/gcc/testsuite/gfortran.dg/large_unit_2.f90 new file mode 100644 index 00000000000..5f3554cc5bb --- /dev/null +++ b/gcc/testsuite/gfortran.dg/large_unit_2.f90 @@ -0,0 +1,13 @@ +! { dg-do run } +! PR31201 Too large unit number generates wrong code +! Test case by Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + integer :: i + logical :: l + character(len=60) :: s + open(2_8*huge(0)+20_8,file="foo",iostat=i) + if (i == 0) call abort + open(2_8*huge(0)+20_8,file="foo",err=99) + call abort + 99 inquire(unit=18,opened=l) + if (l) call abort + end diff --git a/gcc/testsuite/gfortran.dg/nested_modules_2.f90 b/gcc/testsuite/gfortran.dg/nested_modules_2.f90 index 3d0985a7eac..5bfdaddaac2 100644 --- a/gcc/testsuite/gfortran.dg/nested_modules_2.f90 +++ b/gcc/testsuite/gfortran.dg/nested_modules_2.f90 @@ -1,4 +1,4 @@ -! { dg do-run } +! { dg-do run } ! This tests the patch for PR16861. ! ! Contributed by Paul Thomas <pault@gcc.gnu.org> diff --git a/gcc/testsuite/gfortran.dg/new_line.f90 b/gcc/testsuite/gfortran.dg/new_line.f90 index 355ca30209b..aacabc69f6e 100644 --- a/gcc/testsuite/gfortran.dg/new_line.f90 +++ b/gcc/testsuite/gfortran.dg/new_line.f90 @@ -2,6 +2,19 @@ ! Checks Fortran 2003's new_line intrinsic function ! PR fortran/28585 program new_line_check - implicit none - if(achar(10) /= new_line('a')) call abort() + implicit none + character(len=10) :: a1 + character(len=10) :: a2(2) + character(len=10), parameter :: a3 = "1234567890" + character(len=10), parameter :: a4(2) = "1234567890" + character(len=10), parameter :: a5(2) = repeat("1234567890",2) + + if(achar(10) /= new_line('a')) call abort + + if (iachar(new_line(a1)) /= 10) call abort + if (iachar(new_line(a2)) /= 10) call abort + if (iachar(new_line(a3)) /= 10) call abort + if (iachar(new_line(a4)) /= 10) call abort + if (iachar(new_line(a5)) /= 10) call abort + end program new_line_check diff --git a/gcc/testsuite/gfortran.dg/parameter_array_init_1.f90 b/gcc/testsuite/gfortran.dg/parameter_array_init_1.f90 new file mode 100644 index 00000000000..bb029a5b080 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/parameter_array_init_1.f90 @@ -0,0 +1,11 @@ +! { dg-do compile } +! tests the fix for PR29397, in which the initializer for the parameter +! 'J' was not expanded into an array. +! +! Contributed by Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> +! + INTEGER :: K(3) = 1 + INTEGER, PARAMETER :: J(3) = 2 + IF (ANY (MAXLOC (K, J<3) .NE. 1)) CALL ABORT () + IF (ANY (J .NE. 2)) CALL ABORT () +END diff --git a/gcc/testsuite/gfortran.dg/parameter_array_init_2.f90 b/gcc/testsuite/gfortran.dg/parameter_array_init_2.f90 new file mode 100644 index 00000000000..bf238e5ee32 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/parameter_array_init_2.f90 @@ -0,0 +1,26 @@ +! { dg-do run } +! { dg-options "-std=gnu" } ! suppress the warning about line 15 +! Thrashes the fix for PR29400, where the scalar initializers +! were not expanded to arrays with the appropriate shape. +! +! Contributed by Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> +! + integer,parameter :: i(1,1) = 0, j(2) = 42
+
+ if (any (maxloc(j+j,mask=(j==2)) .ne. 0)) call abort ()
+ if (size(j+j) .ne. 2) call abort ()
+ if (minval(j+j) .ne. 84) call abort ()
+ if (minval(j,mask=(j==2)) .ne. huge (j)) call abort ()
+ if (maxval(j+j) .ne. 84) call abort ()
+ if (maxval(j,mask=(j==2)) .ne. -huge (j)-1) call abort ()
+ if (sum(j,mask=j==2) .ne. 0) call abort ()
+ if (sum(j+j) .ne. 168) call abort ()
+ if (product(j+j) .ne. 7056) call abort ()
+ if (any(ubound(j+j) .ne. 2)) call abort ()
+ if (any(lbound(j+j) .ne. 1)) call abort ()
+ if (dot_product(j+j,j) .ne. 7056) call abort ()
+ if (dot_product(j,j+j) .ne. 7056) call abort ()
+ if (count(i==1) .ne. 0) call abort ()
+ if (any(i==1)) call abort ()
+ if (all(i==1)) call abort ()
+ end
diff --git a/gcc/testsuite/gfortran.dg/shift-alloc.f90 b/gcc/testsuite/gfortran.dg/shift-alloc.f90 index 2d660317235..70f1cbb660e 100644 --- a/gcc/testsuite/gfortran.dg/shift-alloc.f90 +++ b/gcc/testsuite/gfortran.dg/shift-alloc.f90 @@ -1,4 +1,4 @@ -! { dg do-run } +! { dg-do run } ! PR 22144: eoshift1, eoshift3 and cshift1 used to lack memory ! allocation, which caused the writes to segfault. program main diff --git a/gcc/testsuite/gfortran.dg/unf_read_corrupted_2.f90 b/gcc/testsuite/gfortran.dg/unf_read_corrupted_2.f90 new file mode 100644 index 00000000000..1788b457d19 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/unf_read_corrupted_2.f90 @@ -0,0 +1,27 @@ +! { dg-do run } +! PR31880 silent data corruption in gfortran read statement +! Test from PR. + program r3 + + integer(kind=4) :: a(1025),b(1025),c(1025),d(2048),e(1022) + + a = 5 + b = 6 + c = 7 + e = 8 + + do i=1,2048 + d(i)=i + end do + + open (3,form='unformatted', status="scratch") + write (3) a,b,c,d,e + rewind 3 + d = 0 + read (3) a,b,c,d + close (3) + + if (d(1).ne.1) call abort + if (d(2048).ne.2048) call abort + + end diff --git a/gcc/testsuite/gnat.dg/opt1.adb b/gcc/testsuite/gnat.dg/opt1.adb new file mode 100644 index 00000000000..69bb8136d04 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt1.adb @@ -0,0 +1,29 @@ +-- { dg-do compile } +-- { dg-options "-O -gnatws" } + +package body Opt1 is + + function De_Linear_Index + (Index : Natural; + D : Natural; + Ind_Lengths : Dimention_Length) + return Dimension_Indexes + is + Len : Natural := 1; + Tmp_Ind : Natural := Index; + Tmp_Res : Natural; + Result : Dimension_Indexes (1 .. D); + begin + for J in 1 .. D loop + Len := Len * Ind_Lengths (J); + end loop; + + for J in Result'Range loop + Result (J) := Tmp_Res; + Tmp_Ind := Tmp_Ind - Len * (Result (J) - 1); + end loop; + + return Result; + end; + +end Opt1; diff --git a/gcc/testsuite/gnat.dg/opt1.ads b/gcc/testsuite/gnat.dg/opt1.ads new file mode 100644 index 00000000000..247e7dc639c --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt1.ads @@ -0,0 +1,13 @@ +package Opt1 is + + type Dimention_Length is array (1 .. 16) of Natural; + + type Dimension_Indexes is array (Positive range <>) of Positive; + + function De_Linear_Index + (Index : Natural; + D : Natural; + Ind_Lengths : Dimention_Length) + return Dimension_Indexes; + +end Opt1; diff --git a/gcc/tree-chrec.c b/gcc/tree-chrec.c index b5c5a535589..03cd5f3eb8c 100644 --- a/gcc/tree-chrec.c +++ b/gcc/tree-chrec.c @@ -897,11 +897,12 @@ chrec_contains_undetermined (tree chrec) { int i, n; - if (chrec == chrec_dont_know - || chrec == chrec_not_analyzed_yet - || chrec == NULL_TREE) + if (chrec == chrec_dont_know) return true; + if (chrec == NULL_TREE) + return false; + n = TREE_OPERAND_LENGTH (chrec); for (i = 0; i < n; i++) if (chrec_contains_undetermined (TREE_OPERAND (chrec, i))) diff --git a/gcc/tree-chrec.h b/gcc/tree-chrec.h index 42bbb6c0440..70bb4c8ab89 100644 --- a/gcc/tree-chrec.h +++ b/gcc/tree-chrec.h @@ -36,8 +36,7 @@ extern GTY(()) tree chrec_known; static inline bool automatically_generated_chrec_p (tree chrec) { - return (chrec == chrec_not_analyzed_yet - || chrec == chrec_dont_know + return (chrec == chrec_dont_know || chrec == chrec_known); } diff --git a/gcc/tree-dump.c b/gcc/tree-dump.c index ea8f378d2d1..16f71df2028 100644 --- a/gcc/tree-dump.c +++ b/gcc/tree-dump.c @@ -803,7 +803,7 @@ static const struct dump_option_value_info dump_options[] = {"stmtaddr", TDF_STMTADDR}, {"memsyms", TDF_MEMSYMS}, {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA - | TDF_STMTADDR | TDF_GRAPH)}, + | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC)}, {NULL, 0} }; diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 832bd122626..cb74180c2da 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -1863,7 +1863,8 @@ maybe_fold_stmt_indirect (tree expr, tree base, tree offset) return NULL_TREE; base = TREE_OPERAND (base, 0); - offset = int_const_binop (PLUS_EXPR, offset, offset2, 1); + offset = fold_convert (sizetype, + int_const_binop (PLUS_EXPR, offset, offset2, 1)); } if (TREE_CODE (base) == ADDR_EXPR) diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index 6e1387f7157..7a146157f99 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -275,6 +275,7 @@ tree_ssa_dominator_optimize (void) init_walk_dominator_tree (&walk_data); calculate_dominance_info (CDI_DOMINATORS); + cfg_altered = false; /* We need to know which edges exit loops so that we can aggressively thread through loop headers to an exit @@ -320,17 +321,17 @@ tree_ssa_dominator_optimize (void) /* Thread jumps, creating duplicate blocks as needed. */ cfg_altered |= thread_through_all_blocks (); + if (cfg_altered) + free_dominance_info (CDI_DOMINATORS); + /* Removal of statements may make some EH edges dead. Purge such edges from the CFG as needed. */ if (!bitmap_empty_p (need_eh_cleanup)) { - cfg_altered |= tree_purge_all_dead_eh_edges (need_eh_cleanup); + tree_purge_all_dead_eh_edges (need_eh_cleanup); bitmap_zero (need_eh_cleanup); } - if (cfg_altered) - free_dominance_info (CDI_DOMINATORS); - /* Finally, remove everything except invariants in SSA_NAME_VALUE. Long term we will be able to let everything in SSA_NAME_VALUE @@ -2336,7 +2337,7 @@ propagate_rhs_into_lhs (tree stmt, tree lhs, tree rhs, bitmap interesting_names) te->count += e->count; remove_edge (e); - cfg_altered = 1; + cfg_altered = true; } else ei_next (&ei); @@ -2485,6 +2486,9 @@ eliminate_degenerate_phis (void) interesting_names = BITMAP_ALLOC (NULL); interesting_names1 = BITMAP_ALLOC (NULL); + calculate_dominance_info (CDI_DOMINATORS); + cfg_altered = false; + /* First phase. Eliminate degenerate PHIs via a dominator walk of the CFG. @@ -2493,7 +2497,6 @@ eliminate_degenerate_phis (void) phase in dominator order. Presumably this is because walking in dominator order leaves fewer PHIs for later examination by the worklist phase. */ - calculate_dominance_info (CDI_DOMINATORS); eliminate_degenerate_phis_1 (ENTRY_BLOCK_PTR, interesting_names); /* Second phase. Eliminate second order degenerate PHIs as well @@ -2522,18 +2525,19 @@ eliminate_degenerate_phis (void) } } + if (cfg_altered) + free_dominance_info (CDI_DOMINATORS); + /* Propagation of const and copies may make some EH edges dead. Purge such edges from the CFG as needed. */ if (!bitmap_empty_p (need_eh_cleanup)) { - cfg_altered |= tree_purge_all_dead_eh_edges (need_eh_cleanup); + tree_purge_all_dead_eh_edges (need_eh_cleanup); BITMAP_FREE (need_eh_cleanup); } BITMAP_FREE (interesting_names); BITMAP_FREE (interesting_names1); - if (cfg_altered) - free_dominance_info (CDI_DOMINATORS); return 0; } diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 239bbb32cd2..a8bdfebaecb 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -679,12 +679,15 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1, mpz_t mmod; tree assumption = boolean_true_node, bound, noloop; bool ret = false; + tree type1 = type; + if (POINTER_TYPE_P (type)) + type1 = sizetype; if (TREE_CODE (mod) != INTEGER_CST) return false; if (integer_nonzerop (mod)) mod = fold_build2 (MINUS_EXPR, niter_type, step, mod); - tmod = fold_convert (type, mod); + tmod = fold_convert (type1, mod); mpz_init (mmod); mpz_set_double_int (mmod, tree_to_double_int (mod), true); @@ -698,7 +701,7 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1, if (!iv1->no_overflow && !integer_zerop (mod)) { bound = fold_build2 (MINUS_EXPR, type, - TYPE_MAX_VALUE (type), tmod); + TYPE_MAX_VALUE (type1), tmod); assumption = fold_build2 (LE_EXPR, boolean_type_node, iv1->base, bound); if (integer_zerop (assumption)) @@ -709,7 +712,7 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1, else noloop = fold_build2 (GT_EXPR, boolean_type_node, iv0->base, - fold_build2 (PLUS_EXPR, type, + fold_build2 (PLUS_EXPR, type1, iv1->base, tmod)); } else @@ -719,8 +722,8 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1, iv0->base - MOD <= iv1->base. */ if (!iv0->no_overflow && !integer_zerop (mod)) { - bound = fold_build2 (PLUS_EXPR, type, - TYPE_MIN_VALUE (type), tmod); + bound = fold_build2 (PLUS_EXPR, type1, + TYPE_MIN_VALUE (type1), tmod); assumption = fold_build2 (GE_EXPR, boolean_type_node, iv0->base, bound); if (integer_zerop (assumption)) @@ -730,7 +733,7 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1, noloop = boolean_false_node; else noloop = fold_build2 (GT_EXPR, boolean_type_node, - fold_build2 (MINUS_EXPR, type, + fold_build2 (MINUS_EXPR, type1, iv0->base, tmod), iv1->base); } |