|
@@ -18,9 +18,9 @@ OpDesc opdesc[NOp] = {
|
|
|
[OUDiv] = { "udiv", 2, {A(w,l,s,d), A(w,l,s,d)}, 0, 0, 1 },
|
|
[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 },
|
|
[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 },
|
|
[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 },
|
|
[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 },
|
|
[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 },
|
|
[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 },
|
|
[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 },
|
|
[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 },
|
|
[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 },
|
|
[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 },
|
|
[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 },
|
|
[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 },
|
|
[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 },
|
|
[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 },
|
|
[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 },
|
|
[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 },
|
|
[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 },
|
|
[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};
|
|
*curi = (Ins){OArg, R, {r}, k};
|
|
|
else
|
|
else
|
|
|
*curi = (Ins){OPar, r, {R}, k};
|
|
*curi = (Ins){OPar, r, {R}, k};
|
|
|
|
|
+ if (!arg)
|
|
|
|
|
+ curf->tmp[r.val].cls = curi->cls;
|
|
|
curi++;
|
|
curi++;
|
|
|
t = next();
|
|
t = next();
|
|
|
if (t == TRParen)
|
|
if (t == TRParen)
|
|
@@ -481,6 +483,7 @@ findblk(char *name)
|
|
|
return bmap[i];
|
|
return bmap[i];
|
|
|
vgrow(&bmap, ++nblk);
|
|
vgrow(&bmap, ++nblk);
|
|
|
bmap[i] = blknew();
|
|
bmap[i] = blknew();
|
|
|
|
|
+ bmap[i]->id = i;
|
|
|
strcpy(bmap[i]->name, name);
|
|
strcpy(bmap[i]->name, name);
|
|
|
return bmap[i];
|
|
return bmap[i];
|
|
|
}
|
|
}
|
|
@@ -566,6 +569,8 @@ parseline(PState ps)
|
|
|
expect(TLbl);
|
|
expect(TLbl);
|
|
|
curb->s2 = findblk(tokval.str);
|
|
curb->s2 = findblk(tokval.str);
|
|
|
}
|
|
}
|
|
|
|
|
+ if (curb->s1 == curf->start || curb->s2 == curf->start)
|
|
|
|
|
+ err("invalid jump to the start node");
|
|
|
Close:
|
|
Close:
|
|
|
expect(TNL);
|
|
expect(TNL);
|
|
|
closeblk();
|
|
closeblk();
|
|
@@ -618,8 +623,10 @@ DoOp:
|
|
|
next();
|
|
next();
|
|
|
}
|
|
}
|
|
|
next();
|
|
next();
|
|
|
|
|
+Ins:
|
|
|
|
|
+ if (!req(r, R))
|
|
|
|
|
+ curf->tmp[r.val].cls = k;
|
|
|
if (op != -1) {
|
|
if (op != -1) {
|
|
|
- Ins:
|
|
|
|
|
if (curi - insb >= NIns)
|
|
if (curi - insb >= NIns)
|
|
|
err("too many instructions (2)");
|
|
err("too many instructions (2)");
|
|
|
curi->op = op;
|
|
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; n<b->npred; n++)
|
|
|
|
|
+ bsset(pb, b->pred[n]->id);
|
|
|
|
|
+ for (p=b->phi; p; p=p->link) {
|
|
|
|
|
+ bszero(ppb);
|
|
|
|
|
+ for (n=0; n<p->narg; 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 *
|
|
static Fn *
|
|
|
parsefn(int export)
|
|
parsefn(int export)
|
|
|
{
|
|
{
|
|
@@ -685,6 +771,7 @@ parsefn(int export)
|
|
|
curf->nmem = 0;
|
|
curf->nmem = 0;
|
|
|
curf->nblk = nblk;
|
|
curf->nblk = nblk;
|
|
|
curf->rpo = 0;
|
|
curf->rpo = 0;
|
|
|
|
|
+ validate(curf);
|
|
|
return curf;
|
|
return curf;
|
|
|
}
|
|
}
|
|
|
|
|
|