Commit a95ee61a authored by Russ Cox's avatar Russ Cox

ideal bools and related fixes

R=ken
OCL=34859
CL=34865
parent 27969e87
...@@ -136,7 +136,7 @@ cgen(Node *n, Node *res) ...@@ -136,7 +136,7 @@ cgen(Node *n, Node *res)
tempfree(&n1); tempfree(&n1);
return; return;
} }
// 64-bit ops are hard on 32-bit machine. // 64-bit ops are hard on 32-bit machine.
if(is64(n->type) || is64(res->type) || n->left != N && is64(n->left->type)) { if(is64(n->type) || is64(res->type) || n->left != N && is64(n->left->type)) {
switch(n->op) { switch(n->op) {
...@@ -156,7 +156,7 @@ cgen(Node *n, Node *res) ...@@ -156,7 +156,7 @@ cgen(Node *n, Node *res)
} }
} }
if(isfloat[n->type->etype] && isfloat[nl->type->etype]) if(nl != N && isfloat[n->type->etype] && isfloat[nl->type->etype])
goto flt; goto flt;
switch(n->op) { switch(n->op) {
...@@ -392,7 +392,7 @@ flt: // floating-point. 387 (not SSE2) to interoperate with 6c ...@@ -392,7 +392,7 @@ flt: // floating-point. 387 (not SSE2) to interoperate with 6c
// unary // unary
cgen(nl, &f0); cgen(nl, &f0);
if(n->op != OCONV) if(n->op != OCONV && n->op != OPLUS)
gins(foptoas(n->op, n->type, 0), &f0, &f0); gins(foptoas(n->op, n->type, 0), &f0, &f0);
gmove(&f0, res); gmove(&f0, res);
return; return;
......
...@@ -70,7 +70,7 @@ convlit1(Node **np, Type *t, int explicit) ...@@ -70,7 +70,7 @@ convlit1(Node **np, Type *t, int explicit)
Node *n, *nn; Node *n, *nn;
n = *np; n = *np;
if(n == N || t == T || n->type == T || isideal(t) || eqtype(t, n->type)) if(n == N || t == T || n->type == T || isideal(t) || n->type == t)
return; return;
if(!explicit && !isideal(n->type)) if(!explicit && !isideal(n->type))
return; return;
...@@ -285,12 +285,19 @@ tostr(Val v) ...@@ -285,12 +285,19 @@ tostr(Val v)
s = mal(sizeof(*s)+l); s = mal(sizeof(*s)+l);
s->len = l; s->len = l;
runetochar((char*)s->s, &rune); runetochar((char*)s->s, &rune);
memset(&v, 0, sizeof v);
v.ctype = CTSTR; v.ctype = CTSTR;
v.u.sval = s; v.u.sval = s;
break; break;
case CTFLT: case CTFLT:
yyerror("no float -> string"); yyerror("no float -> string");
case CTNIL:
memset(&v, 0, sizeof v);
v.ctype = CTSTR;
v.u.sval = mal(sizeof *s);
break;
} }
return v; return v;
} }
...@@ -593,11 +600,17 @@ unary: ...@@ -593,11 +600,17 @@ unary:
} }
return; return;
case TUP(OCONV, CTNIL):
case TUP(OARRAYBYTESTR, CTNIL):
if(n->type->etype == TSTRING) {
v = tostr(v);
nl->type = n->type;
break;
}
// fall through
case TUP(OCONV, CTINT): case TUP(OCONV, CTINT):
case TUP(OCONV, CTFLT): case TUP(OCONV, CTFLT):
case TUP(OCONV, CTSTR): case TUP(OCONV, CTSTR):
case TUP(OCONV, CTNIL):
case TUP(OARRAYBYTESTR, CTNIL):
convlit1(&nl, n->type, 1); convlit1(&nl, n->type, 1);
break; break;
...@@ -679,10 +692,10 @@ nodlit(Val v) ...@@ -679,10 +692,10 @@ nodlit(Val v)
default: default:
fatal("nodlit ctype %d", v.ctype); fatal("nodlit ctype %d", v.ctype);
case CTSTR: case CTSTR:
n->type = types[TSTRING]; n->type = idealstring;
break; break;
case CTBOOL: case CTBOOL:
n->type = types[TBOOL]; n->type = idealbool;
break; break;
case CTINT: case CTINT:
case CTFLT: case CTFLT:
...@@ -730,7 +743,10 @@ defaultlit(Node **np, Type *t) ...@@ -730,7 +743,10 @@ defaultlit(Node **np, Type *t)
} }
defaultlit(&n->left, t); defaultlit(&n->left, t);
defaultlit(&n->right, t); defaultlit(&n->right, t);
n->type = n->left->type; if(n->type == idealbool || n->type == idealstring)
n->type = types[n->type->etype];
else
n->type = n->left->type;
return; return;
} }
...@@ -753,6 +769,9 @@ defaultlit(Node **np, Type *t) ...@@ -753,6 +769,9 @@ defaultlit(Node **np, Type *t)
} }
yyerror("defaultlit: unknown literal: %#N", n); yyerror("defaultlit: unknown literal: %#N", n);
break; break;
case CTBOOL:
n->type = types[TBOOL];
break;
case CTINT: case CTINT:
n->type = types[TINT]; n->type = types[TINT];
if(t != T) { if(t != T) {
...@@ -795,11 +814,11 @@ defaultlit2(Node **lp, Node **rp, int force) ...@@ -795,11 +814,11 @@ defaultlit2(Node **lp, Node **rp, int force)
r = *rp; r = *rp;
if(l->type == T || r->type == T) if(l->type == T || r->type == T)
return; return;
if(l->type->etype != TIDEAL && l->type->etype != TNIL) { if(!isideal(l->type)) {
convlit(rp, l->type); convlit(rp, l->type);
return; return;
} }
if(r->type->etype != TIDEAL && r->type->etype != TNIL) { if(!isideal(r->type)) {
convlit(lp, r->type); convlit(lp, r->type);
return; return;
} }
......
...@@ -102,7 +102,7 @@ dumpexportconst(Sym *s) ...@@ -102,7 +102,7 @@ dumpexportconst(Sym *s)
Bprint(bout, "\t"); Bprint(bout, "\t");
Bprint(bout, "const %lS", s); Bprint(bout, "const %lS", s);
if(t != T && t->etype != TIDEAL) if(t != T && !isideal(t))
Bprint(bout, " %#T", t); Bprint(bout, " %#T", t);
Bprint(bout, " = "); Bprint(bout, " = ");
......
...@@ -443,7 +443,8 @@ cgen_discard(Node *nr) ...@@ -443,7 +443,8 @@ cgen_discard(Node *nr)
switch(nr->op) { switch(nr->op) {
case ONAME: case ONAME:
gused(nr); if(!(nr->class & PHEAP))
gused(nr);
break; break;
// unary // unary
......
...@@ -630,6 +630,7 @@ EXTERN Idir* idirs; ...@@ -630,6 +630,7 @@ EXTERN Idir* idirs;
EXTERN Type* types[NTYPE]; EXTERN Type* types[NTYPE];
EXTERN Type* idealstring; EXTERN Type* idealstring;
EXTERN Type* idealbool;
EXTERN uchar simtype[NTYPE]; EXTERN uchar simtype[NTYPE];
EXTERN uchar isptr[NTYPE]; EXTERN uchar isptr[NTYPE];
EXTERN uchar isforw[NTYPE]; EXTERN uchar isforw[NTYPE];
......
...@@ -1311,15 +1311,6 @@ lexinit(void) ...@@ -1311,15 +1311,6 @@ lexinit(void)
s->def->iota = 1; s->def->iota = 1;
s->def->sym = s; s->def->sym = s;
s = pkglookup("true", "/builtin/");
s->def = nodbool(1);
s->def->sym = lookup("true");
s = pkglookup("false", "/builtin/");
s->def = nodbool(0);
s->def->sym = lookup("false");
// logically, the type of a string literal. // logically, the type of a string literal.
// types[TSTRING] is the named type string // types[TSTRING] is the named type string
// (the type of x in var x string or var x = "hello"). // (the type of x in var x string or var x = "hello").
...@@ -1327,6 +1318,17 @@ lexinit(void) ...@@ -1327,6 +1318,17 @@ lexinit(void)
// (the type of x in const x = "hello"). // (the type of x in const x = "hello").
// TODO(rsc): this may need some more thought. // TODO(rsc): this may need some more thought.
idealstring = typ(TSTRING); idealstring = typ(TSTRING);
idealbool = typ(TBOOL);
s = pkglookup("true", "/builtin/");
s->def = nodbool(1);
s->def->sym = lookup("true");
s->def->type = idealbool;
s = pkglookup("false", "/builtin/");
s->def = nodbool(0);
s->def->sym = lookup("false");
s->def->type = idealbool;
s = lookup("_"); s = lookup("_");
s->block = -100; s->block = -100;
......
...@@ -450,7 +450,7 @@ typename(Type *t) ...@@ -450,7 +450,7 @@ typename(Type *t)
Sym *s; Sym *s;
Node *n; Node *n;
if(isptr[t->etype] && t->type == T) if((isptr[t->etype] && t->type == T) || isideal(t))
fatal("typename %T", t); fatal("typename %T", t);
s = typesym(t); s = typesym(t);
if(s->def == N) { if(s->def == N) {
...@@ -482,8 +482,8 @@ dtypesym(Type *t) ...@@ -482,8 +482,8 @@ dtypesym(Type *t)
Type *t1; Type *t1;
Sym *tsym; Sym *tsym;
if(t->etype == TNIL || t->etype == TIDEAL || t == idealstring) if(isideal(t))
fatal("dtypesym ideal %T", t); fatal("dtypesym %T", t);
s = typesym(t); s = typesym(t);
if(s->flags & SymSiggen) if(s->flags & SymSiggen)
......
...@@ -462,7 +462,7 @@ nodbool(int b) ...@@ -462,7 +462,7 @@ nodbool(int b)
c = nodintconst(0); c = nodintconst(0);
c->val.ctype = CTBOOL; c->val.ctype = CTBOOL;
c->val.u.bval = b; c->val.u.bval = b;
c->type = types[TBOOL]; c->type = idealbool;
return c; return c;
} }
...@@ -992,8 +992,11 @@ Tpretty(Fmt *fp, Type *t) ...@@ -992,8 +992,11 @@ Tpretty(Fmt *fp, Type *t)
return fmtprint(fp, "%S", s); return fmtprint(fp, "%S", s);
} }
if(t->etype < nelem(basicnames) && basicnames[t->etype] != nil) if(t->etype < nelem(basicnames) && basicnames[t->etype] != nil) {
if(isideal(t) && t->etype != TIDEAL && t->etype != TNIL)
fmtprint(fp, "ideal ");
return fmtprint(fp, "%s", basicnames[t->etype]); return fmtprint(fp, "%s", basicnames[t->etype]);
}
switch(t->etype) { switch(t->etype) {
case TPTR32: case TPTR32:
...@@ -1498,9 +1501,7 @@ isideal(Type *t) ...@@ -1498,9 +1501,7 @@ isideal(Type *t)
{ {
if(t == T) if(t == T)
return 0; return 0;
if(t == idealstring) return t == idealstring || t == idealbool || t->etype == TNIL || t->etype == TIDEAL;
return 1;
return t->etype == TNIL || t->etype == TIDEAL;
} }
/* /*
......
...@@ -840,7 +840,7 @@ typecheckswitch(Node *n) ...@@ -840,7 +840,7 @@ typecheckswitch(Node *n)
if(ll->n->op == OTYPE) if(ll->n->op == OTYPE)
yyerror("type %T is not an expression", ll->n->type); yyerror("type %T is not an expression", ll->n->type);
else if(ll->n->type != T && !eqtype(ll->n->type, t)) else if(ll->n->type != T && !eqtype(ll->n->type, t))
yyerror("case %+N in switch of %+N %#O", ll->n, n->ntest, ll->n->op); yyerror("case %+N in %T switch", ll->n, t);
break; break;
case Etype: // type switch case Etype: // type switch
if(ll->n->op == OLITERAL && istype(ll->n->type, TNIL)) if(ll->n->op == OLITERAL && istype(ll->n->type, TNIL))
......
...@@ -337,7 +337,7 @@ reswitch: ...@@ -337,7 +337,7 @@ reswitch:
goto badbinary; goto badbinary;
t = l->type; t = l->type;
if(iscmp[n->op]) { if(iscmp[n->op]) {
t = types[TBOOL]; t = idealbool;
evconst(n); evconst(n);
if(n->op != OLITERAL) { if(n->op != OLITERAL) {
defaultlit2(&l, &r, 1); defaultlit2(&l, &r, 1);
...@@ -564,9 +564,11 @@ reswitch: ...@@ -564,9 +564,11 @@ reswitch:
goto error; goto error;
// TODO: more aggressive // TODO: more aggressive
n->etype = 0; n->etype = 0;
if(top & Erv) n->type = T;
if(top & Erv) {
n->op = OSENDNB; n->op = OSENDNB;
n->type = types[TBOOL]; n->type = idealbool;
}
goto ret; goto ret;
case OSLICE: case OSLICE:
...@@ -743,7 +745,7 @@ reswitch: ...@@ -743,7 +745,7 @@ reswitch:
goto error; goto error;
} }
if(n->op == OCLOSED) { if(n->op == OCLOSED) {
n->type = types[TBOOL]; n->type = idealbool;
ok |= Erv; ok |= Erv;
} else } else
ok |= Etop; ok |= Etop;
...@@ -1185,12 +1187,17 @@ nokeys(NodeList *l) ...@@ -1185,12 +1187,17 @@ nokeys(NodeList *l)
return 1; return 1;
} }
/*
* check implicit or explicit conversion from node type nt to type t.
*/
int int
checkconv(Type *nt, Type *t, int explicit, int *op, int *et) checkconv(Type *nt, Type *t, int explicit, int *op, int *et)
{ {
*op = OCONV; *op = OCONV;
*et = 0; *et = 0;
// preexisting error // preexisting error
if(t == T || t->etype == TFORW) if(t == T || t->etype == TFORW)
return 0; return 0;
...@@ -1218,6 +1225,8 @@ checkconv(Type *nt, Type *t, int explicit, int *op, int *et) ...@@ -1218,6 +1225,8 @@ checkconv(Type *nt, Type *t, int explicit, int *op, int *et)
// accept anything involving interfaces and let ifacecvt // accept anything involving interfaces and let ifacecvt
// generate a good message. some messages have to be // generate a good message. some messages have to be
// delayed anyway. // delayed anyway.
// TODO(rsc): now that everything is delayed for whole-package
// compilation, the messages could be generated right here.
if(isnilinter(t) || isnilinter(nt) || isinter(t) || isinter(nt)) { if(isnilinter(t) || isnilinter(nt) || isinter(t) || isinter(nt)) {
*et = ifaceas1(t, nt, 0); *et = ifaceas1(t, nt, 0);
*op = OCONVIFACE; *op = OCONVIFACE;
...@@ -1320,7 +1329,7 @@ typecheckconv(Node *nconv, Node *n, Type *t, int explicit) ...@@ -1320,7 +1329,7 @@ typecheckconv(Node *nconv, Node *n, Type *t, int explicit)
return n; return n;
if(n->op == OLITERAL) if(n->op == OLITERAL)
if(explicit || n->type->etype == TIDEAL || n->type == idealstring || n->type->etype == TNIL) if(explicit || isideal(n->type))
if(cvttype(t, n->type)) { if(cvttype(t, n->type)) {
// can convert literal in place // can convert literal in place
// TODO(rsc) is this needed? // TODO(rsc) is this needed?
...@@ -1346,6 +1355,9 @@ typecheckconv(Node *nconv, Node *n, Type *t, int explicit) ...@@ -1346,6 +1355,9 @@ typecheckconv(Node *nconv, Node *n, Type *t, int explicit)
return n; return n;
} }
if(op == OCONVIFACE)
defaultlit(&n, T);
if(nconv == N) if(nconv == N)
nconv = nod(OCONV, n, N); nconv = nod(OCONV, n, N);
nconv->op = op; nconv->op = op;
...@@ -1909,7 +1921,7 @@ typecheckas2(Node *n) ...@@ -1909,7 +1921,7 @@ typecheckas2(Node *n)
n->op = OAS2MAPW; n->op = OAS2MAPW;
n->rlist->n = typecheckconv(nil, r, l->type->down, 0); n->rlist->n = typecheckconv(nil, r, l->type->down, 0);
r = n->rlist->next->n; r = n->rlist->next->n;
n->rlist->next->n = typecheckconv(nil, r, types[TBOOL], 0); n->rlist->next->n = typecheckconv(nil, r, types[TBOOL], 1);
goto out; goto out;
} }
...@@ -1959,7 +1971,7 @@ typecheckas2(Node *n) ...@@ -1959,7 +1971,7 @@ typecheckas2(Node *n)
if(l->defn == n) if(l->defn == n)
l->type = r->type; l->type = r->type;
l = n->list->next->n; l = n->list->next->n;
if(l->type != T && checkconv(types[TBOOL], l->type, 0, &op, &et) < 0) if(l->type != T && checkconv(idealbool, l->type, 0, &op, &et) < 0)
yyerror("cannot assign bool value to %+N", l); yyerror("cannot assign bool value to %+N", l);
if(l->defn == n && l->ntype == N) if(l->defn == n && l->ntype == N)
l->type = types[TBOOL]; l->type = types[TBOOL];
......
...@@ -718,7 +718,7 @@ walkexpr(Node **np, NodeList **init) ...@@ -718,7 +718,7 @@ walkexpr(Node **np, NodeList **init)
if(n->etype == OANDNOT) { if(n->etype == OANDNOT) {
n->etype = OAND; n->etype = OAND;
n->right = nod(OCOM, n->right, N); n->right = nod(OCOM, n->right, N);
n->right->type = n->right->left->type; typecheck(&n->right, Erv);
goto ret; goto ret;
} }
...@@ -740,7 +740,7 @@ walkexpr(Node **np, NodeList **init) ...@@ -740,7 +740,7 @@ walkexpr(Node **np, NodeList **init)
walkexpr(&n->right, init); walkexpr(&n->right, init);
n->op = OAND; n->op = OAND;
n->right = nod(OCOM, n->right, N); n->right = nod(OCOM, n->right, N);
n->right->type = n->right->left->type; typecheck(&n->right, Erv);
goto ret; goto ret;
case ODIV: case ODIV:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment