2008-06-04 15:37:38 -06:00
|
|
|
// 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))
|
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
static Val toflt(Val);
|
|
|
|
static Val toint(Val);
|
|
|
|
static Val tostr(Val);
|
|
|
|
static void overflow(Val, Type*);
|
|
|
|
static Val copyval(Val);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* truncate float literal fv to 32-bit or 64-bit precision
|
|
|
|
* according to type.
|
|
|
|
*/
|
2008-12-02 18:03:47 -07:00
|
|
|
void
|
|
|
|
truncfltlit(Mpflt *fv, Type *t)
|
|
|
|
{
|
|
|
|
double d;
|
|
|
|
float f;
|
|
|
|
|
|
|
|
if(t == T)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// convert large precision literal floating
|
|
|
|
// into limited precision (float64 or float32)
|
|
|
|
// botch -- this assumes that compiler fp
|
|
|
|
// has same precision as runtime fp
|
|
|
|
switch(t->etype) {
|
|
|
|
case TFLOAT64:
|
|
|
|
d = mpgetflt(fv);
|
|
|
|
mpmovecflt(fv, d);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TFLOAT32:
|
|
|
|
d = mpgetflt(fv);
|
|
|
|
f = d;
|
|
|
|
d = f;
|
|
|
|
mpmovecflt(fv, d);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
/*
|
|
|
|
* convert n, if literal, to type t.
|
|
|
|
* implicit conversion.
|
|
|
|
*/
|
2008-06-04 15:37:38 -06:00
|
|
|
void
|
2009-03-12 20:04:38 -06:00
|
|
|
convlit(Node *n, Type *t)
|
|
|
|
{
|
|
|
|
convlit1(n, t, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* convert n, if literal, to type t.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
convlit1(Node *n, Type *t, int explicit)
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-03-12 20:04:38 -06:00
|
|
|
int et, ct;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
if(n == N || t == T || n->type == T)
|
|
|
|
return;
|
|
|
|
et = t->etype;
|
|
|
|
if(et == TIDEAL || et == TNIL)
|
2008-06-04 15:37:38 -06:00
|
|
|
return;
|
2008-10-29 21:25:34 -06:00
|
|
|
|
2008-08-29 14:24:53 -06:00
|
|
|
switch(n->op) {
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
case OLITERAL:
|
|
|
|
break;
|
|
|
|
case OLSH:
|
|
|
|
case ORSH:
|
|
|
|
convlit(n->left, t);
|
|
|
|
n->type = n->left->type;
|
|
|
|
return;
|
|
|
|
}
|
2008-09-04 13:21:10 -06:00
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
// avoided repeated calculations, errors
|
|
|
|
if(eqtype(n->type, t, 0)) {
|
|
|
|
n->type = t;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ct = consttype(n);
|
|
|
|
if(ct < 0)
|
|
|
|
goto bad;
|
2008-10-16 16:59:31 -06:00
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
if(et == TINTER) {
|
|
|
|
if(ct == CTNIL) {
|
|
|
|
n->type = t;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
defaultlit(n, T);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if already has non-ideal type, cannot change implicitly
|
|
|
|
if(n->type->etype != TIDEAL && n->type->etype != TNIL && !explicit)
|
|
|
|
goto bad;
|
|
|
|
|
|
|
|
switch(ct) {
|
2008-06-17 19:01:05 -06:00
|
|
|
default:
|
2009-03-12 20:04:38 -06:00
|
|
|
goto bad;
|
2008-06-17 19:01:05 -06:00
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
case CTNIL:
|
2008-12-18 22:33:45 -07:00
|
|
|
switch(et) {
|
|
|
|
default:
|
2009-03-12 20:04:38 -06:00
|
|
|
goto bad;
|
2008-12-18 22:33:45 -07:00
|
|
|
|
|
|
|
case TPTR32:
|
|
|
|
case TPTR64:
|
|
|
|
case TINTER:
|
|
|
|
case TARRAY:
|
2009-01-09 12:13:39 -07:00
|
|
|
case TMAP:
|
|
|
|
case TCHAN:
|
2009-01-30 15:39:42 -07:00
|
|
|
case TFUNC:
|
2008-10-15 18:08:10 -06:00
|
|
|
break;
|
2008-12-18 22:33:45 -07:00
|
|
|
}
|
|
|
|
break;
|
2008-06-17 23:33:32 -06:00
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
case CTSTR:
|
|
|
|
case CTBOOL:
|
|
|
|
if(et != n->type->etype)
|
|
|
|
goto bad;
|
|
|
|
break;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
case CTINT:
|
|
|
|
case CTFLT:
|
|
|
|
ct = n->val.ctype;
|
2008-06-04 15:37:38 -06:00
|
|
|
if(isint[et]) {
|
2009-03-12 20:04:38 -06:00
|
|
|
if(ct == CTFLT)
|
|
|
|
n->val = toint(n->val);
|
|
|
|
else if(ct != CTINT)
|
|
|
|
goto bad;
|
|
|
|
overflow(n->val, t);
|
|
|
|
} else if(isfloat[et]) {
|
|
|
|
if(ct == CTINT)
|
|
|
|
n->val = toflt(n->val);
|
|
|
|
else if(ct != CTFLT)
|
|
|
|
goto bad;
|
|
|
|
overflow(n->val, t);
|
|
|
|
truncfltlit(n->val.u.fval, t);
|
|
|
|
} else if(et == TSTRING && ct == CTINT && explicit)
|
|
|
|
n->val = tostr(n->val);
|
|
|
|
else
|
|
|
|
goto bad;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-06-15 21:24:30 -06:00
|
|
|
n->type = t;
|
2008-06-04 15:37:38 -06:00
|
|
|
return;
|
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
bad:
|
|
|
|
if(n->type->etype == TIDEAL)
|
|
|
|
defaultlit(n, T);
|
|
|
|
yyerror("cannot convert %T constant to %T", n->type, t);
|
|
|
|
n->type = T;
|
|
|
|
n->diag = 1;
|
2008-06-04 15:37:38 -06:00
|
|
|
return;
|
2009-03-12 20:04:38 -06:00
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
static Val
|
|
|
|
copyval(Val v)
|
|
|
|
{
|
|
|
|
Mpint *i;
|
|
|
|
Mpflt *f;
|
2008-10-16 16:59:31 -06:00
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
switch(v.ctype) {
|
|
|
|
case CTINT:
|
|
|
|
i = mal(sizeof(*i));
|
|
|
|
mpmovefixfix(i, v.u.xval);
|
|
|
|
v.u.xval = i;
|
|
|
|
break;
|
|
|
|
case CTFLT:
|
|
|
|
f = mal(sizeof(*f));
|
|
|
|
mpmovefltflt(f, v.u.fval);
|
|
|
|
v.u.fval = f;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return v;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
static Val
|
|
|
|
toflt(Val v)
|
2008-12-12 14:10:36 -07:00
|
|
|
{
|
2009-03-12 20:04:38 -06:00
|
|
|
Mpflt *f;
|
|
|
|
|
|
|
|
if(v.ctype == CTINT) {
|
|
|
|
f = mal(sizeof(*f));
|
|
|
|
mpmovefixflt(f, v.u.xval);
|
|
|
|
v.ctype = CTFLT;
|
|
|
|
v.u.fval = f;
|
|
|
|
}
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Val
|
|
|
|
toint(Val v)
|
|
|
|
{
|
|
|
|
Mpint *i;
|
|
|
|
|
|
|
|
if(v.ctype == CTFLT) {
|
|
|
|
i = mal(sizeof(*i));
|
|
|
|
if(mpmovefltfix(i, v.u.fval) < 0)
|
|
|
|
yyerror("constant %#F truncated to integer", v.u.fval);
|
|
|
|
v.ctype = CTINT;
|
|
|
|
v.u.xval = i;
|
|
|
|
}
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
overflow(Val v, Type *t)
|
|
|
|
{
|
|
|
|
// v has already been converted
|
|
|
|
// to appropriate form for t.
|
|
|
|
if(t == T || t->etype == TIDEAL)
|
|
|
|
return;
|
|
|
|
switch(v.ctype) {
|
|
|
|
case CTINT:
|
|
|
|
if(mpcmpfixfix(v.u.xval, minintval[t->etype]) < 0
|
|
|
|
|| mpcmpfixfix(v.u.xval, maxintval[t->etype]) > 0)
|
|
|
|
yyerror("constant %B overflows %T", v.u.xval, t);
|
|
|
|
break;
|
|
|
|
case CTFLT:
|
|
|
|
if(mpcmpfltflt(v.u.fval, minfltval[t->etype]) < 0
|
|
|
|
|| mpcmpfltflt(v.u.fval, maxfltval[t->etype]) > 0)
|
|
|
|
yyerror("constant %#F overflows %T", v.u.fval, t);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Val
|
|
|
|
tostr(Val v)
|
|
|
|
{
|
|
|
|
Rune rune;
|
|
|
|
int l;
|
|
|
|
String *s;
|
|
|
|
|
|
|
|
switch(v.ctype) {
|
|
|
|
case CTINT:
|
|
|
|
if(mpcmpfixfix(v.u.xval, minintval[TINT]) < 0
|
|
|
|
|| mpcmpfixfix(v.u.xval, maxintval[TINT]) > 0)
|
|
|
|
yyerror("overflow in int -> string");
|
|
|
|
rune = mpgetfix(v.u.xval);
|
|
|
|
l = runelen(rune);
|
|
|
|
s = mal(sizeof(*s)+l);
|
|
|
|
s->len = l;
|
|
|
|
runetochar((char*)s->s, &rune);
|
|
|
|
v.ctype = CTSTR;
|
|
|
|
v.u.sval = s;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CTFLT:
|
|
|
|
yyerror("no float -> string");
|
|
|
|
}
|
|
|
|
return v;
|
2008-12-12 14:10:36 -07:00
|
|
|
}
|
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
int
|
|
|
|
consttype(Node *n)
|
|
|
|
{
|
|
|
|
if(n == N || n->op != OLITERAL)
|
|
|
|
return -1;
|
|
|
|
return n->val.ctype;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
isconst(Node *n, int ct)
|
|
|
|
{
|
|
|
|
return consttype(n) == ct;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* if n is constant, rewrite as OLITERAL node.
|
|
|
|
*/
|
2008-06-04 15:37:38 -06:00
|
|
|
void
|
|
|
|
evconst(Node *n)
|
|
|
|
{
|
|
|
|
Node *nl, *nr;
|
2008-08-03 18:25:15 -06:00
|
|
|
int32 len;
|
2008-06-04 15:37:38 -06:00
|
|
|
String *str;
|
2009-03-24 17:40:38 -06:00
|
|
|
int wl, wr, lno, et;
|
2009-03-12 20:04:38 -06:00
|
|
|
Val v;
|
2009-03-24 17:40:38 -06:00
|
|
|
Mpint b;
|
2008-10-06 14:52:23 -06:00
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
nl = n->left;
|
2009-03-12 20:04:38 -06:00
|
|
|
if(nl == N || nl->type == T)
|
2008-06-04 15:37:38 -06:00
|
|
|
return;
|
2009-03-12 20:04:38 -06:00
|
|
|
if(consttype(nl) < 0)
|
2008-06-04 15:37:38 -06:00
|
|
|
return;
|
2009-03-12 20:04:38 -06:00
|
|
|
wl = nl->type->etype;
|
|
|
|
if(isint[wl] || isfloat[wl])
|
|
|
|
wl = TIDEAL;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
nr = n->right;
|
|
|
|
if(nr == N)
|
|
|
|
goto unary;
|
2009-03-12 20:04:38 -06:00
|
|
|
if(nr->type == T)
|
2008-06-04 15:37:38 -06:00
|
|
|
return;
|
2009-03-12 20:04:38 -06:00
|
|
|
if(consttype(nr) < 0)
|
|
|
|
return;
|
|
|
|
wr = nr->type->etype;
|
|
|
|
if(isint[wr] || isfloat[wr])
|
|
|
|
wr = TIDEAL;
|
|
|
|
|
|
|
|
// check for compatible general types (numeric, string, etc)
|
|
|
|
if(wl != wr)
|
|
|
|
goto illegal;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
// check for compatible types.
|
|
|
|
switch(n->op) {
|
|
|
|
default:
|
|
|
|
// ideal const mixes with anything but otherwise must match.
|
|
|
|
if(nl->type->etype != TIDEAL)
|
|
|
|
defaultlit(nr, nl->type);
|
|
|
|
if(nr->type->etype != TIDEAL)
|
|
|
|
defaultlit(nl, nr->type);
|
|
|
|
if(nl->type->etype != nr->type->etype)
|
|
|
|
goto illegal;
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2008-06-15 21:24:30 -06:00
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
case OLSH:
|
|
|
|
case ORSH:
|
|
|
|
// right must be unsigned.
|
|
|
|
// left can be ideal.
|
|
|
|
defaultlit(nr, types[TUINT]);
|
|
|
|
break;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
// copy numeric value to avoid modifying
|
|
|
|
// n->left, in case someone still refers to it (e.g. iota).
|
|
|
|
v = nl->val;
|
|
|
|
if(wl == TIDEAL)
|
|
|
|
v = copyval(v);
|
|
|
|
|
|
|
|
// since wl == wr,
|
|
|
|
// the only way v.ctype != nr->val.ctype
|
|
|
|
// is when one is CTINT and the other CTFLT.
|
|
|
|
// make both CTFLT.
|
|
|
|
if(v.ctype != nr->val.ctype) {
|
|
|
|
v = toflt(v);
|
|
|
|
nr->val = toflt(nr->val);
|
2008-08-08 18:13:31 -06:00
|
|
|
}
|
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
// run op
|
|
|
|
switch(TUP(n->op, v.ctype)) {
|
2008-06-04 15:37:38 -06:00
|
|
|
default:
|
2009-03-12 20:04:38 -06:00
|
|
|
illegal:
|
|
|
|
yyerror("illegal constant expression %T %O %T",
|
|
|
|
nl->type, n->op, nr->type);
|
|
|
|
n->diag = 1;
|
2008-06-04 15:37:38 -06:00
|
|
|
return;
|
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OADD, CTINT):
|
|
|
|
mpaddfixfix(v.u.xval, nr->val.u.xval);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OSUB, CTINT):
|
|
|
|
mpsubfixfix(v.u.xval, nr->val.u.xval);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OMUL, CTINT):
|
|
|
|
mpmulfixfix(v.u.xval, nr->val.u.xval);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(ODIV, CTINT):
|
|
|
|
if(mpcmpfixc(nr->val.u.xval, 0) == 0) {
|
|
|
|
yyerror("division by zero");
|
|
|
|
mpmovecfix(v.u.xval, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mpdivfixfix(v.u.xval, nr->val.u.xval);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OMOD, CTINT):
|
|
|
|
if(mpcmpfixc(nr->val.u.xval, 0) == 0) {
|
|
|
|
yyerror("division by zero");
|
|
|
|
mpmovecfix(v.u.xval, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mpmodfixfix(v.u.xval, nr->val.u.xval);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2008-08-08 18:13:31 -06:00
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OLSH, CTINT):
|
|
|
|
mplshfixfix(v.u.xval, nr->val.u.xval);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(ORSH, CTINT):
|
|
|
|
mprshfixfix(v.u.xval, nr->val.u.xval);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OOR, CTINT):
|
|
|
|
mporfixfix(v.u.xval, nr->val.u.xval);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OAND, CTINT):
|
|
|
|
mpandfixfix(v.u.xval, nr->val.u.xval);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OANDNOT, CTINT):
|
|
|
|
mpandnotfixfix(v.u.xval, nr->val.u.xval);
|
2009-03-11 20:59:35 -06:00
|
|
|
break;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OXOR, CTINT):
|
|
|
|
mpxorfixfix(v.u.xval, nr->val.u.xval);
|
2008-07-27 14:09:15 -06:00
|
|
|
break;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OADD, CTFLT):
|
|
|
|
mpaddfltflt(v.u.fval, nr->val.u.fval);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OSUB, CTFLT):
|
|
|
|
mpsubfltflt(v.u.fval, nr->val.u.fval);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OMUL, CTFLT):
|
|
|
|
mpmulfltflt(v.u.fval, nr->val.u.fval);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(ODIV, CTFLT):
|
|
|
|
if(mpcmpfltc(nr->val.u.fval, 0) == 0) {
|
|
|
|
yyerror("division by zero");
|
|
|
|
mpmovecflt(v.u.fval, 1.0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mpdivfltflt(v.u.fval, nr->val.u.fval);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OEQ, CTNIL):
|
2008-12-09 18:52:41 -07:00
|
|
|
goto settrue;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(ONE, CTNIL):
|
2008-12-09 18:52:41 -07:00
|
|
|
goto setfalse;
|
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OEQ, CTINT):
|
|
|
|
if(mpcmpfixfix(v.u.xval, nr->val.u.xval) == 0)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(ONE, CTINT):
|
|
|
|
if(mpcmpfixfix(v.u.xval, nr->val.u.xval) != 0)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OLT, CTINT):
|
|
|
|
if(mpcmpfixfix(v.u.xval, nr->val.u.xval) < 0)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OLE, CTINT):
|
|
|
|
if(mpcmpfixfix(v.u.xval, nr->val.u.xval) <= 0)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OGE, CTINT):
|
|
|
|
if(mpcmpfixfix(v.u.xval, nr->val.u.xval) >= 0)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OGT, CTINT):
|
|
|
|
if(mpcmpfixfix(v.u.xval, nr->val.u.xval) > 0)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OEQ, CTFLT):
|
|
|
|
if(mpcmpfltflt(v.u.fval, nr->val.u.fval) == 0)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(ONE, CTFLT):
|
|
|
|
if(mpcmpfltflt(v.u.fval, nr->val.u.fval) != 0)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OLT, CTFLT):
|
|
|
|
if(mpcmpfltflt(v.u.fval, nr->val.u.fval) < 0)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OLE, CTFLT):
|
|
|
|
if(mpcmpfltflt(v.u.fval, nr->val.u.fval) <= 0)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OGE, CTFLT):
|
|
|
|
if(mpcmpfltflt(v.u.fval, nr->val.u.fval) >= 0)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OGT, CTFLT):
|
|
|
|
if(mpcmpfltflt(v.u.fval, nr->val.u.fval) > 0)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OEQ, CTSTR):
|
2008-06-04 15:37:38 -06:00
|
|
|
if(cmpslit(nl, nr) == 0)
|
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(ONE, CTSTR):
|
2008-06-04 15:37:38 -06:00
|
|
|
if(cmpslit(nl, nr) != 0)
|
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OLT, CTSTR):
|
2008-06-04 15:37:38 -06:00
|
|
|
if(cmpslit(nl, nr) < 0)
|
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OLE, CTSTR):
|
2008-06-04 15:37:38 -06:00
|
|
|
if(cmpslit(nl, nr) <= 0)
|
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OGE, CTSTR):
|
2008-06-04 15:37:38 -06:00
|
|
|
if(cmpslit(nl, nr) >= 0l)
|
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OGT, CTSTR):
|
2008-06-04 15:37:38 -06:00
|
|
|
if(cmpslit(nl, nr) > 0)
|
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OADD, CTSTR):
|
|
|
|
len = v.u.sval->len + nr->val.u.sval->len;
|
2008-06-04 15:37:38 -06:00
|
|
|
str = mal(sizeof(*str) + len);
|
|
|
|
str->len = len;
|
2009-03-12 20:04:38 -06:00
|
|
|
memcpy(str->s, v.u.sval->s, v.u.sval->len);
|
|
|
|
memcpy(str->s+v.u.sval->len, nr->val.u.sval->s, nr->val.u.sval->len);
|
2008-06-04 15:37:38 -06:00
|
|
|
str->len = len;
|
2009-03-12 20:04:38 -06:00
|
|
|
v.u.sval = str;
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OOROR, CTBOOL):
|
|
|
|
if(v.u.bval || nr->val.u.bval)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OANDAND, CTBOOL):
|
|
|
|
if(v.u.bval && nr->val.u.bval)
|
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
|
|
|
case TUP(OEQ, CTBOOL):
|
|
|
|
if(v.u.bval == nr->val.u.bval)
|
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
|
|
|
case TUP(ONE, CTBOOL):
|
|
|
|
if(v.u.bval != nr->val.u.bval)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
|
|
|
}
|
2008-08-09 18:29:26 -06:00
|
|
|
goto ret;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
unary:
|
2009-03-12 20:04:38 -06:00
|
|
|
// copy numeric value to avoid modifying
|
|
|
|
// nl, in case someone still refers to it (e.g. iota).
|
|
|
|
v = nl->val;
|
|
|
|
if(wl == TIDEAL)
|
|
|
|
v = copyval(v);
|
2008-08-09 18:29:26 -06:00
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
switch(TUP(n->op, v.ctype)) {
|
2008-06-04 15:37:38 -06:00
|
|
|
default:
|
2009-03-12 20:04:38 -06:00
|
|
|
yyerror("illegal constant expression %O %T %d", n->op, nl->type, v.ctype);
|
2008-06-04 15:37:38 -06:00
|
|
|
return;
|
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OPLUS, CTINT):
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OMINUS, CTINT):
|
|
|
|
mpnegfix(v.u.xval);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OCOM, CTINT):
|
2009-03-24 17:40:38 -06:00
|
|
|
et = Txxx;
|
|
|
|
if(nl->type != T)
|
|
|
|
et = nl->type->etype;
|
|
|
|
|
|
|
|
// calculate the mask in b
|
|
|
|
// result will be (a ^ mask)
|
|
|
|
switch(et) {
|
|
|
|
default:
|
|
|
|
mpmovecfix(&b, -1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TINT8:
|
|
|
|
case TINT16:
|
|
|
|
case TINT32:
|
|
|
|
case TINT64:
|
|
|
|
case TINT:
|
|
|
|
et++; // convert to unsigned
|
|
|
|
// fallthrough
|
|
|
|
case TUINT8:
|
|
|
|
case TUINT16:
|
|
|
|
case TUINT32:
|
|
|
|
case TUINT64:
|
|
|
|
case TUINT:
|
|
|
|
case TUINTPTR:
|
|
|
|
mpmovefixfix(&b, maxintval[et]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mpxorfixfix(v.u.xval, &b);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OPLUS, CTFLT):
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(OMINUS, CTFLT):
|
|
|
|
mpnegflt(v.u.fval);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
case TUP(ONOT, CTBOOL):
|
|
|
|
if(!v.u.bval)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto settrue;
|
|
|
|
goto setfalse;
|
|
|
|
}
|
2008-08-09 18:29:26 -06:00
|
|
|
|
|
|
|
ret:
|
2009-03-12 20:04:38 -06:00
|
|
|
// rewrite n in place.
|
2008-06-04 15:37:38 -06:00
|
|
|
*n = *nl;
|
2009-03-12 20:04:38 -06:00
|
|
|
n->val = v;
|
|
|
|
|
|
|
|
// lose type name if any:
|
|
|
|
// type T int
|
|
|
|
// const A T = 1;
|
|
|
|
// A+0 has type int, not T.
|
|
|
|
n->type = types[n->type->etype];
|
|
|
|
|
|
|
|
// check range.
|
|
|
|
lno = lineno;
|
|
|
|
lineno = n->lineno;
|
|
|
|
overflow(v, n->type);
|
|
|
|
lineno = lno;
|
|
|
|
|
|
|
|
// truncate precision for non-ideal float.
|
|
|
|
if(v.ctype == CTFLT && n->type->etype != TIDEAL)
|
|
|
|
truncfltlit(v.u.fval, n->type);
|
|
|
|
return;
|
|
|
|
|
|
|
|
settrue:
|
|
|
|
*n = *nodbool(1);
|
|
|
|
return;
|
|
|
|
|
|
|
|
setfalse:
|
|
|
|
*n = *nodbool(0);
|
|
|
|
return;
|
|
|
|
}
|
2008-08-09 18:29:26 -06:00
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
Node*
|
|
|
|
nodlit(Val v)
|
|
|
|
{
|
|
|
|
Node *n;
|
|
|
|
|
|
|
|
n = nod(OLITERAL, N, N);
|
|
|
|
n->val = v;
|
|
|
|
switch(v.ctype) {
|
|
|
|
default:
|
|
|
|
fatal("nodlit ctype %d", v.ctype);
|
|
|
|
case CTSTR:
|
|
|
|
n->type = types[TSTRING];
|
|
|
|
break;
|
|
|
|
case CTBOOL:
|
|
|
|
n->type = types[TBOOL];
|
|
|
|
break;
|
|
|
|
case CTINT:
|
|
|
|
case CTFLT:
|
|
|
|
n->type = types[TIDEAL];
|
|
|
|
break;
|
|
|
|
case CTNIL:
|
|
|
|
n->type = types[TNIL];
|
|
|
|
break;
|
2008-08-09 18:29:26 -06:00
|
|
|
}
|
2009-03-12 20:04:38 -06:00
|
|
|
return n;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-03-12 20:04:38 -06:00
|
|
|
defaultlit(Node *n, Type *t)
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-03-12 20:04:38 -06:00
|
|
|
int lno;
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
if(n == N)
|
|
|
|
return;
|
2009-03-12 20:04:38 -06:00
|
|
|
if(n->type == T || n->type->etype != TIDEAL)
|
2008-06-04 15:37:38 -06:00
|
|
|
return;
|
2009-03-12 20:04:38 -06:00
|
|
|
|
|
|
|
switch(n->op) {
|
|
|
|
case OLITERAL:
|
|
|
|
break;
|
|
|
|
case OLSH:
|
|
|
|
case ORSH:
|
|
|
|
defaultlit(n->left, t);
|
|
|
|
n->type = n->left->type;
|
2008-06-04 15:37:38 -06:00
|
|
|
return;
|
2009-03-12 20:04:38 -06:00
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-03-12 20:04:38 -06:00
|
|
|
lno = lineno;
|
|
|
|
lineno = n->lineno;
|
2008-06-04 15:37:38 -06:00
|
|
|
switch(n->val.ctype) {
|
|
|
|
default:
|
|
|
|
yyerror("defaultlit: unknown literal: %N", n);
|
|
|
|
break;
|
|
|
|
case CTINT:
|
2008-10-29 13:46:44 -06:00
|
|
|
n->type = types[TINT];
|
2009-03-12 20:04:38 -06:00
|
|
|
if(t != T) {
|
|
|
|
if(isint[t->etype])
|
|
|
|
n->type = t;
|
|
|
|
else if(isfloat[t->etype]) {
|
|
|
|
n->type = t;
|
|
|
|
n->val = toflt(n->val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
overflow(n->val, n->type);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
case CTFLT:
|
2008-10-29 13:46:44 -06:00
|
|
|
n->type = types[TFLOAT];
|
2009-03-12 20:04:38 -06:00
|
|
|
if(t != T) {
|
|
|
|
if(isfloat[t->etype])
|
|
|
|
n->type = t;
|
|
|
|
else if(isint[t->etype]) {
|
|
|
|
n->type = t;
|
|
|
|
n->val = toint(n->val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
overflow(n->val, n->type);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
}
|
2009-03-12 20:04:38 -06:00
|
|
|
lineno = lno;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* defaultlit on both nodes simultaneously;
|
|
|
|
* if they're both ideal going in they better
|
|
|
|
* get the same type going out.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
defaultlit2(Node *l, Node *r)
|
|
|
|
{
|
|
|
|
if(l->type == T || r->type == T)
|
|
|
|
return;
|
|
|
|
if(l->type->etype != TIDEAL && l->type->etype != TNIL) {
|
|
|
|
convlit(r, l->type);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(r->type->etype != TIDEAL && r->type->etype != TNIL) {
|
|
|
|
convlit(l, r->type);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(isconst(l, CTFLT) || isconst(r, CTFLT)) {
|
|
|
|
convlit(l, types[TFLOAT]);
|
|
|
|
convlit(r, types[TFLOAT]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
convlit(l, types[TINT]);
|
|
|
|
convlit(r, types[TINT]);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
cmpslit(Node *l, Node *r)
|
|
|
|
{
|
2008-08-03 18:25:15 -06:00
|
|
|
int32 l1, l2, i, m;
|
2008-06-04 15:37:38 -06:00
|
|
|
char *s1, *s2;
|
|
|
|
|
2008-08-08 18:13:31 -06:00
|
|
|
l1 = l->val.u.sval->len;
|
|
|
|
l2 = r->val.u.sval->len;
|
|
|
|
s1 = l->val.u.sval->s;
|
|
|
|
s2 = r->val.u.sval->s;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
m = l1;
|
|
|
|
if(l2 < m)
|
|
|
|
m = l2;
|
|
|
|
|
|
|
|
for(i=0; i<m; i++) {
|
|
|
|
if(s1[i] == s2[i])
|
|
|
|
continue;
|
|
|
|
if(s1[i] > s2[i])
|
|
|
|
return +1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if(l1 == l2)
|
|
|
|
return 0;
|
|
|
|
if(l1 > l2)
|
|
|
|
return +1;
|
|
|
|
return -1;
|
|
|
|
}
|
2008-12-14 19:45:00 -07:00
|
|
|
|
|
|
|
int
|
|
|
|
smallintconst(Node *n)
|
|
|
|
{
|
|
|
|
if(n->op == OLITERAL)
|
|
|
|
switch(simtype[n->type->etype]) {
|
|
|
|
case TINT8:
|
|
|
|
case TUINT8:
|
|
|
|
case TINT16:
|
|
|
|
case TUINT16:
|
|
|
|
case TINT32:
|
|
|
|
case TUINT32:
|
|
|
|
case TBOOL:
|
|
|
|
case TPTR32:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|