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));