shithub: mc

Download patch

ref: 12b9ad5cea789d9a3fc5c6e57e556877d02bff38
parent: 42e46e1b22d03c57fa8c424b46c3645e921966e0
author: Ori Bernstein <[email protected]>
date: Mon Aug 19 07:53:50 EDT 2013

Don't recurse infinitely when duplicating types.

    Now, the type subsitution map contains all types that we are
    specializing, rather than just the params.

    When we duplicate a type, we put it into the map, so that we look it up
    and return it. This prevents infinite recursion when specializing.

--- a/parse/htab.c
+++ b/parse/htab.c
@@ -200,6 +200,11 @@
 
 ulong ptrhash(void *key)
 {
+    return inthash((intptr_t)key);
+}
+
+ulong inthash(uint64_t key)
+{
     intptr_t h;
 
     h = (intptr_t) key;
@@ -209,6 +214,11 @@
     h ^= h >> 31;
     h ^= h << 31;
     return h;
+}
+
+int inteq(uint64_t a, uint64_t b)
+{
+    return a == b;
 }
 
 int ptreq(void *a, void *b)
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -299,10 +299,12 @@
 int hthas(Htab *ht, void *k);
 void **htkeys(Htab *ht, size_t *nkeys);
 /* useful key types */
-ulong strhash(void *str);
-int streq(void *s1, void *s2);
-ulong ptrhash(void *ptr);
-int ptreq(void *s1, void *s2);
+ulong strhash(void *key);
+int streq(void *a, void *b);
+ulong ptrhash(void *key);
+int ptreq(void *a, void *b);
+ulong inthash(uint64_t key);
+int inteq(uint64_t a, uint64_t b);
 
 /* util functions */
 void *zalloc(size_t size);
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -43,25 +43,27 @@
 Type *tyspecialize(Type *t, Htab *tsmap)
 {
     Type *ret;
-
     size_t i;
+
+    if (hthas(tsmap, t))
+        return htget(tsmap, t);
     switch (t->type) {
         case Typaram:
-            if (hthas(tsmap, t->pname))
-                return htget(tsmap, t->pname);
             ret = mktyvar(t->line);
-            htput(tsmap, t->pname, ret);
+            htput(tsmap, t, ret);
             break;
         case Tygeneric:
             for (i = 0; i < t->nparam; i++)
-                if (!hthas(tsmap, t->param[i]->pname))
-                    htput(tsmap, t->param[i]->pname, mktyvar(t->param[i]->line));
+                if (!hthas(tsmap, t->param[i]))
+                    htput(tsmap, t->param[i], mktyvar(t->param[i]->line));
             ret = mktyname(t->line, t->name, tyspecialize(t->sub[0], tsmap));
+            htput(tsmap, t, ret);
             for (i = 0; i < t->nparam; i++)
                 lappend(&ret->param, &ret->nparam, tyspecialize(t->param[i], tsmap));
             break;
         case Tystruct:
             ret = tydup(t);
+            htput(tsmap, t, ret);
             pushstab(NULL);
             for (i = 0; i < t->nmemb; i++)
                 ret->sdecls[i] = specializenode(t->sdecls[i], tsmap);
@@ -69,6 +71,7 @@
             break;
         case Tyunion:
             ret = tydup(t);
+            htput(tsmap, t, ret);
             for (i = 0; i < t->nmemb; i++) {
                 ret->udecls[i]->utype = ret;
                 if (ret->udecls[i]->etype)
@@ -78,6 +81,7 @@
         default:
             if (t->nsub > 0) {
                 ret = tydup(t);
+                htput(tsmap, t, ret);
                 for (i = 0; i < t->nsub; i++)
                     ret->sub[i] = tyspecialize(t->sub[i], tsmap);
             } else {
@@ -108,7 +112,7 @@
     size_t i;
 
     if (from->type == Typaram) {
-        htput(tsmap, from->pname, to);
+        htput(tsmap, from, to);
     }
     if (to->nsub != from->nsub)
         return;
@@ -340,6 +344,42 @@
     return name;
 }
 
+ulong tyhash(void *ty)
+{
+    size_t i;
+    Type *t;
+    ulong hash;
+
+    t = (Type *)ty;
+    if (t->type == Typaram)
+        hash = strhash(t->pname);
+    else
+        hash = inthash(t->tid);
+
+    for (i = 0; i < t->nparam; i++)
+        hash ^= tyhash(t->param[i]);
+    return hash;
+}
+
+int tyeq(void *t1, void *t2)
+{
+    Type *a, *b;
+    size_t i;
+
+    a = (Type *)t1;
+    b = (Type *)t2;
+    if (a->type == Typaram && b->type == Typaram)
+        return streq(a->pname, b->pname);
+    if (a->tid == b->tid)
+        return 1;
+    if (a->nparam != b->nparam)
+        return 0;
+    for (i = 0; i < a->nparam; i++)
+        if (!tyeq(a->param[i], b->param[i]))
+            return 0;
+    return 1;
+}
+
 /*
  * Takes a generic declaration, and creates a specialized
  * duplicate of it with type 'to'. It also generates
@@ -368,7 +408,7 @@
     }
 
     /* specialize */
-    tsmap = mkht(strhash, streq);
+    tsmap = mkht(tyhash, tyeq);
     fillsubst(tsmap, to, n->decl.type);
 
     d = mkdecl(n->line, *name, tysubst(n->decl.type, tsmap));