diff --git a/.cvsignore b/.cvsignore index 055b350..889576b 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1,2 +1,2 @@ fastjar-0.97.tar.gz -gcc-4.4.0-20090420.tar.bz2 +gcc-4.4.0-20090422.tar.bz2 diff --git a/gcc.spec b/gcc.spec index 05c3a01..7699625 100644 --- a/gcc.spec +++ b/gcc.spec @@ -1,9 +1,9 @@ -%define DATE 20090420 -%define SVNREV 146449 +%define DATE 20090422 +%define SVNREV 146590 %define gcc_version 4.4.0 # Note, gcc_release must be integer, if you want to add suffixes to # %{release}, append them after %{gcc_release} on Release: line. -%define gcc_release 0.35 +%define gcc_release 1 %define _unpackaged_files_terminate_build 0 %define multilib_64_archs sparc64 ppc64 s390x x86_64 %define include_gappletviewer 1 @@ -150,6 +150,12 @@ Patch24: gcc44-atom.patch Patch26: gcc44-power7.patch Patch28: gcc44-pr38757.patch Patch30: gcc44-pr39543.patch +Patch31: gcc44-find_base_term.patch +Patch32: gcc44-pr39794.patch +Patch33: gcc44-rh459374-1.patch +Patch34: gcc44-rh459374-2.patch +Patch35: gcc44-rh459374-3.patch +Patch36: gcc44-cswtch.patch Patch1000: fastjar-0.97-segfault.patch @@ -437,7 +443,13 @@ which are required to compile with the GNAT. %patch24 -p0 -b .atom~ %patch26 -p0 -b .power7~ %patch28 -p0 -b .pr38757~ -#%patch30 -p0 -b .pr39543~ +%patch30 -p0 -b .pr39543~ +%patch31 -p0 -b .find_base_term~ +%patch32 -p0 -b .pr39794~ +%patch33 -p0 -b .rh459374-1~ +%patch34 -p0 -b .rh459374-2~ +%patch35 -p0 -b .rh459374-3~ +%patch36 -p0 -b .cswtch~ # This testcase doesn't compile. rm libjava/testsuite/libjava.lang/PR35020* @@ -1748,6 +1760,15 @@ fi %doc rpm.doc/changelogs/libmudflap/ChangeLog* %changelog +* Wed Apr 22 2009 Jakub Jelinek 4.4.0-1 +- update from gcc-4_4-branch + - GCC 4.4.0 release + - PR libstdc++/39802 +- fix up DSE (PR middle-end/39794) +- debuginfo fixes for VLA and nested/contained functions (#459374) +- improve -ftree-switch-conversion optimization if the constant is the + same in all cases + * Mon Apr 20 2009 Jakub Jelinek 4.4.0-0.35 - update from gcc-4_4-branch - PRs middle-end/39804, target/39678, target/39767, tree-optimization/39675, @@ -1827,7 +1848,7 @@ fi - fix memcmp builtin asm redirection (PR middle-end/39443) - fix sparcv9 profiledbootstrap (PR bootstrap/39454) -* Thu Mar 12 2009 Dennis Gilmore +* Thu Mar 12 2009 Dennis Gilmore - don't build with graphite support on sparc arches - still missing some deps diff --git a/gcc44-cswtch.patch b/gcc44-cswtch.patch new file mode 100644 index 0000000..e77118b --- /dev/null +++ b/gcc44-cswtch.patch @@ -0,0 +1,129 @@ +2009-04-21 Martin Jambor + + * tree-switch-conversion.c (constructor_contains_same_values_p): + New function. + (build_one_array): Create assigns of constants if possible. + + * gcc.dg/tree-ssa/cswtch-2.c: New test. + +--- gcc/tree-switch-conversion.c.jj 2009-03-28 18:11:43.000000000 +0100 ++++ gcc/tree-switch-conversion.c 2009-04-22 20:09:45.000000000 +0200 +@@ -459,6 +459,28 @@ build_constructors (gimple swtch) + } + } + ++/* If all values in the constructor vector are the same, return the value. ++ Otherwise return NULL_TREE. Not supposed to be called for empty ++ vectors. */ ++ ++static tree ++constructor_contains_same_values_p (VEC (constructor_elt, gc) *vec) ++{ ++ int i, len = VEC_length (constructor_elt, vec); ++ tree prev = NULL_TREE; ++ ++ for (i = 0; i < len; i++) ++ { ++ constructor_elt *elt = VEC_index (constructor_elt, vec, i); ++ ++ if (!prev) ++ prev = elt->value; ++ else if (!operand_equal_p (elt->value, prev, OEP_ONLY_CONST)) ++ return NULL_TREE; ++ } ++ return prev; ++} ++ + /* Create an appropriate array type and declaration and assemble a static array + variable. Also create a load statement that initializes the variable in + question with a value from the static array. SWTCH is the switch statement +@@ -472,35 +494,44 @@ static void + build_one_array (gimple swtch, int num, tree arr_index_type, gimple phi, + tree tidx) + { +- tree array_type, ctor, decl, value_type, name, fetch; ++ tree name, cst; + gimple load; + gimple_stmt_iterator gsi; + + gcc_assert (info.default_values[num]); +- value_type = TREE_TYPE (info.default_values[num]); +- array_type = build_array_type (value_type, arr_index_type); +- +- ctor = build_constructor (array_type, info.constructors[num]); +- TREE_CONSTANT (ctor) = true; +- +- decl = build_decl (VAR_DECL, NULL_TREE, array_type); +- TREE_STATIC (decl) = 1; +- DECL_INITIAL (decl) = ctor; +- +- DECL_NAME (decl) = create_tmp_var_name ("CSWTCH"); +- DECL_ARTIFICIAL (decl) = 1; +- TREE_CONSTANT (decl) = 1; +- add_referenced_var (decl); +- varpool_mark_needed_node (varpool_node (decl)); +- varpool_finalize_decl (decl); +- mark_sym_for_renaming (decl); + + name = make_ssa_name (SSA_NAME_VAR (PHI_RESULT (phi)), NULL); + info.target_inbound_names[num] = name; + +- fetch = build4 (ARRAY_REF, value_type, decl, tidx, NULL_TREE, +- NULL_TREE); +- load = gimple_build_assign (name, fetch); ++ cst = constructor_contains_same_values_p (info.constructors[num]); ++ if (cst) ++ load = gimple_build_assign (name, cst); ++ else ++ { ++ tree array_type, ctor, decl, value_type, fetch; ++ ++ value_type = TREE_TYPE (info.default_values[num]); ++ array_type = build_array_type (value_type, arr_index_type); ++ ++ ctor = build_constructor (array_type, info.constructors[num]); ++ TREE_CONSTANT (ctor) = true; ++ ++ decl = build_decl (VAR_DECL, NULL_TREE, array_type); ++ TREE_STATIC (decl) = 1; ++ DECL_INITIAL (decl) = ctor; ++ ++ DECL_NAME (decl) = create_tmp_var_name ("CSWTCH"); ++ DECL_ARTIFICIAL (decl) = 1; ++ TREE_CONSTANT (decl) = 1; ++ add_referenced_var (decl); ++ varpool_mark_needed_node (varpool_node (decl)); ++ varpool_finalize_decl (decl); ++ mark_sym_for_renaming (decl); ++ ++ fetch = build4 (ARRAY_REF, value_type, decl, tidx, NULL_TREE, ++ NULL_TREE); ++ load = gimple_build_assign (name, fetch); ++ } + SSA_NAME_DEF_STMT (name) = load; + + gsi = gsi_for_stmt (swtch); +--- gcc/testsuite/gcc.dg/tree-ssa/cswtch-2.c.jj 2009-04-22 20:01:40.000000000 +0200 ++++ gcc/testsuite/gcc.dg/tree-ssa/cswtch-2.c 2009-04-22 20:01:40.000000000 +0200 +@@ -0,0 +1,21 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -fdump-tree-switchconv" } */ ++ ++typedef enum { a = 5, b = 6, c = 7, d = 8, e = 9 } X; ++ ++int h1 (X x) ++{ ++ switch (x) { ++ case a: ++ case b: ++ case c: ++ case d: ++ case e: ++ return 1; ++ default: ++ return 0; ++ } ++} ++ ++/* { dg-final { scan-tree-dump-times "CSWTCH" 0 "switchconv" } } */ ++/* { dg-final { cleanup-tree-dump "switchconv" } } */ diff --git a/gcc44-find_base_term.patch b/gcc44-find_base_term.patch new file mode 100644 index 0000000..dd1c1dc --- /dev/null +++ b/gcc44-find_base_term.patch @@ -0,0 +1,28 @@ +2009-04-22 Jakub Jelinek + + * alias.c (find_base_term): Move around LO_SUM case, so that + CONST falls through into PLUS/MINUS handling. + +--- gcc/alias.c.jj 2009-04-21 11:16:28.000000000 +0200 ++++ gcc/alias.c 2009-04-21 12:44:18.000000000 +0200 +@@ -1438,15 +1438,16 @@ find_base_term (rtx x) + return x; + return 0; + ++ case LO_SUM: ++ /* The standard form is (lo_sum reg sym) so look only at the ++ second operand. */ ++ return find_base_term (XEXP (x, 1)); ++ + case CONST: + x = XEXP (x, 0); + if (GET_CODE (x) != PLUS && GET_CODE (x) != MINUS) + return 0; + /* Fall through. */ +- case LO_SUM: +- /* The standard form is (lo_sum reg sym) so look only at the +- second operand. */ +- return find_base_term (XEXP (x, 1)); + case PLUS: + case MINUS: + { diff --git a/gcc44-pr39543.patch b/gcc44-pr39543.patch index e84c6b5..3ee4dbd 100644 --- a/gcc44-pr39543.patch +++ b/gcc44-pr39543.patch @@ -1,6 +1,6 @@ -2009-04-10 Jakub Jelinek +2009-04-22 Jakub Jelinek - PR rtl-optimization/39543 + PR inline-asm/39543 * fwprop.c (forward_propagate_asm): New function. (forward_propagate_and_simplify): Propagate also into __asm, if it doesn't increase the number of referenced registers. @@ -140,7 +140,7 @@ --- gcc/testsuite/gcc.target/i386/pr39543-1.c.jj 2009-04-09 09:47:16.000000000 +0200 +++ gcc/testsuite/gcc.target/i386/pr39543-1.c 2009-04-09 09:47:16.000000000 +0200 @@ -0,0 +1,52 @@ -+/* PR rtl-optimization/39543 */ ++/* PR inline-asm/39543 */ +/* { dg-do compile } */ +/* { dg-options "-O3 -fomit-frame-pointer" } */ + @@ -195,7 +195,7 @@ --- gcc/testsuite/gcc.target/i386/pr39543-2.c.jj 2009-04-09 09:47:16.000000000 +0200 +++ gcc/testsuite/gcc.target/i386/pr39543-2.c 2009-04-09 09:47:16.000000000 +0200 @@ -0,0 +1,51 @@ -+/* PR rtl-optimization/39543 */ ++/* PR inline-asm/39543 */ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + @@ -249,7 +249,7 @@ --- gcc/testsuite/gcc.target/i386/pr39543-3.c.jj 2009-04-09 09:47:16.000000000 +0200 +++ gcc/testsuite/gcc.target/i386/pr39543-3.c 2009-04-09 09:47:16.000000000 +0200 @@ -0,0 +1,42 @@ -+/* PR rtl-optimization/39543 */ ++/* PR inline-asm/39543 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + diff --git a/gcc44-pr39794.patch b/gcc44-pr39794.patch new file mode 100644 index 0000000..620343e --- /dev/null +++ b/gcc44-pr39794.patch @@ -0,0 +1,277 @@ +2009-04-21 Jakub Jelinek + + PR middle-end/39794 + * alias.c (canon_true_dependence): Add x_addr argument. + * rtl.h (canon_true_dependence): Adjust prototype. + * cse.c (check_dependence): Adjust canon_true_dependence callers. + * cselib.c (cselib_invalidate_mem): Likewise. + * gcse.c (compute_transp): Likewise. + * dse.c (scan_reads_nospill): Likewise. + (record_store, check_mem_read_rtx): Likewise. For non-const or + frame addresses pass cselib_subst_to_values as mem_addr, for + const or frame addresses canon_base_mem of the group plus + optionally offset. + + * gcc.dg/pr39794.c: New test. + +--- gcc/alias.c.jj 2009-03-28 18:11:42.000000000 +0100 ++++ gcc/alias.c 2009-04-21 12:44:18.000000000 +0200 +@@ -2250,14 +2251,13 @@ true_dependence (const_rtx mem, enum mac + Variant of true_dependence which assumes MEM has already been + canonicalized (hence we no longer do that here). + The mem_addr argument has been added, since true_dependence computed +- this value prior to canonicalizing. */ ++ this value prior to canonicalizing. ++ If x_addr is non-NULL, it is used in preference of XEXP (x, 0). */ + + int + canon_true_dependence (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr, +- const_rtx x, bool (*varies) (const_rtx, bool)) ++ const_rtx x, rtx x_addr, bool (*varies) (const_rtx, bool)) + { +- rtx x_addr; +- + if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem)) + return 1; + +@@ -2283,7 +2283,8 @@ canon_true_dependence (const_rtx mem, en + if (nonoverlapping_memrefs_p (x, mem)) + return 0; + +- x_addr = get_addr (XEXP (x, 0)); ++ if (! x_addr) ++ x_addr = get_addr (XEXP (x, 0)); + + if (! base_alias_check (x_addr, mem_addr, GET_MODE (x), mem_mode)) + return 0; +--- gcc/dse.c.jj 2009-03-28 18:11:42.000000000 +0100 ++++ gcc/dse.c 2009-04-21 18:11:19.000000000 +0200 +@@ -1286,7 +1286,7 @@ static rtx get_stored_val (store_info_t, + static int + record_store (rtx body, bb_info_t bb_info) + { +- rtx mem, rhs, const_rhs; ++ rtx mem, rhs, const_rhs, mem_addr; + HOST_WIDE_INT offset = 0; + HOST_WIDE_INT width = 0; + alias_set_type spill_alias_set; +@@ -1456,6 +1456,20 @@ record_store (rtx body, bb_info_t bb_inf + ptr = active_local_stores; + last = NULL; + redundant_reason = NULL; ++ mem = canon_rtx (mem); ++ if (spill_alias_set || group_id < 0) ++ { ++ cselib_lookup (XEXP (mem, 0), Pmode, 1); ++ mem_addr = cselib_subst_to_values (XEXP (mem, 0)); ++ } ++ else ++ { ++ group_info_t group ++ = VEC_index (group_info_t, rtx_group_vec, group_id); ++ mem_addr = group->canon_base_mem; ++ if (offset) ++ mem_addr = gen_rtx_PLUS (GET_MODE (mem_addr), mem_addr, GEN_INT (offset)); ++ } + + while (ptr) + { +@@ -1547,13 +1561,13 @@ record_store (rtx body, bb_info_t bb_inf + if (canon_true_dependence (s_info->mem, + GET_MODE (s_info->mem), + s_info->mem_addr, +- mem, rtx_varies_p)) ++ mem, mem_addr, rtx_varies_p)) + { + s_info->rhs = NULL; + s_info->const_rhs = NULL; + } + } +- ++ + /* An insn can be deleted if every position of every one of + its s_infos is zero. */ + if (any_positions_needed_p (s_info) +@@ -1580,9 +1594,9 @@ record_store (rtx body, bb_info_t bb_inf + /* Finish filling in the store_info. */ + store_info->next = insn_info->store_rec; + insn_info->store_rec = store_info; +- store_info->mem = canon_rtx (mem); ++ store_info->mem = mem; + store_info->alias_set = spill_alias_set; +- store_info->mem_addr = get_addr (XEXP (mem, 0)); ++ store_info->mem_addr = mem_addr; + store_info->cse_base = base; + if (width > HOST_BITS_PER_WIDE_INT) + { +@@ -2006,7 +2020,7 @@ replace_read (store_info_t store_info, i + static int + check_mem_read_rtx (rtx *loc, void *data) + { +- rtx mem = *loc; ++ rtx mem = *loc, mem_addr; + bb_info_t bb_info; + insn_info_t insn_info; + HOST_WIDE_INT offset = 0; +@@ -2058,6 +2072,19 @@ check_mem_read_rtx (rtx *loc, void *data + read_info->end = offset + width; + read_info->next = insn_info->read_rec; + insn_info->read_rec = read_info; ++ if (spill_alias_set || group_id < 0) ++ { ++ cselib_lookup (XEXP (mem, 0), Pmode, 1); ++ mem_addr = cselib_subst_to_values (XEXP (mem, 0)); ++ } ++ else ++ { ++ group_info_t group ++ = VEC_index (group_info_t, rtx_group_vec, group_id); ++ mem_addr = group->canon_base_mem; ++ if (offset) ++ mem_addr = gen_rtx_PLUS (GET_MODE (mem_addr), mem_addr, GEN_INT (offset)); ++ } + + /* We ignore the clobbers in store_info. The is mildly aggressive, + but there really should not be a clobber followed by a read. */ +@@ -2128,7 +2155,7 @@ check_mem_read_rtx (rtx *loc, void *data + = canon_true_dependence (store_info->mem, + GET_MODE (store_info->mem), + store_info->mem_addr, +- mem, rtx_varies_p); ++ mem, mem_addr, rtx_varies_p); + + else if (group_id == store_info->group_id) + { +@@ -2139,7 +2166,7 @@ check_mem_read_rtx (rtx *loc, void *data + = canon_true_dependence (store_info->mem, + GET_MODE (store_info->mem), + store_info->mem_addr, +- mem, rtx_varies_p); ++ mem, mem_addr, rtx_varies_p); + + /* If this read is just reading back something that we just + stored, rewrite the read. */ +@@ -2224,7 +2251,7 @@ check_mem_read_rtx (rtx *loc, void *data + remove = canon_true_dependence (store_info->mem, + GET_MODE (store_info->mem), + store_info->mem_addr, +- mem, rtx_varies_p); ++ mem, mem_addr, rtx_varies_p); + + if (remove) + { +@@ -3067,7 +3094,8 @@ scan_reads_nospill (insn_info_t insn_inf + && canon_true_dependence (group->base_mem, + QImode, + group->canon_base_mem, +- read_info->mem, rtx_varies_p)) ++ read_info->mem, NULL_RTX, ++ rtx_varies_p)) + { + if (kill) + bitmap_ior_into (kill, group->group_kill); +--- gcc/cse.c.jj 2009-03-28 18:11:42.000000000 +0100 ++++ gcc/cse.c 2009-04-21 11:18:02.000000000 +0200 +@@ -1,6 +1,6 @@ + /* Common subexpression elimination for GNU compiler. + Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998 +- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 ++ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + Free Software Foundation, Inc. + + This file is part of GCC. +@@ -1658,7 +1658,7 @@ check_dependence (rtx *x, void *data) + { + struct check_dependence_data *d = (struct check_dependence_data *) data; + if (*x && MEM_P (*x)) +- return canon_true_dependence (d->exp, d->mode, d->addr, *x, ++ return canon_true_dependence (d->exp, d->mode, d->addr, *x, NULL_RTX, + cse_rtx_varies_p); + else + return 0; +--- gcc/rtl.h.jj 2009-03-28 18:11:43.000000000 +0100 ++++ gcc/rtl.h 2009-04-21 11:17:04.000000000 +0200 +@@ -2282,7 +2282,7 @@ extern rtx canon_rtx (rtx); + extern int true_dependence (const_rtx, enum machine_mode, const_rtx, bool (*)(const_rtx, bool)); + extern rtx get_addr (rtx); + extern int canon_true_dependence (const_rtx, enum machine_mode, rtx, const_rtx, +- bool (*)(const_rtx, bool)); ++ rtx, bool (*)(const_rtx, bool)); + extern int read_dependence (const_rtx, const_rtx); + extern int anti_dependence (const_rtx, const_rtx); + extern int output_dependence (const_rtx, const_rtx); +--- gcc/cselib.c.jj 2009-03-28 18:11:43.000000000 +0100 ++++ gcc/cselib.c 2009-04-21 11:18:25.000000000 +0200 +@@ -1,6 +1,6 @@ + /* Common subexpression elimination library for GNU compiler. + Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, +- 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008 ++ 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + Free Software Foundation, Inc. + + This file is part of GCC. +@@ -1483,7 +1483,7 @@ cselib_invalidate_mem (rtx mem_rtx) + } + if (num_mems < PARAM_VALUE (PARAM_MAX_CSELIB_MEMORY_LOCATIONS) + && ! canon_true_dependence (mem_rtx, GET_MODE (mem_rtx), mem_addr, +- x, cselib_rtx_varies_p)) ++ x, NULL_RTX, cselib_rtx_varies_p)) + { + has_mem = true; + num_mems++; +--- gcc/gcse.c.jj 2009-03-28 18:11:42.000000000 +0100 ++++ gcc/gcse.c 2009-04-21 11:19:20.000000000 +0200 +@@ -1,7 +1,7 @@ + /* Global common subexpression elimination/Partial redundancy elimination + and global constant/copy propagation for GNU compiler. + Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, +- 2006, 2007, 2008 Free Software Foundation, Inc. ++ 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + + This file is part of GCC. + +@@ -2516,7 +2516,7 @@ compute_transp (const_rtx x, int indx, s + dest_addr = XEXP (list_entry, 0); + + if (canon_true_dependence (dest, GET_MODE (dest), dest_addr, +- x, rtx_addr_varies_p)) ++ x, NULL_RTX, rtx_addr_varies_p)) + { + if (set_p) + SET_BIT (bmap[bb_index], indx); +--- gcc/testsuite/gcc.dg/pr39794.c.jj 2009-04-21 13:08:45.000000000 +0200 ++++ gcc/testsuite/gcc.dg/pr39794.c 2009-04-21 13:07:29.000000000 +0200 +@@ -0,0 +1,33 @@ ++/* PR middle-end/39794 */ ++/* { dg-do run } */ ++/* { dg-options "-O2 -funroll-loops" } */ ++ ++extern void abort (); ++ ++void ++foo (int *a, int n) ++{ ++ int i; ++ for (i = 0; i < n; i++) ++ { ++ a[i] *= 2; ++ a[i + 1] = a[i - 1] + a[i - 2]; ++ } ++} ++ ++int a[16]; ++int ref[16] = { 0, 1, 4, 2, 10, 12, 24, 44, ++ 72, 136, 232, 416, 736, 1296, 2304, 2032 }; ++ ++int ++main () ++{ ++ int i; ++ for (i = 0; i < 16; i++) ++ a[i] = i; ++ foo (a + 2, 16 - 3); ++ for (i = 0; i < 16; i++) ++ if (ref[i] != a[i]) ++ abort (); ++ return 0; ++} diff --git a/gcc44-rh459374-1.patch b/gcc44-rh459374-1.patch new file mode 100644 index 0000000..f736bdc --- /dev/null +++ b/gcc44-rh459374-1.patch @@ -0,0 +1,239 @@ +2009-04-08 Jakub Jelinek + + * tree.h (DECL_BY_REFERENCE): Note that it is also valid for + !TREE_STATIC VAR_DECLs. + * dwarf2out.c (loc_by_reference, gen_decl_die): Handle + DECL_BY_REFERENCE on !TREE_STATIC VAR_DECLs. + (gen_variable_die): Likewise. Don't look at TREE_PRIVATE if + DECL_BY_REFERENCE is valid. + * dbxout.c (DECL_ACCESSIBILITY_CHAR): Don't look at TREE_PRIVATE + for PARM_DECLs, RESULT_DECLs or !TREE_STATIC VAR_DECLs. + * tree-nested.c (get_nonlocal_debug_decl, get_local_debug_decl): + Copy DECL_BY_REFERENCE. + (struct nesting_copy_body_data): New type. + (nesting_copy_decl): New function. + (finalize_nesting_tree_1): Remap types of debug_var_chain variables, + if they have variable length. + +--- gcc/dwarf2out.c.jj 2009-04-07 08:32:56.000000000 +0200 ++++ gcc/dwarf2out.c 2009-04-08 11:10:16.000000000 +0200 +@@ -11709,7 +11709,9 @@ loc_by_reference (dw_loc_descr_ref loc, + if (loc == NULL) + return NULL; + +- if ((TREE_CODE (decl) != PARM_DECL && TREE_CODE (decl) != RESULT_DECL) ++ if ((TREE_CODE (decl) != PARM_DECL ++ && TREE_CODE (decl) != RESULT_DECL ++ && (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl))) + || !DECL_BY_REFERENCE (decl)) + return loc; + +@@ -14047,12 +14049,19 @@ gen_variable_die (tree decl, tree origin + else + { + tree type = TREE_TYPE (decl); ++ bool private_flag_valid = true; + + add_name_and_src_coords_attributes (var_die, decl); + if ((TREE_CODE (decl) == PARM_DECL +- || TREE_CODE (decl) == RESULT_DECL) ++ || TREE_CODE (decl) == RESULT_DECL ++ || (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))) + && DECL_BY_REFERENCE (decl)) +- add_type_attribute (var_die, TREE_TYPE (type), 0, 0, context_die); ++ { ++ add_type_attribute (var_die, TREE_TYPE (type), 0, 0, context_die); ++ /* DECL_BY_REFERENCE uses the same bit as TREE_PRIVATE, ++ for PARM_DECL, RESULT_DECL or non-static VAR_DECL. */ ++ private_flag_valid = false; ++ } + else + add_type_attribute (var_die, type, TREE_READONLY (decl), + TREE_THIS_VOLATILE (decl), context_die); +@@ -14065,7 +14074,7 @@ gen_variable_die (tree decl, tree origin + + if (TREE_PROTECTED (decl)) + add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_protected); +- else if (TREE_PRIVATE (decl)) ++ else if (private_flag_valid && TREE_PRIVATE (decl)) + add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_private); + } + +@@ -15298,7 +15307,9 @@ gen_decl_die (tree decl, tree origin, dw + + /* Output any DIEs that are needed to specify the type of this data + object. */ +- if (TREE_CODE (decl_or_origin) == RESULT_DECL ++ if ((TREE_CODE (decl_or_origin) == RESULT_DECL ++ || (TREE_CODE (decl_or_origin) == VAR_DECL ++ && !TREE_STATIC (decl_or_origin))) + && DECL_BY_REFERENCE (decl_or_origin)) + gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die); + else +--- gcc/tree.h.jj 2009-04-06 11:48:32.000000000 +0200 ++++ gcc/tree.h 2009-04-07 17:16:28.000000000 +0200 +@@ -478,7 +478,7 @@ struct tree_common GTY(()) + CALL_EXPR + + DECL_BY_REFERENCE in +- PARM_DECL, RESULT_DECL ++ PARM_DECL, RESULT_DECL, VAR_DECL (only !TREE_STATIC) + + OMP_SECTION_LAST in + OMP_SECTION +@@ -1291,8 +1291,9 @@ extern void omp_clause_range_check_faile + #define CALL_EXPR_RETURN_SLOT_OPT(NODE) \ + (CALL_EXPR_CHECK (NODE)->base.private_flag) + +-/* In a RESULT_DECL or PARM_DECL, means that it is passed by invisible +- reference (and the TREE_TYPE is a pointer to the true type). */ ++/* In a RESULT_DECL, PARM_DECL or VAR_DECL without TREE_STATIC, means that it is ++ passed by invisible reference (and the TREE_TYPE is a pointer to the true ++ type). */ + #define DECL_BY_REFERENCE(NODE) (DECL_COMMON_CHECK (NODE)->base.private_flag) + + /* In a CALL_EXPR, means that the call is the jump from a thunk to the +--- gcc/tree-nested.c.jj 2009-04-06 11:47:30.000000000 +0200 ++++ gcc/tree-nested.c 2009-04-08 09:50:55.000000000 +0200 +@@ -827,6 +827,11 @@ get_nonlocal_debug_decl (struct nesting_ + TREE_READONLY (new_decl) = TREE_READONLY (decl); + TREE_ADDRESSABLE (new_decl) = TREE_ADDRESSABLE (decl); + DECL_SEEN_IN_BIND_EXPR_P (new_decl) = 1; ++ if ((TREE_CODE (decl) == PARM_DECL ++ || TREE_CODE (decl) == RESULT_DECL ++ || TREE_CODE (decl) == VAR_DECL) ++ && DECL_BY_REFERENCE (decl)) ++ DECL_BY_REFERENCE (new_decl) = 1; + + SET_DECL_VALUE_EXPR (new_decl, x); + DECL_HAS_VALUE_EXPR_P (new_decl) = 1; +@@ -1240,6 +1245,11 @@ get_local_debug_decl (struct nesting_inf + TREE_READONLY (new_decl) = TREE_READONLY (decl); + TREE_ADDRESSABLE (new_decl) = TREE_ADDRESSABLE (decl); + DECL_SEEN_IN_BIND_EXPR_P (new_decl) = 1; ++ if ((TREE_CODE (decl) == PARM_DECL ++ || TREE_CODE (decl) == RESULT_DECL ++ || TREE_CODE (decl) == VAR_DECL) ++ && DECL_BY_REFERENCE (decl)) ++ DECL_BY_REFERENCE (new_decl) = 1; + + SET_DECL_VALUE_EXPR (new_decl, x); + DECL_HAS_VALUE_EXPR_P (new_decl) = 1; +@@ -1944,6 +1954,34 @@ convert_all_function_calls (struct nesti + while (root); + } + ++struct nesting_copy_body_data ++{ ++ copy_body_data cb; ++ struct nesting_info *root; ++}; ++ ++/* A helper subroutine for debug_var_chain type remapping. */ ++ ++static tree ++nesting_copy_decl (tree decl, copy_body_data *id) ++{ ++ struct nesting_copy_body_data *nid = (struct nesting_copy_body_data *) id; ++ void **slot = pointer_map_contains (nid->root->var_map, decl); ++ ++ if (slot) ++ return (tree) *slot; ++ ++ if (TREE_CODE (decl) == TYPE_DECL && DECL_ORIGINAL_TYPE (decl)) ++ { ++ tree new_decl = copy_decl_no_change (decl, id); ++ DECL_ORIGINAL_TYPE (new_decl) ++ = remap_type (DECL_ORIGINAL_TYPE (decl), id); ++ return new_decl; ++ } ++ ++ return copy_decl_no_change (decl, id); ++} ++ + /* Do "everything else" to clean up or complete state collected by the + various walking passes -- lay out the types and decls, generate code + to initialize the frame decl, store critical expressions in the +@@ -2076,10 +2114,66 @@ finalize_nesting_tree_1 (struct nesting_ + declare_vars (root->new_local_var_chain, + gimple_seq_first_stmt (gimple_body (root->context)), + false); ++ + if (root->debug_var_chain) +- declare_vars (root->debug_var_chain, +- gimple_seq_first_stmt (gimple_body (root->context)), +- true); ++ { ++ tree debug_var; ++ ++ for (debug_var = root->debug_var_chain; debug_var; ++ debug_var = TREE_CHAIN (debug_var)) ++ if (variably_modified_type_p (TREE_TYPE (debug_var), NULL)) ++ break; ++ ++ /* If there are any debug decls with variable length types, ++ remap those types using other debug_var_chain variables. */ ++ if (debug_var) ++ { ++ struct nesting_copy_body_data id; ++ ++ memset (&id, 0, sizeof (id)); ++ id.cb.copy_decl = nesting_copy_decl; ++ id.cb.decl_map = pointer_map_create (); ++ id.root = root; ++ ++ for (; debug_var; debug_var = TREE_CHAIN (debug_var)) ++ if (variably_modified_type_p (TREE_TYPE (debug_var), NULL)) ++ { ++ tree type = TREE_TYPE (debug_var); ++ tree newt, t = type; ++ struct nesting_info *i; ++ ++ for (i = root; i; i = i->outer) ++ if (variably_modified_type_p (type, i->context)) ++ break; ++ ++ if (i == NULL) ++ continue; ++ ++ id.cb.src_fn = i->context; ++ id.cb.dst_fn = i->context; ++ id.cb.src_cfun = DECL_STRUCT_FUNCTION (root->context); ++ ++ TREE_TYPE (debug_var) = newt = remap_type (type, &id.cb); ++ while (POINTER_TYPE_P (newt) && !TYPE_NAME (newt)) ++ { ++ newt = TREE_TYPE (newt); ++ t = TREE_TYPE (t); ++ } ++ if (TYPE_NAME (newt) ++ && TREE_CODE (TYPE_NAME (newt)) == TYPE_DECL ++ && DECL_ORIGINAL_TYPE (TYPE_NAME (newt)) ++ && newt != t ++ && TYPE_NAME (newt) == TYPE_NAME (t)) ++ TYPE_NAME (newt) = remap_decl (TYPE_NAME (newt), &id.cb); ++ } ++ ++ pointer_map_destroy (id.cb.decl_map); ++ } ++ ++ declare_vars (root->debug_var_chain, ++ gimple_seq_first_stmt (gimple_body (root->context)), ++ true); ++ } + + /* Dump the translated tree function. */ + dump_function (TDI_nested, root->context); +--- gcc/dbxout.c.jj 2009-04-06 11:47:29.000000000 +0200 ++++ gcc/dbxout.c 2009-04-07 17:16:27.000000000 +0200 +@@ -1397,7 +1397,9 @@ dbxout_type_index (tree type) + /* Used in several places: evaluates to '0' for a private decl, + '1' for a protected decl, '2' for a public decl. */ + #define DECL_ACCESSIBILITY_CHAR(DECL) \ +-(TREE_PRIVATE (DECL) ? '0' : TREE_PROTECTED (DECL) ? '1' : '2') ++((TREE_CODE (DECL) != PARM_DECL && TREE_CODE (DECL) != RESULT_DECL \ ++ && (TREE_CODE (DECL) != VAR_DECL || TREE_STATIC (DECL)) \ ++ && TREE_PRIVATE (DECL)) ? '0' : TREE_PROTECTED (DECL) ? '1' : '2') + + /* Subroutine of `dbxout_type'. Output the type fields of TYPE. + This must be a separate function because anonymous unions require diff --git a/gcc44-rh459374-2.patch b/gcc44-rh459374-2.patch new file mode 100644 index 0000000..d1a8c17 --- /dev/null +++ b/gcc44-rh459374-2.patch @@ -0,0 +1,175 @@ +2009-04-08 Jakub Jelinek + + * dwarf2out.c (loc_descr_plus_const): New function. + (build_cfa_aligned_loc, tls_mem_loc_descriptor, + mem_loc_descriptor, loc_descriptor_from_tree_1, + descr_info_loc, gen_variable_die): Use it. + +--- gcc/dwarf2out.c.jj 2009-04-08 11:10:16.000000000 +0200 ++++ gcc/dwarf2out.c 2009-04-08 12:52:16.000000000 +0200 +@@ -3890,6 +3890,47 @@ add_loc_descr (dw_loc_descr_ref *list_he + *d = descr; + } + ++/* Add a constant OFFSET to a location expression. */ ++ ++static void ++loc_descr_plus_const (dw_loc_descr_ref *list_head, HOST_WIDE_INT offset) ++{ ++ dw_loc_descr_ref loc; ++ HOST_WIDE_INT *p; ++ ++ gcc_assert (*list_head != NULL); ++ ++ if (!offset) ++ return; ++ ++ /* Find the end of the chain. */ ++ for (loc = *list_head; loc->dw_loc_next != NULL; loc = loc->dw_loc_next) ++ ; ++ ++ p = NULL; ++ if (loc->dw_loc_opc == DW_OP_fbreg ++ || (loc->dw_loc_opc >= DW_OP_breg0 && loc->dw_loc_opc <= DW_OP_breg31)) ++ p = &loc->dw_loc_oprnd1.v.val_int; ++ else if (loc->dw_loc_opc == DW_OP_bregx) ++ p = &loc->dw_loc_oprnd2.v.val_int; ++ ++ /* If the last operation is fbreg, breg{0..31,x}, optimize by adjusting its ++ offset. Don't optimize if an signed integer overflow would happen. */ ++ if (p != NULL ++ && ((offset > 0 && *p <= INTTYPE_MAXIMUM (HOST_WIDE_INT) - offset) ++ || (offset < 0 && *p >= INTTYPE_MINIMUM (HOST_WIDE_INT) - offset))) ++ *p += offset; ++ ++ else if (offset > 0) ++ loc->dw_loc_next = new_loc_descr (DW_OP_plus_uconst, offset, 0); ++ ++ else ++ { ++ loc->dw_loc_next = int_loc_descriptor (offset); ++ add_loc_descr (&loc->dw_loc_next, new_loc_descr (DW_OP_plus, 0, 0)); ++ } ++} ++ + /* Return the size of a location descriptor. */ + + static unsigned long +@@ -4409,9 +4450,7 @@ build_cfa_aligned_loc (HOST_WIDE_INT off + head = new_reg_loc_descr (dwarf_fp, 0); + add_loc_descr (&head, int_loc_descriptor (alignment)); + add_loc_descr (&head, new_loc_descr (DW_OP_and, 0, 0)); +- +- add_loc_descr (&head, int_loc_descriptor (offset)); +- add_loc_descr (&head, new_loc_descr (DW_OP_plus, 0, 0)); ++ loc_descr_plus_const (&head, offset); + } + else + head = new_reg_loc_descr (dwarf_fp, offset); +@@ -9913,7 +9952,7 @@ static dw_loc_descr_ref + tls_mem_loc_descriptor (rtx mem) + { + tree base; +- dw_loc_descr_ref loc_result, loc_result2; ++ dw_loc_descr_ref loc_result; + + if (MEM_EXPR (mem) == NULL_TREE || MEM_OFFSET (mem) == NULL_RTX) + return NULL; +@@ -9929,21 +9968,7 @@ tls_mem_loc_descriptor (rtx mem) + return NULL; + + if (INTVAL (MEM_OFFSET (mem))) +- { +- if (INTVAL (MEM_OFFSET (mem)) >= 0) +- add_loc_descr (&loc_result, +- new_loc_descr (DW_OP_plus_uconst, +- INTVAL (MEM_OFFSET (mem)), 0)); +- else +- { +- loc_result2 = mem_loc_descriptor (MEM_OFFSET (mem), GET_MODE (mem), +- VAR_INIT_STATUS_INITIALIZED); +- if (loc_result2 == 0) +- return NULL; +- add_loc_descr (&loc_result, loc_result2); +- add_loc_descr (&loc_result, new_loc_descr (DW_OP_plus, 0, 0)); +- } +- } ++ loc_descr_plus_const (&loc_result, INTVAL (MEM_OFFSET (mem))); + + return loc_result; + } +@@ -10108,11 +10133,8 @@ mem_loc_descriptor (rtx rtl, enum machin + if (mem_loc_result == 0) + break; + +- if (GET_CODE (XEXP (rtl, 1)) == CONST_INT +- && INTVAL (XEXP (rtl, 1)) >= 0) +- add_loc_descr (&mem_loc_result, +- new_loc_descr (DW_OP_plus_uconst, +- INTVAL (XEXP (rtl, 1)), 0)); ++ if (GET_CODE (XEXP (rtl, 1)) == CONST_INT) ++ loc_descr_plus_const (&mem_loc_result, INTVAL (XEXP (rtl, 1))); + else + { + dw_loc_descr_ref mem_loc_result2 +@@ -10526,13 +10548,7 @@ loc_descriptor_from_tree_1 (tree loc, in + } + + bytepos = bitpos / BITS_PER_UNIT; +- if (bytepos > 0) +- add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst, bytepos, 0)); +- else if (bytepos < 0) +- { +- add_loc_descr (&ret, int_loc_descriptor (bytepos)); +- add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0)); +- } ++ loc_descr_plus_const (&ret, bytepos); + + have_address = 1; + break; +@@ -10616,11 +10632,7 @@ loc_descriptor_from_tree_1 (tree loc, in + if (ret == 0) + return 0; + +- add_loc_descr (&ret, +- new_loc_descr (DW_OP_plus_uconst, +- tree_low_cst (TREE_OPERAND (loc, 1), +- 0), +- 0)); ++ loc_descr_plus_const (&ret, tree_low_cst (TREE_OPERAND (loc, 1), 0)); + break; + } + +@@ -13001,10 +13013,7 @@ descr_info_loc (tree val, tree base_decl + loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl); + if (!loc) + break; +- add_loc_descr (&loc, +- new_loc_descr (DW_OP_plus_uconst, +- tree_low_cst (TREE_OPERAND (val, 1), +- 1), 0)); ++ loc_descr_plus_const (&loc, tree_low_cst (TREE_OPERAND (val, 1), 0)); + } + else + { +@@ -13920,9 +13929,7 @@ gen_variable_die (tree decl, tree origin + loc->dw_loc_oprnd1.v.val_addr + = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off); + else +- add_loc_descr (&loc, +- new_loc_descr (DW_OP_plus_uconst, +- off, 0)); ++ loc_descr_plus_const (&loc, off); + } + add_AT_loc (var_die, DW_AT_location, loc); + remove_AT (var_die, DW_AT_declaration); +@@ -13985,8 +13992,7 @@ gen_variable_die (tree decl, tree origin + loc->dw_loc_oprnd1.v.val_addr + = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off); + else +- add_loc_descr (&loc, new_loc_descr (DW_OP_plus_uconst, +- off, 0)); ++ loc_descr_plus_const (&loc, off); + } + add_AT_loc (var_die, DW_AT_location, loc); + } diff --git a/gcc44-rh459374-3.patch b/gcc44-rh459374-3.patch new file mode 100644 index 0000000..3ad7c25 --- /dev/null +++ b/gcc44-rh459374-3.patch @@ -0,0 +1,468 @@ +2009-04-22 Jakub Jelinek + + * tree-nested.c (get_nonlocal_vla_type): If not optimizing, call + note_nonlocal_vla_type for nonlocal VLAs. + (note_nonlocal_vla_type, note_nonlocal_block_vlas, + contains_remapped_vars, remap_vla_decls): New functions. + (convert_nonlocal_reference_stmt): If not optimizing, call + note_nonlocal_block_vlas on GIMPLE_BIND block vars. + (nesting_copy_decl): Return {VAR,PARM,RESULT}_DECL unmodified + if it wasn't found in var_map. + (finalize_nesting_tree_1): Call remap_vla_decls. If outermost + GIMPLE_BIND doesn't have gimple_bind_block, chain debug_var_chain + to BLOCK_VARS (DECL_INITIAL (root->context)) instead of calling + declare_vars. + * gimplify.c (nonlocal_vlas): New variable. + (gimplify_var_or_parm_decl): Add debug VAR_DECLs for non-local + referenced VLAs. + (gimplify_body): Create and destroy nonlocal_vlas. + + * trans-decl.c: Include pointer-set.h. + (nonlocal_dummy_decl_pset, tree nonlocal_dummy_decls): New variables. + (gfc_nonlocal_dummy_array_decl): New function. + (gfc_get_symbol_decl): Call it for non-local dummy args with saved + descriptor. + (gfc_get_symbol_decl): Set DECL_BY_REFERENCE when needed. + (gfc_generate_function_code): Initialize nonlocal_dummy_decl{s,_pset}, + chain it to outermost block's vars, destroy it afterwards. + + * Make-lang.in (trans-decl.o): Depend on pointer-set.h. + +--- gcc/tree-nested.c.jj 2009-04-21 19:24:25.000000000 +0200 ++++ gcc/tree-nested.c 2009-04-22 10:18:38.000000000 +0200 +@@ -770,6 +770,7 @@ get_frame_field (struct nesting_info *in + return x; + } + ++static void note_nonlocal_vla_type (struct nesting_info *info, tree type); + + /* A subroutine of convert_nonlocal_reference_op. Create a local variable + in the nested function with DECL_VALUE_EXPR set to reference the true +@@ -840,6 +841,11 @@ get_nonlocal_debug_decl (struct nesting_ + TREE_CHAIN (new_decl) = info->debug_var_chain; + info->debug_var_chain = new_decl; + ++ if (!optimize ++ && info->context != target_context ++ && variably_modified_type_p (TREE_TYPE (decl), NULL)) ++ note_nonlocal_vla_type (info, TREE_TYPE (decl)); ++ + return new_decl; + } + +@@ -1111,6 +1117,60 @@ convert_nonlocal_omp_clauses (tree *pcla + return need_chain; + } + ++/* Create nonlocal debug decls for nonlocal VLA array bounds. */ ++ ++static void ++note_nonlocal_vla_type (struct nesting_info *info, tree type) ++{ ++ while (POINTER_TYPE_P (type) && !TYPE_NAME (type)) ++ type = TREE_TYPE (type); ++ ++ if (TYPE_NAME (type) ++ && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL ++ && DECL_ORIGINAL_TYPE (TYPE_NAME (type))) ++ type = DECL_ORIGINAL_TYPE (TYPE_NAME (type)); ++ ++ while (POINTER_TYPE_P (type) ++ || TREE_CODE (type) == VECTOR_TYPE ++ || TREE_CODE (type) == FUNCTION_TYPE ++ || TREE_CODE (type) == METHOD_TYPE) ++ type = TREE_TYPE (type); ++ ++ if (TREE_CODE (type) == ARRAY_TYPE) ++ { ++ tree domain, t; ++ ++ note_nonlocal_vla_type (info, TREE_TYPE (type)); ++ domain = TYPE_DOMAIN (type); ++ if (domain) ++ { ++ t = TYPE_MIN_VALUE (domain); ++ if (t && (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL) ++ && decl_function_context (t) != info->context) ++ get_nonlocal_debug_decl (info, t); ++ t = TYPE_MAX_VALUE (domain); ++ if (t && (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL) ++ && decl_function_context (t) != info->context) ++ get_nonlocal_debug_decl (info, t); ++ } ++ } ++} ++ ++/* Create nonlocal debug decls for nonlocal VLA array bounds for VLAs ++ in BLOCK. */ ++ ++static void ++note_nonlocal_block_vlas (struct nesting_info *info, tree block) ++{ ++ tree var; ++ ++ for (var = BLOCK_VARS (block); var; var = TREE_CHAIN (var)) ++ if (TREE_CODE (var) == VAR_DECL ++ && variably_modified_type_p (TREE_TYPE (var), NULL) ++ && DECL_HAS_VALUE_EXPR_P (var) ++ && decl_function_context (var) != info->context) ++ note_nonlocal_vla_type (info, TREE_TYPE (var)); ++} + + /* Callback for walk_gimple_stmt. Rewrite all references to VAR and + PARM_DECLs that belong to outer functions. This handles statements +@@ -1202,6 +1262,13 @@ convert_nonlocal_reference_stmt (gimple_ + info, gimple_omp_body (stmt)); + break; + ++ case GIMPLE_BIND: ++ if (!optimize && gimple_bind_block (stmt)) ++ note_nonlocal_block_vlas (info, gimple_bind_block (stmt)); ++ ++ *handled_ops_p = false; ++ return NULL_TREE; ++ + default: + /* For every other statement that we are not interested in + handling here, let the walker traverse the operands. */ +@@ -1979,9 +2046,117 @@ nesting_copy_decl (tree decl, copy_body_ + return new_decl; + } + ++ if (TREE_CODE (decl) == VAR_DECL ++ || TREE_CODE (decl) == PARM_DECL ++ || TREE_CODE (decl) == RESULT_DECL) ++ return decl; ++ + return copy_decl_no_change (decl, id); + } + ++/* A helper function for remap_vla_decls. See if *TP contains ++ some remapped variables. */ ++ ++static tree ++contains_remapped_vars (tree *tp, int *walk_subtrees, void *data) ++{ ++ struct nesting_info *root = (struct nesting_info *) data; ++ tree t = *tp; ++ void **slot; ++ ++ if (DECL_P (t)) ++ { ++ *walk_subtrees = 0; ++ slot = pointer_map_contains (root->var_map, t); ++ ++ if (slot) ++ return (tree) *slot; ++ } ++ return NULL; ++} ++ ++/* Remap VLA decls in BLOCK and subblocks if remapped variables are ++ involved. */ ++ ++static void ++remap_vla_decls (tree block, struct nesting_info *root) ++{ ++ tree var, subblock, val, type; ++ struct nesting_copy_body_data id; ++ ++ for (subblock = BLOCK_SUBBLOCKS (block); ++ subblock; ++ subblock = BLOCK_CHAIN (subblock)) ++ remap_vla_decls (subblock, root); ++ ++ for (var = BLOCK_VARS (block); var; var = TREE_CHAIN (var)) ++ { ++ if (TREE_CODE (var) == VAR_DECL ++ && variably_modified_type_p (TREE_TYPE (var), NULL) ++ && DECL_HAS_VALUE_EXPR_P (var)) ++ { ++ type = TREE_TYPE (var); ++ val = DECL_VALUE_EXPR (var); ++ if (walk_tree (&type, contains_remapped_vars, root, NULL) != NULL ++ || walk_tree (&val, contains_remapped_vars, root, NULL) != NULL) ++ break; ++ } ++ } ++ if (var == NULL_TREE) ++ return; ++ ++ memset (&id, 0, sizeof (id)); ++ id.cb.copy_decl = nesting_copy_decl; ++ id.cb.decl_map = pointer_map_create (); ++ id.root = root; ++ ++ for (; var; var = TREE_CHAIN (var)) ++ if (TREE_CODE (var) == VAR_DECL ++ && variably_modified_type_p (TREE_TYPE (var), NULL) ++ && DECL_HAS_VALUE_EXPR_P (var)) ++ { ++ struct nesting_info *i; ++ tree newt, t, context; ++ ++ t = type = TREE_TYPE (var); ++ val = DECL_VALUE_EXPR (var); ++ if (walk_tree (&type, contains_remapped_vars, root, NULL) == NULL ++ && walk_tree (&val, contains_remapped_vars, root, NULL) == NULL) ++ continue; ++ ++ context = decl_function_context (var); ++ for (i = root; i; i = i->outer) ++ if (i->context == context) ++ break; ++ ++ if (i == NULL) ++ continue; ++ ++ id.cb.src_fn = i->context; ++ id.cb.dst_fn = i->context; ++ id.cb.src_cfun = DECL_STRUCT_FUNCTION (root->context); ++ ++ TREE_TYPE (var) = newt = remap_type (type, &id.cb); ++ while (POINTER_TYPE_P (newt) && !TYPE_NAME (newt)) ++ { ++ newt = TREE_TYPE (newt); ++ t = TREE_TYPE (t); ++ } ++ if (TYPE_NAME (newt) ++ && TREE_CODE (TYPE_NAME (newt)) == TYPE_DECL ++ && DECL_ORIGINAL_TYPE (TYPE_NAME (newt)) ++ && newt != t ++ && TYPE_NAME (newt) == TYPE_NAME (t)) ++ TYPE_NAME (newt) = remap_decl (TYPE_NAME (newt), &id.cb); ++ ++ walk_tree (&val, copy_tree_body_r, &id.cb, NULL); ++ if (val != DECL_VALUE_EXPR (var)) ++ SET_DECL_VALUE_EXPR (var, val); ++ } ++ ++ pointer_map_destroy (id.cb.decl_map); ++} ++ + /* Do "everything else" to clean up or complete state collected by the + various walking passes -- lay out the types and decls, generate code + to initialize the frame decl, store critical expressions in the +@@ -2118,6 +2293,9 @@ finalize_nesting_tree_1 (struct nesting_ + if (root->debug_var_chain) + { + tree debug_var; ++ gimple scope; ++ ++ remap_vla_decls (DECL_INITIAL (root->context), root); + + for (debug_var = root->debug_var_chain; debug_var; + debug_var = TREE_CHAIN (debug_var)) +@@ -2170,9 +2348,13 @@ finalize_nesting_tree_1 (struct nesting_ + pointer_map_destroy (id.cb.decl_map); + } + +- declare_vars (root->debug_var_chain, +- gimple_seq_first_stmt (gimple_body (root->context)), +- true); ++ scope = gimple_seq_first_stmt (gimple_body (root->context)); ++ if (gimple_bind_block (scope)) ++ declare_vars (root->debug_var_chain, scope, true); ++ else ++ BLOCK_VARS (DECL_INITIAL (root->context)) ++ = chainon (BLOCK_VARS (DECL_INITIAL (root->context)), ++ root->debug_var_chain); + } + + /* Dump the translated tree function. */ +--- gcc/gimplify.c.jj 2009-04-21 19:23:29.000000000 +0200 ++++ gcc/gimplify.c 2009-04-22 00:20:41.000000000 +0200 +@@ -1851,6 +1851,9 @@ gimplify_conversion (tree *expr_p) + return GS_OK; + } + ++/* Nonlocal VLAs seen in the current function. */ ++static struct pointer_set_t *nonlocal_vlas; ++ + /* Gimplify a VAR_DECL or PARM_DECL. Returns GS_OK if we expanded a + DECL_VALUE_EXPR, and it's worth re-examining things. */ + +@@ -1881,7 +1884,36 @@ gimplify_var_or_parm_decl (tree *expr_p) + /* If the decl is an alias for another expression, substitute it now. */ + if (DECL_HAS_VALUE_EXPR_P (decl)) + { +- *expr_p = unshare_expr (DECL_VALUE_EXPR (decl)); ++ tree value_expr = DECL_VALUE_EXPR (decl); ++ ++ /* For referenced nonlocal VLAs add a decl for debugging purposes ++ to the current function. */ ++ if (TREE_CODE (decl) == VAR_DECL ++ && TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST ++ && nonlocal_vlas != NULL ++ && TREE_CODE (value_expr) == INDIRECT_REF ++ && TREE_CODE (TREE_OPERAND (value_expr, 0)) == VAR_DECL ++ && decl_function_context (decl) != current_function_decl) ++ { ++ struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp; ++ while (ctx && ctx->region_type == ORT_WORKSHARE) ++ ctx = ctx->outer_context; ++ if (!ctx && !pointer_set_insert (nonlocal_vlas, decl)) ++ { ++ tree copy = copy_node (decl), block; ++ ++ lang_hooks.dup_lang_specific_decl (copy); ++ SET_DECL_RTL (copy, NULL_RTX); ++ TREE_USED (copy) = 1; ++ block = DECL_INITIAL (current_function_decl); ++ TREE_CHAIN (copy) = BLOCK_VARS (block); ++ BLOCK_VARS (block) = copy; ++ SET_DECL_VALUE_EXPR (copy, unshare_expr (value_expr)); ++ DECL_HAS_VALUE_EXPR_P (copy) = 1; ++ } ++ } ++ ++ *expr_p = unshare_expr (value_expr); + return GS_OK; + } + +@@ -7359,6 +7391,9 @@ gimplify_body (tree *body_p, tree fndecl + unshare_body (body_p, fndecl); + unvisit_body (body_p, fndecl); + ++ if (cgraph_node (fndecl)->origin) ++ nonlocal_vlas = pointer_set_create (); ++ + /* Make sure input_location isn't set to something weird. */ + input_location = DECL_SOURCE_LOCATION (fndecl); + +@@ -7394,6 +7429,12 @@ gimplify_body (tree *body_p, tree fndecl + gimple_bind_set_body (outer_bind, parm_stmts); + } + ++ if (nonlocal_vlas) ++ { ++ pointer_set_destroy (nonlocal_vlas); ++ nonlocal_vlas = NULL; ++ } ++ + pop_gimplify_context (outer_bind); + gcc_assert (gimplify_ctxp == NULL); + +--- gcc/fortran/Make-lang.in.jj 2008-12-11 13:30:28.000000000 +0100 ++++ gcc/fortran/Make-lang.in 2009-04-21 19:26:35.000000000 +0200 +@@ -319,7 +319,7 @@ fortran/convert.o: $(GFORTRAN_TRANS_DEPS + fortran/trans.o: $(GFORTRAN_TRANS_DEPS) tree-iterator.h + fortran/trans-decl.o: $(GFORTRAN_TRANS_DEPS) gt-fortran-trans-decl.h \ + $(CGRAPH_H) $(TARGET_H) $(FUNCTION_H) $(FLAGS_H) $(RTL_H) $(GIMPLE_H) \ +- $(TREE_DUMP_H) debug.h ++ $(TREE_DUMP_H) debug.h pointer-set.h + fortran/trans-types.o: $(GFORTRAN_TRANS_DEPS) gt-fortran-trans-types.h \ + $(REAL_H) toplev.h $(TARGET_H) $(FLAGS_H) dwarf2out.h + fortran/trans-const.o: $(GFORTRAN_TRANS_DEPS) +--- gcc/fortran/trans-decl.c.jj 2009-04-14 10:18:29.000000000 +0200 ++++ gcc/fortran/trans-decl.c 2009-04-21 19:26:35.000000000 +0200 +@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. + #include "cgraph.h" + #include "debug.h" + #include "gfortran.h" ++#include "pointer-set.h" + #include "trans.h" + #include "trans-types.h" + #include "trans-array.h" +@@ -60,6 +61,8 @@ static GTY(()) tree current_function_ret + static GTY(()) tree saved_function_decls; + static GTY(()) tree saved_parent_function_decls; + ++static struct pointer_set_t *nonlocal_dummy_decl_pset; ++static GTY(()) tree nonlocal_dummy_decls; + + /* The namespace of the module we're currently generating. Only used while + outputting decls for module variables. Do not rely on this being set. */ +@@ -870,6 +873,38 @@ gfc_build_dummy_array_decl (gfc_symbol * + return decl; + } + ++/* For symbol SYM with GFC_DECL_SAVED_DESCRIPTOR used in contained ++ function add a VAR_DECL to the current function with DECL_VALUE_EXPR ++ pointing to the artificial variable for debug info purposes. */ ++ ++static void ++gfc_nonlocal_dummy_array_decl (gfc_symbol *sym) ++{ ++ tree decl, dummy; ++ ++ if (! nonlocal_dummy_decl_pset) ++ nonlocal_dummy_decl_pset = pointer_set_create (); ++ ++ if (pointer_set_insert (nonlocal_dummy_decl_pset, sym->backend_decl)) ++ return; ++ ++ dummy = GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl); ++ decl = build_decl (VAR_DECL, DECL_NAME (dummy), ++ TREE_TYPE (sym->backend_decl)); ++ DECL_ARTIFICIAL (decl) = 0; ++ TREE_USED (decl) = 1; ++ TREE_PUBLIC (decl) = 0; ++ TREE_STATIC (decl) = 0; ++ DECL_EXTERNAL (decl) = 0; ++ if (DECL_BY_REFERENCE (dummy)) ++ DECL_BY_REFERENCE (decl) = 1; ++ DECL_LANG_SPECIFIC (decl) = DECL_LANG_SPECIFIC (sym->backend_decl); ++ SET_DECL_VALUE_EXPR (decl, sym->backend_decl); ++ DECL_HAS_VALUE_EXPR_P (decl) = 1; ++ DECL_CONTEXT (decl) = DECL_CONTEXT (sym->backend_decl); ++ TREE_CHAIN (decl) = nonlocal_dummy_decls; ++ nonlocal_dummy_decls = decl; ++} + + /* Return a constant or a variable to use as a string length. Does not + add the decl to the current scope. */ +@@ -1010,6 +1045,13 @@ gfc_get_symbol_decl (gfc_symbol * sym) + { + gfc_add_assign_aux_vars (sym); + } ++ ++ if (sym->attr.dimension ++ && DECL_LANG_SPECIFIC (sym->backend_decl) ++ && GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl) ++ && DECL_CONTEXT (sym->backend_decl) != current_function_decl) ++ gfc_nonlocal_dummy_array_decl (sym); ++ + return sym->backend_decl; + } + +@@ -1129,6 +1171,13 @@ gfc_get_symbol_decl (gfc_symbol * sym) + sym->attr.pointer || sym->attr.allocatable); + } + ++ if (!TREE_STATIC (decl) ++ && POINTER_TYPE_P (TREE_TYPE (decl)) ++ && !sym->attr.pointer ++ && !sym->attr.allocatable ++ && !sym->attr.proc_pointer) ++ DECL_BY_REFERENCE (decl) = 1; ++ + return decl; + } + +@@ -3852,6 +3901,9 @@ gfc_generate_function_code (gfc_namespac + + gfc_generate_contained_functions (ns); + ++ nonlocal_dummy_decls = NULL; ++ nonlocal_dummy_decl_pset = NULL; ++ + generate_local_vars (ns); + + /* Keep the parent fake result declaration in module functions +@@ -4111,6 +4163,15 @@ gfc_generate_function_code (gfc_namespac + = build3_v (BIND_EXPR, decl, DECL_SAVED_TREE (fndecl), + DECL_INITIAL (fndecl)); + ++ if (nonlocal_dummy_decls) ++ { ++ BLOCK_VARS (DECL_INITIAL (fndecl)) ++ = chainon (BLOCK_VARS (DECL_INITIAL (fndecl)), nonlocal_dummy_decls); ++ pointer_set_destroy (nonlocal_dummy_decl_pset); ++ nonlocal_dummy_decls = NULL; ++ nonlocal_dummy_decl_pset = NULL; ++ } ++ + /* Output the GENERIC tree. */ + dump_function (TDI_original, fndecl); + diff --git a/sources b/sources index c79572f..45e01e6 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 2659f09c2e43ef8b7d4406321753f1b2 fastjar-0.97.tar.gz -1e900acdd986c1a3971169e89f70ce94 gcc-4.4.0-20090420.tar.bz2 +095942097cf529c8064c51f07b8fc0b7 gcc-4.4.0-20090422.tar.bz2