aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/module.c
diff options
context:
space:
mode:
authorFrancois-Xavier Coudert <fxcoudert@gcc.gnu.org>2007-11-17 13:46:53 +0000
committerFrançois-Xavier Coudert <fxcoudert@gcc.gnu.org>2007-11-17 13:46:53 +0000
commitd61ae8dd9925ebc662f09837013e0a03bcc353f5 (patch)
tree9383b4b9e23c0e7760d26dbdec31e5cefdd849c6 /gcc/fortran/module.c
parent04901f81ae1db89496354eb88df80376bf053919 (diff)
downloadgcc-d61ae8dd9925ebc662f09837013e0a03bcc353f5.zip
gcc-d61ae8dd9925ebc662f09837013e0a03bcc353f5.tar.gz
gcc-d61ae8dd9925ebc662f09837013e0a03bcc353f5.tar.bz2
re PR fortran/30285 (gfortran excessive memory usage with COMMON blocks in modules)
PR fortran/30285 * module.c (struct written_common, written_commons): New structure. (compare_written_commons, free_written_common, write_common_0): New functions. (write_common): Call recursive function write_common_0. From-SVN: r130257
Diffstat (limited to 'gcc/fortran/module.c')
-rw-r--r--gcc/fortran/module.c116
1 files changed, 92 insertions, 24 deletions
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index a05437a..b0962e0 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -3767,51 +3767,119 @@ gfc_check_access (gfc_access specific_access, gfc_access default_access)
}
-/* Write a common block to the module. */
+/* A structure to remember which commons we've already written. */
+
+struct written_common
+{
+ BBT_HEADER(written_common);
+ const char *name, *label;
+};
+
+static struct written_common *written_commons = NULL;
+
+/* Comparison function used for balancing the binary tree. */
+
+static int
+compare_written_commons (void *a1, void *b1)
+{
+ const char *aname = ((struct written_common *) a1)->name;
+ const char *alabel = ((struct written_common *) a1)->label;
+ const char *bname = ((struct written_common *) b1)->name;
+ const char *blabel = ((struct written_common *) b1)->label;
+ int c = strcmp (aname, bname);
+
+ return (c != 0 ? c : strcmp (alabel, blabel));
+}
+
+/* Free a list of written commons. */
static void
-write_common (gfc_symtree *st)
+free_written_common (struct written_common *w)
+{
+ if (!w)
+ return;
+
+ if (w->left)
+ free_written_common (w->left);
+ if (w->right)
+ free_written_common (w->right);
+
+ gfc_free (w);
+}
+
+/* Write a common block to the module -- recursive helper function. */
+
+static void
+write_common_0 (gfc_symtree *st)
{
gfc_common_head *p;
const char * name;
int flags;
const char *label;
+ struct written_common *w;
+ bool write_me = true;
if (st == NULL)
return;
- write_common (st->left);
- write_common (st->right);
-
- mio_lparen ();
+ write_common_0 (st->left);
- /* Write the unmangled name. */
+ /* We will write out the binding label, or the name if no label given. */
name = st->n.common->name;
-
- mio_pool_string (&name);
-
p = st->n.common;
- mio_symbol_ref (&p->head);
- flags = p->saved ? 1 : 0;
- if (p->threadprivate) flags |= 2;
- mio_integer (&flags);
-
- /* Write out whether the common block is bind(c) or not. */
- mio_integer (&(p->is_bind_c));
+ label = p->is_bind_c ? p->binding_label : p->name;
- /* Write out the binding label, or the com name if no label given. */
- if (p->is_bind_c)
+ /* Check if we've already output this common. */
+ w = written_commons;
+ while (w)
{
- label = p->binding_label;
- mio_pool_string (&label);
+ int c = strcmp (name, w->name);
+ c = (c != 0 ? c : strcmp (label, w->label));
+ if (c == 0)
+ write_me = false;
+
+ w = (c < 0) ? w->left : w->right;
}
- else
+
+ if (write_me)
{
- label = p->name;
+ /* Write the common to the module. */
+ mio_lparen ();
+ mio_pool_string (&name);
+
+ mio_symbol_ref (&p->head);
+ flags = p->saved ? 1 : 0;
+ if (p->threadprivate)
+ flags |= 2;
+ mio_integer (&flags);
+
+ /* Write out whether the common block is bind(c) or not. */
+ mio_integer (&(p->is_bind_c));
+
mio_pool_string (&label);
+ mio_rparen ();
+
+ /* Record that we have written this common. */
+ w = gfc_getmem (sizeof (struct written_common));
+ w->name = p->name;
+ w->label = label;
+ gfc_insert_bbt (&written_commons, w, compare_written_commons);
}
- mio_rparen ();
+ write_common_0 (st->right);
+}
+
+
+/* Write a common, by initializing the list of written commons, calling
+ the recursive function write_common_0() and cleaning up afterwards. */
+
+static void
+write_common (gfc_symtree *st)
+{
+ written_commons = NULL;
+ write_common_0 (st);
+ free_written_common (written_commons);
+ written_commons = NULL;
}