From ce26f8625d984499af3d17aa8501bb13770e0933 Mon Sep 17 00:00:00 2001 From: Quentin Carbonneaux Date: Tue, 12 Apr 2016 12:17:04 -0400 Subject: add simple il validation --- parse.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 100 insertions(+), 13 deletions(-) diff --git a/parse.c b/parse.c index f5c499f..cf97f11 100644 --- a/parse.c +++ b/parse.c @@ -18,9 +18,9 @@ OpDesc opdesc[NOp] = { [OUDiv] = { "udiv", 2, {A(w,l,s,d), A(w,l,s,d)}, 0, 0, 1 }, [OURem] = { "urem", 2, {A(w,l,x,x), A(w,l,x,x)}, 0, 0, 1 }, [OMul] = { "mul", 2, {A(w,l,s,d), A(w,l,s,d)}, 0, 0, 1 }, - [OAnd] = { "and", 2, {A(w,l,s,d), A(w,l,s,d)}, 1, 0, 1 }, - [OOr] = { "or", 2, {A(w,l,s,d), A(w,l,s,d)}, 1, 0, 1 }, - [OXor] = { "xor", 2, {A(w,l,s,d), A(w,l,s,d)}, 1, 0, 1 }, + [OAnd] = { "and", 2, {A(w,l,x,x), A(w,l,x,x)}, 1, 0, 1 }, + [OOr] = { "or", 2, {A(w,l,x,x), A(w,l,x,x)}, 1, 0, 1 }, + [OXor] = { "xor", 2, {A(w,l,x,x), A(w,l,x,x)}, 1, 0, 1 }, [OSar] = { "sar", 1, {A(w,l,x,x), A(w,w,x,x)}, 1, 0, 1 }, [OShr] = { "shr", 1, {A(w,l,x,x), A(w,w,x,x)}, 1, 0, 1 }, [OShl] = { "shl", 1, {A(w,l,x,x), A(w,w,x,x)}, 1, 0, 1 }, @@ -37,13 +37,13 @@ OpDesc opdesc[NOp] = { [OLoaduh] = { "loaduh", 0, {A(m,m,x,x), A(x,x,x,x)}, 0, 1, 0 }, [OLoadsb] = { "loadsb", 0, {A(m,m,x,x), A(x,x,x,x)}, 0, 1, 0 }, [OLoadub] = { "loadub", 0, {A(m,m,x,x), A(x,x,x,x)}, 0, 1, 0 }, - [OExtsw] = { "extsw", 0, {A(w,w,w,w), A(x,x,x,x)}, 0, 1, 1 }, - [OExtuw] = { "extuw", 0, {A(w,w,w,w), A(x,x,x,x)}, 0, 1, 1 }, - [OExtsh] = { "extsh", 0, {A(w,w,w,w), A(x,x,x,x)}, 0, 1, 1 }, - [OExtuh] = { "extuh", 0, {A(w,w,w,w), A(x,x,x,x)}, 0, 1, 1 }, - [OExtsb] = { "extsb", 0, {A(w,w,w,w), A(x,x,x,x)}, 0, 1, 1 }, - [OExtub] = { "extub", 0, {A(w,w,w,w), A(x,x,x,x)}, 0, 1, 1 }, - [OExts] = { "exts", 0, {A(w,w,w,w), A(x,x,x,x)}, 0, 1, 1 }, + [OExtsw] = { "extsw", 0, {A(w,w,x,x), A(x,x,x,x)}, 0, 1, 1 }, + [OExtuw] = { "extuw", 0, {A(w,w,x,x), A(x,x,x,x)}, 0, 1, 1 }, + [OExtsh] = { "extsh", 0, {A(w,w,x,x), A(x,x,x,x)}, 0, 1, 1 }, + [OExtuh] = { "extuh", 0, {A(w,w,x,x), A(x,x,x,x)}, 0, 1, 1 }, + [OExtsb] = { "extsb", 0, {A(w,w,x,x), A(x,x,x,x)}, 0, 1, 1 }, + [OExtub] = { "extub", 0, {A(w,w,x,x), A(x,x,x,x)}, 0, 1, 1 }, + [OExts] = { "exts", 0, {A(x,x,x,s), A(x,x,x,x)}, 0, 1, 1 }, [OTruncd] = { "truncd", 0, {A(d,d,d,d), A(x,x,x,x)}, 0, 1, 1 }, [OFtosi] = { "ftosi", 0, {A(s,d,x,x), A(x,x,x,x)}, 0, 1, 1 }, [OSitof] = { "sitof", 0, {A(x,x,w,l), A(x,x,x,x)}, 0, 1, 1 }, @@ -59,8 +59,8 @@ OpDesc opdesc[NOp] = { [OAddr] = { "addr", 0, {A(m,m,x,x), A(x,x,x,x)}, 0, 1, 0 }, [OPar] = { "parn", 0, {A(x,x,x,x), A(x,x,x,x)}, 0, 0, 0 }, [OParc] = { "parc", 0, {A(x,x,x,x), A(x,x,x,x)}, 0, 0, 0 }, - [OArg] = { "arg", 0, {A(x,x,x,x), A(x,x,x,x)}, 0, 0, 0 }, - [OArgc] = { "argc", 0, {A(x,x,x,x), A(x,x,x,x)}, 0, 0, 0 }, + [OArg] = { "arg", 0, {A(w,l,s,d), A(x,x,x,x)}, 0, 0, 0 }, + [OArgc] = { "argc", 0, {A(x,x,x,x), A(x,l,x,x)}, 0, 0, 0 }, [OCall] = { "call", 0, {A(m,m,m,m), A(x,x,x,x)}, 0, 0, 0 }, [OXSetnp] = { "xsetnp", 0, {A(x,x,x,x), A(x,x,x,x)}, 0, 0, 0 }, [OXSetp] = { "xsetp", 0, {A(x,x,x,x), A(x,x,x,x)}, 0, 0, 0 }, @@ -462,6 +462,8 @@ parserefl(int arg) *curi = (Ins){OArg, R, {r}, k}; else *curi = (Ins){OPar, r, {R}, k}; + if (!arg) + curf->tmp[r.val].cls = curi->cls; curi++; t = next(); if (t == TRParen) @@ -481,6 +483,7 @@ findblk(char *name) return bmap[i]; vgrow(&bmap, ++nblk); bmap[i] = blknew(); + bmap[i]->id = i; strcpy(bmap[i]->name, name); return bmap[i]; } @@ -566,6 +569,8 @@ parseline(PState ps) expect(TLbl); curb->s2 = findblk(tokval.str); } + if (curb->s1 == curf->start || curb->s2 == curf->start) + err("invalid jump to the start node"); Close: expect(TNL); closeblk(); @@ -618,8 +623,10 @@ DoOp: next(); } next(); +Ins: + if (!req(r, R)) + curf->tmp[r.val].cls = k; if (op != -1) { - Ins: if (curi - insb >= NIns) err("too many instructions (2)"); curi->op = op; @@ -642,6 +649,85 @@ DoOp: } } +static int +oktype(Ref r, int k, Fn *fn) +{ + return rtype(r) != RTmp || fn->tmp[r.val].cls == k + || (fn->tmp[r.val].cls == Kl && k == Kw); +} + +static void +validate(Fn *fn) +{ + Blk *b; + Phi *p; + Ins *i; + uint n; + int k; + BSet pb[1], ppb[1]; + + fillpreds(fn); + bsinit(pb, fn->nblk); + bsinit(ppb, fn->nblk); + for (b=fn->start; b; b=b->link) { + bszero(pb); + for (n=0; nnpred; n++) + bsset(pb, b->pred[n]->id); + for (p=b->phi; p; p=p->link) { + bszero(ppb); + for (n=0; nnarg; n++) { + k = fn->tmp[p->to.val].cls; + if (bshas(ppb, p->blk[n]->id)) + err("multiple entries for @%s in phi %%%s", + p->blk[n]->name, + fn->tmp[p->to.val].name); + if (!oktype(p->arg[n], k, fn)) + err("invalid type for operand %%%s in phi %%%s", + fn->tmp[p->arg[n].val].name, + fn->tmp[p->to.val].name); + bsset(ppb, p->blk[n]->id); + } + if (!bsequal(pb, ppb)) + err("predecessors not matched in phi %%%s", + fn->tmp[p->to.val].name); + } + for (i=b->ins; i-b->ins < b->nins; i++) + for (n=0; n<2; n++) { + k = opdesc[i->op].argcls[n][i->cls]; + if (rtype(i->arg[n]) == RType) + continue; + if (rtype(i->arg[n]) != -1 && k == Kx) + err("no %s operand expected in %s", + n == 1 ? "second" : "first", + opdesc[i->op].name); + if (rtype(i->arg[n]) == -1 && k != Kx) + err("missing %s operand in %s", + n == 1 ? "second" : "first", + opdesc[i->op].name); + if (!oktype(i->arg[n], k, fn)) + err("invalid type for %s operand %%%s in %s", + n == 1 ? "second" : "first", + fn->tmp[i->arg[n].val].name, + opdesc[i->op].name); + } + if (isret(b->jmp.type)) { + if (b->jmp.type == JRetc) { + if (!oktype(b->jmp.arg, Kl, fn)) + goto JErr; + } else if (!oktype(b->jmp.arg, b->jmp.type-JRetw, fn)) + goto JErr; + } + if (b->jmp.type == JJnz && !oktype(b->jmp.arg, Kw, fn)) + JErr: + err("invalid type for jump argument %%%s in block @%s", + fn->tmp[b->jmp.arg.val].name, b->name); + if (b->s1 && b->s1->jmp.type == JXXX) + err("block @%s is used undefined", b->s1->name); + if (b->s2 && b->s2->jmp.type == JXXX) + err("block @%s is used undefined", b->s2->name); + } +} + static Fn * parsefn(int export) { @@ -685,6 +771,7 @@ parsefn(int export) curf->nmem = 0; curf->nblk = nblk; curf->rpo = 0; + validate(curf); return curf; } -- cgit 1.4.1