1
0
mirror of https://github.com/golang/go synced 2024-11-25 12:17:56 -07:00

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; goto ret;
case OMINUS: 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); a = optoas(n->op, nl->type);
goto uop; goto uop;

View File

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

View File

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

View File

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

View File

@ -356,11 +356,32 @@ reswitch:
goto ret; goto ret;
case OTYPE: case OTYPE:
case OCALLMETH:
case OCALLINTER:
case OCALLFUNC:
case ONONAME:
case OINDREG:
case OEMPTY:
case OCONVNOP:
case OCOMPMAP:
case OCOMPSLICE:
goto ret; goto ret;
case OKEY: case ONOT:
walkexpr(&n->left, top | typeok, init); case OMINUS:
walkexpr(&n->right, top | typeok, init); 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; goto ret;
case OPRINT: case OPRINT:
@ -398,18 +419,6 @@ reswitch:
n->addable = 1; n->addable = 1;
goto ret; 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: case ONAME:
if(top == Etop) if(top == Etop)
goto nottop; goto nottop;
@ -427,11 +436,6 @@ reswitch:
} }
goto ret; goto ret;
case OCALLMETH:
case OCALLINTER:
case OCALLFUNC:
goto ret;
case OCALL: case OCALL:
if(top == Elv) if(top == Elv)
goto nottop; goto nottop;
@ -686,10 +690,6 @@ reswitch:
} }
goto ret; goto ret;
case OINDREG:
case OEMPTY:
goto ret;
case ODOTTYPE: case ODOTTYPE:
walkdottype(n, init); walkdottype(n, init);
// fall through // fall through
@ -699,13 +699,6 @@ reswitch:
walkconv(&n, init); walkconv(&n, init);
goto ret; goto ret;
case OCONVNOP:
goto ret;
case OCOMPMAP:
case OCOMPSLICE:
goto ret;
case OCOMPOS: case OCOMPOS:
walkexpr(&n->right, Etype, init); walkexpr(&n->right, Etype, init);
t = n->right->type; t = n->right->type;
@ -733,17 +726,6 @@ reswitch:
n = r; n = r;
goto ret; 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: case OASOP:
if(top != Etop) if(top != Etop)
goto nottop; goto nottop;
@ -777,7 +759,7 @@ reswitch:
if(issigned[et] || !isint[et]) if(issigned[et] || !isint[et])
goto badt; goto badt;
// check of n->left->type happens in second switch. // check of n->left->type happens in second switch.
break; goto ret;
case OMOD: case OMOD:
case OAND: case OAND:
@ -804,14 +786,8 @@ reswitch:
walkexpr(&n->right, Erv, init); walkexpr(&n->right, Erv, init);
if(n->left == N || n->right == N) if(n->left == N || n->right == N)
goto ret; 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) if(n->left->type == T || n->right->type == T)
goto ret; goto ret;
if(!eqtype(n->left->type, n->right->type))
goto badt;
switch(n->op) { switch(n->op) {
case OANDNOT: case OANDNOT:
@ -846,80 +822,60 @@ reswitch:
} }
break; break;
} }
break;
switch(n->op) {
case OMINUS: case OEQ:
case OPLUS: case ONE:
case OCOM: if(isinter(n->left->type)) {
if(!(top & Erv)) n = ifaceop(n);
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");
goto ret; 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; break;
} }
n->type = types[TINT];
goto ret; /*
* rewrite div and mod into function calls
case OCAP: * on 32-bit architectures.
if(!(top & Erv)) */
goto nottop; switch(n->op) {
if(n->left == N) { case ODIV:
if(n->list == nil) { case OMOD:
yyerror("missing argument to cap"); et = n->left->type->etype;
goto ret; if(widthptr > 4 || (et != TUINT64 && et != TINT64))
} break;
if(n->list->next) if(et == TINT64)
yyerror("too many arguments to cap"); strcpy(namebuf, "int64");
n->left = n->list->n; else
} strcpy(namebuf, "uint64");
walkexpr(&n->left, Erv, init); if(n->op == ODIV)
defaultlit(&n->left, T); strcat(namebuf, "div");
t = n->left->type; else
if(t == T) strcat(namebuf, "mod");
goto ret; l = syslook(namebuf, 0);
switch(t->etype) { n->left = nod(OCONV, n->left, N);
default: n->left->type = types[et];
goto badt; n->right = nod(OCONV, n->right, N);
case TARRAY: n->right->type = types[et];
if(t->bound >= 0) r = nod(OCALL, l, N);
nodconst(n, types[TINT], t->bound); 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; break;
} }
n->type = types[TINT];
goto ret; goto ret;
case OINDEX: case OINDEX:
@ -1040,13 +996,6 @@ reswitch:
badtype(OSLICE, n->left->type, T); badtype(OSLICE, n->left->type, T);
goto ret; goto ret;
case ODOT:
case ODOTPTR:
case ODOTMETH:
case ODOTINTER:
walkexpr(&n->left, Erv, init);
goto ret;
case OADDR: case OADDR:
if(!(top & Erv)) if(!(top & Erv))
goto nottop; goto nottop;
@ -1112,28 +1061,6 @@ reswitch:
n->type = ptrto(t); n->type = ptrto(t);
goto ret; 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: case OMAKE:
if(!(top & Erv)) if(!(top & Erv))
goto nottop; goto nottop;
@ -1157,151 +1084,7 @@ reswitch:
n = callnew(t); n = callnew(t);
goto ret; goto ret;
} }
fatal("missing switch %#O", n->op);
/*
* ======== 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;
nottop: nottop:
if(n->diag) if(n->diag)

View File

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

View File

@ -8,5 +8,5 @@ package main
func f() { func f() {
a := true; 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. // it decides there are type errors.
x := x :=
len(m0)+ len(m0)+
len(m1)+ // ERROR "illegal|must be" len(m1)+ // ERROR "illegal|invalid|must be"
len(m2)+ // ERROR "illegal|must be" len(m2)+ // ERROR "illegal|invalid|must be"
len(m3)+ len(m3)+
len(m4)+ // ERROR "illegal|must be" len(m4)+ // ERROR "illegal|invalid|must be"
len(s0)+ len(s0)+
len(s1)+ // ERROR "illegal|must be" len(s1)+ // ERROR "illegal|invalid|must be"
len(s2)+ // ERROR "illegal|must be" len(s2)+ // ERROR "illegal|invalid|must be"
len(s3)+ len(s3)+
len(s4)+ // ERROR "illegal|must be" len(s4)+ // ERROR "illegal|invalid|must be"
len(a0)+ len(a0)+
len(a1)+ len(a1)+
@ -56,14 +56,14 @@ func f()
cap(a2)+ cap(a2)+
len(b0)+ len(b0)+
len(b1)+ // ERROR "illegal|must be" len(b1)+ // ERROR "illegal|invalid|must be"
len(b2)+ // ERROR "illegal|must be" len(b2)+ // ERROR "illegal|invalid|must be"
len(b3)+ len(b3)+
len(b4)+ // ERROR "illegal|must be" len(b4)+ // ERROR "illegal|invalid|must be"
cap(b0)+ cap(b0)+
cap(b1)+ // ERROR "illegal|must be" cap(b1)+ // ERROR "illegal|invalid|must be"
cap(b2)+ // ERROR "illegal|must be" cap(b2)+ // ERROR "illegal|invalid|must be"
cap(b3)+ cap(b3)+
cap(b4); // ERROR "illegal|must be" cap(b4); // ERROR "illegal|invalid|must be"
} }