// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. #include "go.h" #define TUP(x,y) (((x)<<16)|(y)) void convlit(Node *n, Type *t) { int et; if(n == N || t == T) return; switch(n->op) { default: return; case OLITERAL: break; case OLSH: case ORSH: convlit(n->left, t); n->type = n->left->type; return; } et = t->etype; switch(et) { case TARRAY: case TFUNC: case TCHAN: case TMAP: // case TPTR32: // case TPTR64: return; } switch(whatis(n)) { default: goto bad1; case Wlitnil: if(!isptr[et] && et != TINTER) goto bad1; if(isptrto(t, TSTRING)) goto bad1; break; case Wlitstr: if(isptrto(t, TSTRING)) break; goto bad1; case Wlitbool: if(et == TBOOL) break; goto bad1; case Wlitint: if(isptrto(t, TSTRING)) { Rune rune; int l; String *s; rune = mpgetfix(n->val.u.xval); l = runelen(rune); s = mal(sizeof(*s)+l); s->len = l; runetochar((char*)(s->s), &rune); n->val.u.sval = s; n->val.ctype = CTSTR; break; } if(isint[et]) { // int to int if(mpcmpfixfix(n->val.u.xval, minintval[et]) < 0) goto bad2; if(mpcmpfixfix(n->val.u.xval, maxintval[et]) > 0) goto bad2; break; } if(isfloat[et]) { Mpint *xv; // int to float xv = n->val.u.xval; if(mpcmpfixflt(xv, minfltval[et]) < 0) goto bad2; if(mpcmpfixflt(xv, maxfltval[et]) > 0) goto bad2; n->val.u.fval = mal(sizeof(*n->val.u.fval)); mpmovefixflt(n->val.u.fval, xv); n->val.ctype = CTFLT; break; } goto bad1; case Wlitfloat: if(isint[et]) { Mpflt *fv; // float to int fv = n->val.u.fval; if(mpcmpfltfix(fv, minintval[et]) < 0) goto bad2; if(mpcmpfltfix(fv, maxintval[et]) > 0) goto bad2; n->val.u.xval = mal(sizeof(*n->val.u.xval)); mpmovefltfix(n->val.u.xval, fv); n->val.ctype = CTINT; break; } if(isfloat[et]) { // float to float if(mpcmpfltflt(n->val.u.fval, minfltval[et]) < 0) goto bad2; if(mpcmpfltflt(n->val.u.fval, maxfltval[et]) > 0) goto bad2; break; } goto bad1; } n->type = t; return; bad1: yyerror("illegal conversion of constant to %T", t); return; bad2: yyerror("overflow converting constant to %T", t); return; } void evconst(Node *n) { Node *nl, *nr; int32 len; String *str; int wl, wr; Mpint *xval; Mpflt *fval; nl = n->left; if(nl == N) return; wl = whatis(nl); switch(wl) { default: return; case Wlitint: case Wlitfloat: case Wlitbool: case Wlitstr: break; } nr = n->right; if(nr == N) goto unary; wr = whatis(nr); switch(wr) { default: return; case Wlitint: case Wlitfloat: case Wlitbool: case Wlitstr: break; } if(wl != wr) { if(wl == Wlitfloat && wr == Wlitint) { xval = nr->val.u.xval; nr->val.u.fval = mal(sizeof(*nr->val.u.fval)); mpmovefixflt(nr->val.u.fval, xval); nr->val.ctype = CTFLT; wr = whatis(nr); } else if(wl == Wlitint && wr == Wlitfloat) { xval = nl->val.u.xval; nl->val.u.fval = mal(sizeof(*nl->val.u.fval)); mpmovefixflt(nl->val.u.fval, xval); nl->val.ctype = CTFLT; wl = whatis(nl); } else { yyerror("illegal combination of literals %E %E", nl->etype, nr->etype); return; } } // dance to not modify left side // this is because iota will reuse it if(wl == Wlitint) { xval = mal(sizeof(*xval)); mpmovefixfix(xval, nl->val.u.xval); } else if(wl == Wlitfloat) { fval = mal(sizeof(*fval)); mpmovefltflt(fval, nl->val.u.fval); } switch(TUP(n->op, wl)) { default: yyerror("illegal combination of literals %O %E", n->op, nl->etype); return; case TUP(OADD, Wlitint): mpaddfixfix(xval, nr->val.u.xval); break; case TUP(OSUB, Wlitint): mpsubfixfix(xval, nr->val.u.xval); break; case TUP(OMUL, Wlitint): mpmulfixfix(xval, nr->val.u.xval); break; case TUP(ODIV, Wlitint): mpdivfixfix(xval, nr->val.u.xval); break; case TUP(OMOD, Wlitint): mpmodfixfix(xval, nr->val.u.xval); break; case TUP(OLSH, Wlitint): mplshfixfix(xval, nr->val.u.xval); break; case TUP(ORSH, Wlitint): mprshfixfix(xval, nr->val.u.xval); break; case TUP(OOR, Wlitint): mporfixfix(xval, nr->val.u.xval); break; case TUP(OAND, Wlitint): mpandfixfix(xval, nr->val.u.xval); break; case TUP(OXOR, Wlitint): mpxorfixfix(xval, nr->val.u.xval); break; case TUP(OADD, Wlitfloat): mpaddfltflt(fval, nr->val.u.fval); break; case TUP(OSUB, Wlitfloat): mpsubfltflt(fval, nr->val.u.fval); break; case TUP(OMUL, Wlitfloat): mpmulfltflt(fval, nr->val.u.fval); break; case TUP(ODIV, Wlitfloat): mpdivfltflt(fval, nr->val.u.fval); break; case TUP(OEQ, Wlitint): if(mpcmpfixfix(xval, nr->val.u.xval) == 0) goto settrue; goto setfalse; case TUP(ONE, Wlitint): if(mpcmpfixfix(xval, nr->val.u.xval) != 0) goto settrue; goto setfalse; case TUP(OLT, Wlitint): if(mpcmpfixfix(xval, nr->val.u.xval) < 0) goto settrue; goto setfalse; case TUP(OLE, Wlitint): if(mpcmpfixfix(xval, nr->val.u.xval) <= 0) goto settrue; goto setfalse; case TUP(OGE, Wlitint): if(mpcmpfixfix(xval, nr->val.u.xval) >= 0) goto settrue; goto setfalse; case TUP(OGT, Wlitint): if(mpcmpfixfix(xval, nr->val.u.xval) > 0) goto settrue; goto setfalse; case TUP(OEQ, Wlitfloat): if(mpcmpfltflt(fval, nr->val.u.fval) == 0) goto settrue; goto setfalse; case TUP(ONE, Wlitfloat): if(mpcmpfltflt(fval, nr->val.u.fval) != 0) goto settrue; goto setfalse; case TUP(OLT, Wlitfloat): if(mpcmpfltflt(fval, nr->val.u.fval) < 0) goto settrue; goto setfalse; case TUP(OLE, Wlitfloat): if(mpcmpfltflt(fval, nr->val.u.fval) <= 0) goto settrue; goto setfalse; case TUP(OGE, Wlitfloat): if(mpcmpfltflt(fval, nr->val.u.fval) >= 0) goto settrue; goto setfalse; case TUP(OGT, Wlitfloat): if(mpcmpfltflt(fval, nr->val.u.fval) > 0) goto settrue; goto setfalse; case TUP(OEQ, Wlitstr): if(cmpslit(nl, nr) == 0) goto settrue; goto setfalse; case TUP(ONE, Wlitstr): if(cmpslit(nl, nr) != 0) goto settrue; goto setfalse; case TUP(OLT, Wlitstr): if(cmpslit(nl, nr) < 0) goto settrue; goto setfalse; case TUP(OLE, Wlitstr): if(cmpslit(nl, nr) <= 0) goto settrue; goto setfalse; case TUP(OGE, Wlitstr): if(cmpslit(nl, nr) >= 0l) goto settrue; goto setfalse; case TUP(OGT, Wlitstr): if(cmpslit(nl, nr) > 0) goto settrue; goto setfalse; case TUP(OADD, Wlitstr): len = nl->val.u.sval->len + nr->val.u.sval->len; str = mal(sizeof(*str) + len); str->len = len; memcpy(str->s, nl->val.u.sval->s, nl->val.u.sval->len); memcpy(str->s+nl->val.u.sval->len, nr->val.u.sval->s, nr->val.u.sval->len); str->len = len; nl->val.u.sval = str; break; case TUP(OOROR, Wlitbool): if(nl->val.u.bval || nr->val.u.bval) goto settrue; goto setfalse; case TUP(OANDAND, Wlitbool): if(nl->val.u.bval && nr->val.u.bval) goto settrue; goto setfalse; } goto ret; settrue: *n = *booltrue; return; setfalse: *n = *boolfalse; return; unary: if(wl == Wlitint) { xval = mal(sizeof(*xval)); mpmovefixfix(xval, nl->val.u.xval); } else if(wl == Wlitfloat) { fval = mal(sizeof(*fval)); mpmovefltflt(fval, nl->val.u.fval); } switch(TUP(n->op, wl)) { default: yyerror("illegal combination of literals %O %d", n->op, wl); return; case TUP(OPLUS, Wlitint): break; case TUP(OMINUS, Wlitint): mpnegfix(xval); break; case TUP(OCOM, Wlitint): mpcomfix(xval); break; case TUP(OPLUS, Wlitfloat): break; case TUP(OMINUS, Wlitfloat): mpnegflt(fval); break; case TUP(ONOT, Wlitbool): if(nl->val.u.bval) goto settrue; goto setfalse; } ret: *n = *nl; // second half of dance if(wl == Wlitint) { n->val.u.xval = xval; } else if(wl == Wlitfloat) { n->val.u.fval = fval; } } void defaultlit(Node *n) { if(n == N) return; if(n->type != T) return; if(n->op != OLITERAL) return; switch(n->val.ctype) { default: yyerror("defaultlit: unknown literal: %N", n); break; case CTINT: case CTSINT: case CTUINT: n->type = types[TINT32]; break; case CTFLT: n->type = types[TFLOAT64]; break; case CTBOOL: n->type = types[TBOOL]; break; case CTSTR: n->type = types[TSTRING]; break; } } int cmpslit(Node *l, Node *r) { int32 l1, l2, i, m; char *s1, *s2; l1 = l->val.u.sval->len; l2 = r->val.u.sval->len; s1 = l->val.u.sval->s; s2 = r->val.u.sval->s; m = l1; if(l2 < m) m = l2; for(i=0; i s2[i]) return +1; return -1; } if(l1 == l2) return 0; if(l1 > l2) return +1; return -1; }