delete some code from walkexpr that is now

handled by typecheck.

second switch is gone

move floating point minus into back end

R=ken
OCL=32558
CL=32558
This commit is contained in:
Russ Cox 2009-07-30 18:56:44 -07:00
parent d9c914e985
commit b754b4348f
8 changed files with 117 additions and 309 deletions

View file

@ -192,6 +192,12 @@ cgen(Node *n, Node *res)
goto ret;
case OMINUS:
if(isfloat[nl->type->etype]) {
nr = nodintconst(-1);
convlit(&nr, n->type);
a = optoas(OMUL, nl->type);
goto sbop;
}
a = optoas(n->op, nl->type);
goto uop;

View file

@ -365,6 +365,13 @@ flt: // floating-point. 387 (not SSE2) to interoperate with 6c
if(nr != N)
goto flt2;
if(n->op == OMINUS) {
nr = nodintconst(-1);
convlit(&nr, n->type);
n->op = OMUL;
goto flt2;
}
// unary
cgen(nl, &f0);
if(n->op != OCONV)

View file

@ -967,6 +967,9 @@ Jconv(Fmt *fp)
if(n->funcdepth != 0)
fmtprint(fp, " f(%d)", n->funcdepth);
if(n->typecheck != 0)
fmtprint(fp, " tc(%d)", n->typecheck);
return 0;
}

View file

