shithub: mc

Download patch

ref: a07a52d75ed87ab92e5985f553a41d8bbff11d24
parent: 5c5b656a306888ea563f10c911e362a0632e7112
author: Ori Bernstein <ori@eigenstate.org>
date: Mon Jul 13 19:21:09 EDT 2015

Correctly deduplicate types.

--- a/parse/type.c
+++ b/parse/type.c
@@ -678,21 +678,14 @@
     return hash;
 }
 
-int tyeq(void *t1, void *t2)
+int tyeq_rec(Type *a, Type *b, Bitset *visited)
 {
-    Type *a, *b;
     size_t i;
 
-    a = (Type *)t1;
-    b = (Type *)t2;
-    if (a == b)
-        return 1;
     if (!a || !b)
         return 0;
     if (a->type != b->type)
         return 0;
-    if (a->tid == b->tid)
-        return 1;
     if (a->narg != b->narg)
         return 0;
     if (a->nsub != b->nsub)
@@ -699,6 +692,17 @@
         return 0;
     if (a->nmemb != b->nmemb)
         return 0;
+
+    if (a == b)
+        return 1;
+    if (a->tid == b->tid)
+        return 1;
+    if (bshas(visited, a->tid) || bshas(visited, b->tid))
+        return 1;
+
+    bsput(visited, a->tid);
+    bsput(visited, b->tid);
+
     switch (a->type) {
         case Typaram:
             return streq(a->pname, b->pname);
@@ -714,7 +718,7 @@
             for (i = 0; i < a->nmemb; i++) {
                 if (!nameeq(a->udecls[i]->name, b->udecls[i]->name))
                     return 0;
-                if (!tyeq(a->udecls[i]->etype, b->udecls[i]->etype))
+                if (!tyeq_rec(a->udecls[i]->etype, b->udecls[i]->etype, visited))
                     return 0;
             }
             break;
@@ -722,7 +726,7 @@
             for (i = 0; i < a->nmemb; i++) {
                 if (strcmp(declname(a->sdecls[i]), declname(b->sdecls[i])) != 0)
                     return 0;
-                if (!tyeq(decltype(a->sdecls[i]), decltype(b->sdecls[i])))
+                if (!tyeq_rec(decltype(a->sdecls[i]), decltype(b->sdecls[i]), visited))
                     return 0;
             }
             break;
@@ -730,10 +734,10 @@
             if (!nameeq(a->name, b->name))
                 return 0;
             for (i = 0; i < a->narg; i++)
-                if (!tyeq(a->arg[i], b->arg[i]))
+                if (!tyeq_rec(a->arg[i], b->arg[i], visited))
                     return 0;
             for (i = 0; i < a->nsub; i++)
-                if (!tyeq(a->sub[i], b->sub[i]))
+                if (!tyeq_rec(a->sub[i], b->sub[i], visited))
                     return 0;
             break;
         case Tyarray:
@@ -744,9 +748,20 @@
             break;
     }
     for (i = 0; i < a->nsub; i++)
-        if (!tyeq(a->sub[i], b->sub[i]))
+        if (!tyeq_rec(a->sub[i], b->sub[i], visited))
             return 0;
     return 1;
+}
+
+int tyeq(void *a, void *b)
+{
+    Bitset *bs;
+    int eq;
+
+    bs = mkbs();
+    eq = tyeq_rec(a, b, bs);
+    bsfree(bs);
+    return eq;
 }
 
 size_t tyidfmt(char *buf, size_t sz, Type *ty)
--- a/parse/use.c
+++ b/parse/use.c
@@ -726,6 +726,7 @@
     size_t i;
     Type *t, *old;
 
+
     /*
      * merge duplicate definitions.
      * This allows us to compare named types by id, instead
@@ -736,11 +737,23 @@
         t = htget(tidmap, itop(typefixid[i]));
         if (!t)
             die("Unable to find type for id %zd\n", typefixid[i]);
-        if ((t->type == Tyname || t->type == Tygeneric) && !t->issynth) {
-            t = htget(tydedup, t);
-        }
         *typefixdest[i] = t;
     }
+    for (i = 0; i < ntypefixdest; i++) {
+        old = *typefixdest[i];
+        if (old->type == Tyname || old->type == Tygeneric) {
+            t = htget(tydedup, old);
+            if (!t) {
+                t = old;
+                htput(tydedup, old, old);
+            } else {
+                if (strcmp(tystr(old), tystr(t)))
+                    printf("deduping %s -> %s\n", tystr(old), tystr(t));
+            }
+            *typefixdest[i] = t;
+        }
+    }
+
     /* check for duplicate type definitions */
     for (i = 0; i < ntypefixdest; i++) {
         t = htget(tidmap, itop(typefixid[i]));
@@ -750,6 +763,7 @@
         if (old && !tyeq(t, old) && !isspecialization(t, old))
             lfatal(t->loc, "Duplicate definition of type %s on %s:%d", tystr(old), file->file.files[old->loc.file], old->loc.line);
     }
+    for (i = 0; i < ntypefixdest; i++) 
     lfree(&typefixdest, &ntypefixdest);
     lfree(&typefixid, &ntypefixid);
 }
@@ -779,23 +793,6 @@
     lfree(&traitfixid, &ntraitfixid);
 }
 
-ulong tdhash(void *pt)
-{
-    Type *t;
-
-    t = pt;
-    return t->type * namehash(t->name);
-}
-
-int tdeq(void *pa, void *pb)
-{
-    Type *a, *b;
-
-    a = pa;
-    b = pb;
-    return a->type == b->type && nameeq(a->name, b->name);
-}
-
 /* Usefile format:
  *     U<pkgname>
  *     T<pickled-type>
@@ -818,7 +815,7 @@
 
     pushstab(file->file.globls);
     if (!tydedup)
-        tydedup = mkht(tdhash, tdeq);
+        tydedup = mkht(tyhash, tyeq);
     if (fgetc(f) != 'U')
         return 0;
     if (rdint(f) != Abiversion) {
@@ -903,8 +900,6 @@
                         ty->ishidden = 1;
                     if (!gettype(s, ty->name) && !ty->ishidden)
                         puttype(s, ty->name, ty);
-                    if (!hthas(tydedup, ty))
-                        htput(tydedup, ty, ty);
                 } else if (ty->type == Tyunion)  {
                     for (i = 0; i < ty->nmemb; i++)
                         if (!getucon(s, ty->udecls[i]->name) && !ty->udecls[i]->synth)