summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2016-01-01 01:05:50 -0800
committerOri Bernstein <ori@eigenstate.org>2016-01-01 01:05:50 -0800
commitffc55ee721c02d1caede8d7fbad9e8b687f01306 (patch)
tree5ebf03f748eea405339fc1e013675cb3f35442d4
parent7ef2abad32fe3b273f16eeb28d63a63229dca3a6 (diff)
downloadmc-ffc55ee721c02d1caede8d7fbad9e8b687f01306.tar.gz
Actually check array sizes when inferring.
-rw-r--r--mi/Makefile1
-rw-r--r--mi/mi.h3
-rw-r--r--parse/Makefile1
-rw-r--r--parse/fold.c (renamed from mi/fold.c)1
-rw-r--r--parse/infer.c27
-rw-r--r--parse/node.c7
-rw-r--r--parse/parse.h4
7 files changed, 37 insertions, 7 deletions
diff --git a/mi/Makefile b/mi/Makefile
index 3a7cd1b..b0e3645 100644
--- a/mi/Makefile
+++ b/mi/Makefile
@@ -1,7 +1,6 @@
LIB=libmi.a
OBJ=cfg.o \
dfcheck.o \
- fold.o \
match.o \
reaching.o \
diff --git a/mi/mi.h b/mi/mi.h
index 021a3f7..d1910f6 100644
--- a/mi/mi.h
+++ b/mi/mi.h
@@ -35,9 +35,6 @@ struct Reaching {
size_t *ndefs;
};
-/* expression folding */
-Node *fold(Node *n, int foldvar);
-
/* dataflow analysis */
Reaching *reaching(Cfg *cfg);
Node *assignee(Node *n);
diff --git a/parse/Makefile b/parse/Makefile
index 36d9fc7..1eaac98 100644
--- a/parse/Makefile
+++ b/parse/Makefile
@@ -1,6 +1,7 @@
LIB=libparse.a
OBJ=bitset.o \
dump.o \
+ fold.o \
gram.o \
htab.o \
infer.o \
diff --git a/mi/fold.c b/parse/fold.c
index e16b7d3..0687a85 100644
--- a/mi/fold.c
+++ b/parse/fold.c
@@ -11,7 +11,6 @@
#include <unistd.h>
#include "parse.h"
-#include "mi.h"
static int getintlit(Node *n, vlong *v)
{
diff --git a/parse/infer.c b/parse/infer.c
index 17af9e6..4d9b767 100644
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -901,6 +901,29 @@ static Type *basetype(Inferstate *st, Type *a)
return t;
}
+static void checksize(Inferstate *st, Node *ctx, Type *a, Type *b)
+{
+ if (a->asize)
+ a->asize = fold(a->asize, 1);
+ if (b->asize)
+ b->asize = fold(b->asize, 1);
+ if (a->asize && exprop(a->asize) != Olit)
+ lfatal(ctx->loc, "%s: array size is not constant near %s",
+ tystr(a), ctxstr(st, ctx));
+ if (a->asize && exprop(b->asize) != Olit)
+ lfatal(ctx->loc, "%s: array size is not constant near %s",
+ tystr(b), ctxstr(st, ctx));
+ if (!a->asize)
+ a->asize = b->asize;
+ else if (!b->asize)
+ b->asize = a->asize;
+ else if (a->asize && b->asize)
+ if (!litvaleq(a->asize->expr.args[0], b->asize->expr.args[0]))
+ lfatal(ctx->loc, "array size of %s does not match %s near %s",
+ tystr(a), tystr(b), ctxstr(st, ctx));
+}
+
+
/* Unifies two types, or errors if the types are not unifiable. */
static Type *unify(Inferstate *st, Node *ctx, Type *u, Type *v)
{
@@ -949,6 +972,10 @@ static Type *unify(Inferstate *st, Node *ctx, Type *u, Type *v)
typeerror(st, a, b, ctx, "Infinite type\n");
}
+ if (a->type == Tyarray && b->type == Tyarray) {
+ checksize(st, ctx, a, b);
+ }
+
/* if the tyrank of a is 0 (ie, a raw tyvar), just unify.
* Otherwise, match up subtypes. */
if (a->type == b->type && a->type != Tyvar) {
diff --git a/parse/node.c b/parse/node.c
index 63d26c2..309cca8 100644
--- a/parse/node.c
+++ b/parse/node.c
@@ -429,11 +429,14 @@ Type *nodetype(Node *n)
int liteq(Node *a, Node *b)
{
+ return litvaleq(a, b) && tyeq(a->lit.type, b->lit.type);
+}
+
+int litvaleq(Node *a, Node *b)
+{
assert(a->type == Nlit && b->type == Nlit);
if (a->lit.littype != b->lit.littype)
return 0;
- if (!tyeq(a->lit.type, b->lit.type))
- return 0;
switch (a->lit.littype) {
case Lvoid: return 1;
case Lchr: return a->lit.chrval == b->lit.chrval;
diff --git a/parse/parse.h b/parse/parse.h
index 7ca7c07..43744c5 100644
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -454,6 +454,7 @@ int hthas(Htab *ht, void *k);
void **htkeys(Htab *ht, size_t *nkeys);
/* useful key types */
int liteq(Node *a, Node *b);
+int litvaleq(Node *a, Node *b);
ulong strhash(void *key);
int streq(void *a, void *b);
ulong strlithash(void *key);
@@ -624,6 +625,9 @@ void writeuse(FILE *fd, Node *file);
void tagexports(Node *file, int hidelocal);
void addextlibs(Node *file, char **libs, size_t nlibs);
+/* expression folding */
+Node *fold(Node *n, int foldvar);
+
/* typechecking/inference */
void infer(Node *file);
Type *tysearch(Type *t);