@ -28,7 +28,7 @@ typechecklist(NodeList *l, int top)
Node*
typecheck(Node **np, int top)
{
int et, et1, et2, op, nerr, len;
int et, op, nerr, len;
NodeList *ll;
Node *n, *l, *r;
NodeList *args;
@ -256,6 +256,7 @@ reswitch:
et = TINT;
if(t->etype != TIDEAL && !eqtype(l->type, r->type)) {
badbinary:
defaultlit2(&l, &r, 1);
yyerror("invalid operation: %#N (type %T %#O %T)", n, l->type, op, r->type);
goto error;
}
@ -270,8 +271,15 @@ reswitch:
if(isslice(l->type) && !isnil(l) && !isnil(r))
goto badbinary;
t = l->type;
if(iscmp[n->op])
if(iscmp[n->op]) {
t = types[TBOOL];
evconst(n);
if(n->op != OLITERAL) {
defaultlit2(&l, &r, 1);
n->left = l;
n->right = r;
}
}
n->type = t;
goto ret;
@ -637,6 +645,8 @@ yyerror("skip %#N", n);
yyerror("invalid operation: %#N (non-chan type %T)", n, t);
goto error;
}
if(n->op == OCLOSED)
n->type = types[TBOOL];
goto ret;
case OCONV:
@ -1023,7 +1033,6 @@ convert(Node **np, Type *t, int explicit)
// no-op conversion
if(cvttype(t, n->type) == 1) {
nop:
if(n->op == OLITERAL) {
// can convert literal in place
n1 = nod(OXXX, N, N);

View file

@ -356,11 +356,32 @@ reswitch:
goto ret;
case OTYPE:
case OCALLMETH:
case OCALLINTER:
case OCALLFUNC:
case ONONAME:
case OINDREG:
case OEMPTY:
case OCONVNOP:
case OCOMPMAP:
case OCOMPSLICE:
goto ret;
case OKEY:
walkexpr(&n->left, top | typeok, init);
walkexpr(&n->right, top | typeok, init);
case ONOT:
case OMINUS:
case OPLUS:
case OCOM:
case OLEN:
case OCAP:
case ODOT:
case ODOTPTR:
case ODOTMETH:
case ODOTINTER:
walkexpr(&n->left, Erv, init);
goto ret;
case OIND:
walkexpr(&n->left, Erv | Etype, init);
goto ret;
case OPRINT:
@ -398,18 +419,6 @@ reswitch:
n->addable = 1;
goto ret;
case ONONAME:
s = n->sym;
if(n->diag == 0) {
s->undef = 1;
n->diag = 1;
yyerror("undefined: %S", s);
goto ret;
}
if(top == Etop)
goto nottop;
goto ret;
case ONAME:
if(top == Etop)
goto nottop;
@ -427,11 +436,6 @@ reswitch:
}
goto ret;
case OCALLMETH:
case OCALLINTER:
case OCALLFUNC:
goto ret;
case OCALL:
if(top == Elv)
goto nottop;
@ -686,10 +690,6 @@ reswitch:
}
goto ret;
case OINDREG:
case OEMPTY:
goto ret;
case ODOTTYPE:
walkdottype(n, init);
// fall through
@ -699,13 +699,6 @@ reswitch:
walkconv(&n, init);
goto ret;
case OCONVNOP:
goto ret;
case OCOMPMAP:
case OCOMPSLICE:
goto ret;
case OCOMPOS:
walkexpr(&n->right, Etype, init);
t = n->right->type;
@ -733,17 +726,6 @@ reswitch:
n = r;
goto ret;
case ONOT:
if(!(top & Erv))
goto nottop;
if(n->op == OLITERAL)
goto ret;
walkexpr(&n->left, Erv, init);
if(n->left == N || n->left->type == T)
goto ret;
et = n->left->type->etype;
break;
case OASOP:
if(top != Etop)
goto nottop;
@ -777,7 +759,7 @@ reswitch:
if(issigned[et] || !isint[et])
goto badt;
// check of n->left->type happens in second switch.
break;
goto ret;
case OMOD:
case OAND:
@ -804,14 +786,8 @@ reswitch:
walkexpr(&n->right, Erv, init);
if(n->left == N || n->right == N)
goto ret;
evconst(n);
if(n->op == OLITERAL)
goto ret;
defaultlit2(&n->left, &n->right, iscmp[n->op]);
if(n->left->type == T || n->right->type == T)
goto ret;
if(!eqtype(n->left->type, n->right->type))
goto badt;
switch(n->op) {
case OANDNOT:
@ -846,80 +822,60 @@ reswitch:
}
break;
}
break;
case OMINUS:
case OPLUS:
case OCOM:
if(!(top & Erv))
goto nottop;
walkexpr(&n->left, Erv, init);
if(n->left == N)
goto ret;
if(n->op == OLITERAL)
goto ret;
break;
case OLEN:
if(!(top & Erv))
goto nottop;
if(n->left == N) {
if(n->list == nil) {
yyerror("missing argument to len");
switch(n->op) {
case OEQ:
case ONE:
if(isinter(n->left->type)) {
n = ifaceop(n);
goto ret;
}
if(n->list->next)
yyerror("too many arguments to len");
n->left = n->list->n;
}
walkexpr(&n->left, Erv, init);
defaultlit(&n->left, T);
t = n->left->type;
if(t == T)
goto ret;
switch(t->etype) {
default:
goto badt;
case TSTRING:
if(isconst(n->left, CTSTR))
nodconst(n, types[TINT], n->left->val.u.sval->len);
break;
case TMAP:
break;
case TARRAY:
if(t->bound >= 0)
nodconst(n, types[TINT], t->bound);
break;
}
n->type = types[TINT];
goto ret;
case OCAP:
if(!(top & Erv))
goto nottop;
if(n->left == N) {
if(n->list == nil) {
yyerror("missing argument to cap");
goto ret;
}
if(n->list->next)
yyerror("too many arguments to cap");
n->left = n->list->n;
}
walkexpr(&n->left, Erv, init);
defaultlit(&n->left, T);
t = n->left->type;
if(t == T)
goto ret;
switch(t->etype) {
default:
goto badt;
case TARRAY:
if(t->bound >= 0)
nodconst(n, types[TINT], t->bound);
/*
* rewrite div and mod into function calls
* on 32-bit architectures.
*/
switch(n->op) {
case ODIV:
case OMOD:
et = n->left->type->etype;
if(widthptr > 4 || (et != TUINT64 && et != TINT64))
break;
if(et == TINT64)
strcpy(namebuf, "int64");
else
strcpy(namebuf, "uint64");
if(n->op == ODIV)
strcat(namebuf, "div");
else
strcat(namebuf, "mod");
l = syslook(namebuf, 0);
n->left = nod(OCONV, n->left, N);
n->left->type = types[et];
n->right = nod(OCONV, n->right, N);
n->right->type = types[et];
r = nod(OCALL, l, N);
r->list = list(list1(n->left), n->right);
r = nod(OCONV, r, N);
r->type = n->left->left->type;
typecheck(&r, Erv);
walkexpr(&r, Erv, init);
n = r;
break;
case OASOP:
et = n->left->type->etype;
if(widthptr > 4 || (et != TUINT64 && et != TINT64))
break;
l = saferef(n->left, init);
r = nod(OAS, l, nod(n->etype, l, n->right));
typecheck(&r, Etop);
walkexpr(&r, Etop, init);
n = r;
break;
}
n->type = types[TINT];
goto ret;
case OINDEX:
@ -1040,13 +996,6 @@ reswitch:
badtype(OSLICE, n->left->type, T);
goto ret;
case ODOT:
case ODOTPTR:
case ODOTMETH:
case ODOTINTER:
walkexpr(&n->left, Erv, init);
goto ret;
case OADDR:
if(!(top & Erv))
goto nottop;
@ -1112,28 +1061,6 @@ reswitch:
n->type = ptrto(t);
goto ret;
case OIND:
if(top == Etop)
goto nottop;
if(top == Elv) // even if n is lvalue, n->left is rvalue
top = Erv;
if(n->left == N)
goto ret;
walkexpr(&n->left, top | Etype, init);
defaultlit(&n->left, T);
if(n->left->op == OTYPE) {
n->op = OTYPE;
n->type = ptrto(n->left->type);
goto ret;
}
t = n->left->type;
if(t == T)
goto ret;
if(!isptr[t->etype])
goto badt;
n->type = t->type;
goto ret;
case OMAKE:
if(!(top & Erv))
goto nottop;
@ -1157,151 +1084,7 @@ reswitch:
n = callnew(t);
goto ret;
}
/*
* ======== second switch ========
*/
op = n->op;
if(op == OASOP)
op = n->etype;
switch(op) {
default:
fatal("walkexpr: switch 2 unknown op %N", n, init);
goto ret;
case OASOP:
break;
case ONOT:
case OANDAND:
case OOROR:
if(n->left->type == T)
goto ret;
et = n->left->type->etype;
if(et != TBOOL)
goto badt;
t = types[TBOOL];
break;
case OEQ:
case ONE:
if(n->left->type == T)
goto ret;
et = n->left->type->etype;
if(!okforeq[et] && !isslice(n->left->type))
goto badt;
if(isinter(n->left->type)) {
n = ifaceop(n);
goto ret;
}
t = types[TBOOL];
break;
case OLT:
case OLE:
case OGE:
case OGT:
if(n->left->type == T)
goto ret;
et = n->left->type->etype;
if(!okforarith[et] && et != TSTRING)
goto badt;
t = types[TBOOL];
break;
case OADD:
case OSUB:
case OMUL:
case ODIV:
case OPLUS:
if(n->left->type == T)
goto ret;
et = n->left->type->etype;
if(!okforarith[et])
goto badt;
break;
case OMINUS:
if(n->left->type == T)
goto ret;
et = n->left->type->etype;
if(!okforarith[et])
goto badt;
if(isfloat[et]) {
// TODO(rsc): Can do this more efficiently,
// but OSUB is wrong. Should be in back end anyway.
n = nod(OMUL, n->left, nodintconst(-1));
typecheck(&n, Erv);
walkexpr(&n, Erv, init);
goto ret;
}
break;
case OLSH:
case ORSH:
case OAND:
case OANDNOT:
case OOR:
case OXOR:
case OMOD:
case OCOM:
if(n->left->type == T)
goto ret;
et = n->left->type->etype;
if(et != TIDEAL && !okforand[et])
goto badt;
break;
}
/*
* rewrite div and mod into function calls
* on 32-bit architectures.
*/
switch(n->op) {
case ODIV:
case OMOD:
et = n->left->type->etype;
if(widthptr > 4 || (et != TUINT64 && et != TINT64))
break;
if(et == TINT64)
strcpy(namebuf, "int64");
else
strcpy(namebuf, "uint64");
if(n->op == ODIV)
strcat(namebuf, "div");
else
strcat(namebuf, "mod");
l = syslook(namebuf, 0);
n->left = nod(OCONV, n->left, N);
n->left->type = types[et];
n->right = nod(OCONV, n->right, N);
n->right->type = types[et];
r = nod(OCALL, l, N);
r->list = list(list1(n->left), n->right);
r = nod(OCONV, r, N);
r->type = n->left->left->type;
typecheck(&r, Erv);
walkexpr(&r, Erv, init);
n = r;
goto ret;
case OASOP:
et = n->left->type->etype;
if(widthptr > 4 || (et != TUINT64 && et != TINT64))
break;
l = saferef(n->left, init);
r = nod(OAS, l, nod(n->etype, l, n->right));
typecheck(&r, Etop);
walkexpr(&r, Etop, init);
n = r;
goto ret;
}
if(t == T)
t = n->left->type;
n->type = t;
goto ret;
fatal("missing switch %#O", n->op);
nottop:
if(n->diag)

View file

@ -7,6 +7,6 @@
package main
func main() {
var x int64 = 0;
println(x != nil); // ERROR "illegal|incompatible|nil constant"
println(0 != nil); // ERROR "illegal|incompatible|nil constant"
println(x != nil); // ERROR "illegal|incompatible|nil"
println(0 != nil); // ERROR "illegal|incompatible|nil"
}

View file

@ -8,5 +8,5 @@ package main
func f() {
a := true;
a |= a; // ERROR "illegal.*OR"
a |= a; // ERROR "illegal.*OR|bool"
}

View file

@ -36,16 +36,16 @@ func f()
// it decides there are type errors.
x :=
len(m0)+
len(m1)+ // ERROR "illegal|must be"
len(m2)+ // ERROR "illegal|must be"
len(m1)+ // ERROR "illegal|invalid|must be"
len(m2)+ // ERROR "illegal|invalid|must be"
len(m3)+
len(m4)+ // ERROR "illegal|must be"
len(m4)+ // ERROR "illegal|invalid|must be"
len(s0)+
len(s1)+ // ERROR "illegal|must be"
len(s2)+ // ERROR "illegal|must be"
len(s1)+ // ERROR "illegal|invalid|must be"
len(s2)+ // ERROR "illegal|invalid|must be"
len(s3)+
len(s4)+ // ERROR "illegal|must be"
len(s4)+ // ERROR "illegal|invalid|must be"
len(a0)+
len(a1)+
@ -56,14 +56,14 @@ func f()
cap(a2)+
len(b0)+
len(b1)+ // ERROR "illegal|must be"
len(b2)+ // ERROR "illegal|must be"
len(b1)+ // ERROR "illegal|invalid|must be"
len(b2)+ // ERROR "illegal|invalid|must be"
len(b3)+
len(b4)+ // ERROR "illegal|must be"
len(b4)+ // ERROR "illegal|invalid|must be"
cap(b0)+
cap(b1)+ // ERROR "illegal|must be"
cap(b2)+ // ERROR "illegal|must be"
cap(b1)+ // ERROR "illegal|invalid|must be"
cap(b2)+ // ERROR "illegal|invalid|must be"
cap(b3)+
cap(b4); // ERROR "illegal|must be"
cap(b4); // ERROR "illegal|invalid|must be"
}