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
|
2009-05-27 11:16:13 -06:00
|
|
|
* according to type; return truncated value.
|
2009-03-12 20:04:38 -06:00
|
|
|
*/
|
2009-05-27 11:16:13 -06:00
|
|
|
Mpflt*
|
|
|
|
truncfltlit(Mpflt *oldv, Type *t)
|
2008-12-02 18:03:47 -07:00
|
|
|
{
|
|
|
|
double d;
|
|
|
|
float f;
|
2009-05-27 11:16:13 -06:00
|
|
|
Mpflt *fv;
|
2008-12-02 18:03:47 -07:00
|
|
|
|
|
|
|
if(t == T)
|
2009-05-27 11:16:13 -06:00
|
|
|
return oldv;
|
|
|
|
|
|
|
|
fv = mal(sizeof *fv);
|
|
|
|
*fv = *oldv;
|
2008-12-02 18:03:47 -07:00
|
|
|
|
|
|
|
// 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-05-27 11:16:13 -06:00
|
|
|
return fv;
|
2008-12-02 18:03:47 -07:00
|
|
|
}
|
|
|
|
|
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-07-17 14:38:16 -06:00
|
|
|
convlit(Node **np, Type *t)
|
2009-03-12 20:04:38 -06:00
|
|
|
{
|
2009-07-17 14:38:16 -06:00
|
|
|
return convlit1(np, t, 0);
|
2009-03-12 20:04:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* convert n, if literal, to type t.
|
2009-07-17 14:38:16 -06:00
|
|
|
* return a new node if necessary
|
|
|
|
* (if n is a named constant, can't edit n->type directly).
|
2009-03-12 20:04:38 -06:00
|
|
|
*/
|
|
|
|
void
|
2009-07-17 14:38:16 -06:00
|
|
|
convlit1(Node **np, Type *t, int explicit)
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-08-27 12:16:34 -06:00
|
|
|
int ct, et;
|
2009-07-17 14:38:16 -06:00
|
|
|
Node *n, *nn;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-07-17 14:38:16 -06:00
|
|
|
n = *np;
|
2009-09-21 16:45:55 -06:00
|
|
|
if(n == N || t == T || n->type == T || isideal(t) || n->type == t)
|
2009-03-12 20:04:38 -06:00
|
|
|
return;
|
2009-08-27 12:16:34 -06:00
|
|
|
if(!explicit && !isideal(n->type))
|
2009-08-24 14:41:47 -06:00
|
|
|
return;
|
2009-07-17 14:38:16 -06:00
|
|
|
|
|
|
|
//dump("convlit1", n);
|
|
|
|
if(n->op == OLITERAL) {
|
|
|
|
nn = nod(OXXX, N, N);
|
|
|
|
*nn = *n;
|
|
|
|
n = nn;
|
|
|
|
*np = n;
|
|
|
|
}
|
|
|
|
//dump("convlit2", n);
|
2008-10-29 21:25:34 -06:00
|
|
|
|
2008-08-29 14:24:53 -06:00
|
|
|
switch(n->op) {
|
|
|
|
default:
|
2009-07-30 17:53:08 -06:00
|
|
|
if(n->type->etype == TIDEAL) {
|
|
|
|
convlit(&n->left, t);
|
|
|
|
convlit(&n->right, t);
|
|
|
|
n->type = t;
|
|
|
|
}
|
2008-08-29 14:24:53 -06:00
|
|
|
return;
|
|
|
|
case OLITERAL:
|
|
|
|
break;
|
|
|
|
case OLSH:
|
|
|
|
case ORSH:
|
2009-07-30 17:53:08 -06:00
|
|
|
convlit(&n->left, t);
|
2009-08-23 19:09:44 -06:00
|
|
|
t = n->left->type;
|
|
|
|
if(t != T && !isint[t->etype]) {
|
|
|
|
yyerror("invalid operation: %#N (shift of type %T)", n, t);
|
|
|
|
t = T;
|
|
|
|
}
|
|
|
|
n->type = t;
|
2008-08-29 14:24:53 -06:00
|
|
|
return;
|
|
|
|
}
|
2009-03-12 20:04:38 -06:00
|
|
|
// avoided repeated calculations, errors
|
2009-06-25 17:32:33 -06:00
|
|
|
if(cvttype(n->type, t) == 1) {
|
2009-03-12 20:04:38 -06:00
|
|
|
n->type = t;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ct = consttype(n);
|
|
|
|
if(ct < 0)
|
|
|
|
goto bad;
|
2008-10-16 16:59:31 -06:00
|
|
|
|
2009-08-27 12:16:34 -06:00
|
|
|
et = t->etype;
|
2009-03-12 20:04:38 -06:00
|
|
|
if(et == TINTER) {
|
2009-07-06 22:37:29 -06:00
|
|
|
if(ct == CTNIL && n->type == types[TNIL]) {
|
2009-03-12 20:04:38 -06:00
|
|
|
n->type = t;
|
|
|
|
return;
|
|
|
|
}
|
2009-07-17 14:38:16 -06:00
|
|
|
defaultlit(np, T);
|
2009-03-12 20:04:38 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
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-09-09 02:21:20 -06:00
|
|
|
yyerror("cannot use nil as %T", t);
|
|
|
|
n->type = T;
|
2009-03-12 20:04:38 -06:00
|
|
|
goto bad;
|
2008-12-18 22:33:45 -07:00
|
|
|
|
2009-05-29 14:44:30 -06:00
|
|
|
case TSTRING:
|
|
|
|
// let normal conversion code handle it
|
|
|
|
return;
|
|
|
|
|
2009-07-27 18:24:07 -06:00
|
|
|
case TARRAY:
|
|
|
|
if(!isslice(t))
|
|
|
|
goto bad;
|
|
|
|
break;
|
|
|
|
|
2008-12-18 22:33:45 -07:00
|
|
|
case TPTR32:
|
|
|
|
case TPTR64:
|
|
|
|
case TINTER:
|
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);
|
2009-05-27 11:16:13 -06:00
|
|
|
n->val.u.fval = truncfltlit(n->val.u.fval, t);
|
2009-03-12 20:04:38 -06:00
|
|
|
} 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:
|
2009-08-27 12:16:34 -06:00
|
|
|
if(isideal(n->type)) {
|
2009-07-17 14:38:16 -06:00
|
|
|
defaultlit(&n, T);
|
|
|
|
*np = n;
|
|
|
|
}
|
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:
|
2009-07-30 17:53:08 -06:00
|
|
|
if(!isint[t->etype])
|
|
|
|
fatal("overflow: %T integer constant", t);
|
2009-03-12 20:04:38 -06:00
|
|
|
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:
|
2009-07-30 17:53:08 -06:00
|
|
|
if(!isfloat[t->etype])
|
|
|
|
fatal("overflow: %T floating-point constant", t);
|
2009-03-12 20:04:38 -06:00
|
|
|
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;
|
2009-04-09 19:16:21 -06:00
|
|
|
Strlit *s;
|
2009-03-12 20:04:38 -06:00
|
|
|
|
|
|
|
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);
|
2009-09-21 16:45:55 -06:00
|
|
|
memset(&v, 0, sizeof v);
|
2009-03-12 20:04:38 -06:00
|
|
|
v.ctype = CTSTR;
|
|
|
|
v.u.sval = s;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CTFLT:
|
|
|
|
yyerror("no float -> string");
|
2009-09-21 16:45:55 -06:00
|
|
|
|
|
|
|
case CTNIL:
|
|
|
|
memset(&v, 0, sizeof v);
|
|
|
|
v.ctype = CTSTR;
|
|
|
|
v.u.sval = mal(sizeof *s);
|
|
|
|
break;
|
2009-03-12 20:04:38 -06:00
|
|
|
}
|
|
|
|
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;
|
2009-04-09 19:16:21 -06:00
|
|
|
Strlit *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
|
|
|
|
2009-07-30 17:53:08 -06:00
|
|
|
switch(n->op) {
|
|
|
|
case OMAKE:
|
2009-08-03 12:58:52 -06:00
|
|
|
case OMAKEMAP:
|
|
|
|
case OMAKESLICE:
|
|
|
|
case OMAKECHAN:
|
2009-08-07 13:50:26 -06:00
|
|
|
case ODCLCONST:
|
2009-07-30 17:53:08 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
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.
|
2009-07-17 14:38:16 -06:00
|
|
|
if(nl->type->etype != TIDEAL) {
|
|
|
|
defaultlit(&nr, nl->type);
|
|
|
|
n->right = nr;
|
|
|
|
}
|
|
|
|
if(nr->type->etype != TIDEAL) {
|
|
|
|
defaultlit(&nl, nr->type);
|
|
|
|
n->left = nl;
|
|
|
|
}
|
2009-03-12 20:04:38 -06:00
|
|
|
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.
|
2009-07-17 14:38:16 -06:00
|
|
|
defaultlit(&nr, types[TUINT]);
|
|
|
|
n->right = nr;
|
2009-07-07 00:33:17 -06:00
|
|
|
if(nr->type && (issigned[nr->type->etype] || !isint[nr->type->etype]))
|
|
|
|
goto illegal;
|
2009-03-12 20:04:38 -06:00
|
|
|
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:
|
2009-07-07 00:33:17 -06:00
|
|
|
if(!n->diag) {
|
|
|
|
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-08-03 12:58:52 -06:00
|
|
|
case TUP(OADDSTR, CTSTR):
|
2009-03-12 20:04:38 -06:00
|
|
|
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-07-07 00:33:17 -06:00
|
|
|
if(!n->diag) {
|
|
|
|
yyerror("illegal constant expression %O %T", n->op, nl->type);
|
|
|
|
n->diag = 1;
|
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
return;
|
|
|
|
|
2009-09-21 16:45:55 -06:00
|
|
|
case TUP(OCONV, CTNIL):
|
|
|
|
case TUP(OARRAYBYTESTR, CTNIL):
|
|
|
|
if(n->type->etype == TSTRING) {
|
|
|
|
v = tostr(v);
|
|
|
|
nl->type = n->type;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fall through
|
2009-07-29 13:47:51 -06:00
|
|
|
case TUP(OCONV, CTINT):
|
|
|
|
case TUP(OCONV, CTFLT):
|
|
|
|
case TUP(OCONV, CTSTR):
|
|
|
|
convlit1(&nl, n->type, 1);
|
|
|
|
break;
|
|
|
|
|
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:
|
2009-05-29 16:34:47 -06:00
|
|
|
// signed guys change sign
|
2009-03-24 17:40:38 -06:00
|
|
|
mpmovecfix(&b, -1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TUINT8:
|
|
|
|
case TUINT16:
|
|
|
|
case TUINT32:
|
|
|
|
case TUINT64:
|
|
|
|
case TUINT:
|
|
|
|
case TUINTPTR:
|
2009-05-29 16:34:47 -06:00
|
|
|
// unsigned guys invert their bits
|
2009-03-24 17:40:38 -06:00
|
|
|
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;
|
|
|
|
|
|
|
|
// check range.
|
2009-06-25 17:32:33 -06:00
|
|
|
lno = setlineno(n);
|
2009-03-12 20:04:38 -06:00
|
|
|
overflow(v, n->type);
|
|
|
|
lineno = lno;
|
|
|
|
|
|
|
|
// truncate precision for non-ideal float.
|
|
|
|
if(v.ctype == CTFLT && n->type->etype != TIDEAL)
|
2009-05-27 11:16:13 -06:00
|
|
|
n->val.u.fval = truncfltlit(v.u.fval, n->type);
|
2009-03-12 20:04:38 -06:00
|
|
|
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:
|
2009-09-21 16:45:55 -06:00
|
|
|
n->type = idealstring;
|
2009-03-12 20:04:38 -06:00
|
|
|
break;
|
|
|
|
case CTBOOL:
|
2009-09-21 16:45:55 -06:00
|
|
|
n->type = idealbool;
|
2009-03-12 20:04:38 -06:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2009-08-04 11:26:29 -06:00
|
|
|
// TODO(rsc): combine with convlit
|
2008-06-04 15:37:38 -06:00
|
|
|
void
|
2009-07-17 14:38:16 -06:00
|
|
|
defaultlit(Node **np, Type *t)
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-03-12 20:04:38 -06:00
|
|
|
int lno;
|
2009-07-17 14:38:16 -06:00
|
|
|
Node *n, *nn;
|
2009-03-12 20:04:38 -06:00
|
|
|
|
2009-07-17 14:38:16 -06:00
|
|
|
n = *np;
|
2009-08-27 12:16:34 -06:00
|
|
|
if(n == N || !isideal(n->type))
|
2008-06-04 15:37:38 -06:00
|
|
|
return;
|
2009-03-12 20:04:38 -06:00
|
|
|
|
|
|
|
switch(n->op) {
|
|
|
|
case OLITERAL:
|
2009-07-17 14:38:16 -06:00
|
|
|
nn = nod(OXXX, N, N);
|
|
|
|
*nn = *n;
|
|
|
|
n = nn;
|
|
|
|
*np = n;
|
2009-03-12 20:04:38 -06:00
|
|
|
break;
|
|
|
|
case OLSH:
|
|
|
|
case ORSH:
|
2009-07-17 14:38:16 -06:00
|
|
|
defaultlit(&n->left, t);
|
2009-08-23 19:09:44 -06:00
|
|
|
t = n->left->type;
|
|
|
|
if(t != T && !isint[t->etype]) {
|
|
|
|
yyerror("invalid operation: %#N (shift of type %T)", n, t);
|
|
|
|
t = T;
|
|
|
|
}
|
|
|
|
n->type = t;
|
2008-06-04 15:37:38 -06:00
|
|
|
return;
|
2009-07-30 17:53:08 -06:00
|
|
|
default:
|
2009-09-09 02:01:39 -06:00
|
|
|
if(n->left == N) {
|
|
|
|
dump("defaultlit", n);
|
|
|
|
fatal("defaultlit");
|
|
|
|
}
|
2009-07-30 17:53:08 -06:00
|
|
|
defaultlit(&n->left, t);
|
|
|
|
defaultlit(&n->right, t);
|
2009-09-21 16:45:55 -06:00
|
|
|
if(n->type == idealbool || n->type == idealstring)
|
|
|
|
n->type = types[n->type->etype];
|
|
|
|
else
|
|
|
|
n->type = n->left->type;
|
2009-07-30 17:53:08 -06:00
|
|
|
return;
|
2009-03-12 20:04:38 -06:00
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-08-27 12:16:34 -06:00
|
|
|
lno = setlineno(n);
|
2008-06-04 15:37:38 -06:00
|
|
|
switch(n->val.ctype) {
|
|
|
|
default:
|
2009-08-04 11:26:29 -06:00
|
|
|
if(t != T) {
|
|
|
|
convlit(np, t);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(n->val.ctype == CTNIL) {
|
|
|
|
lineno = lno;
|
|
|
|
yyerror("use of untyped nil");
|
|
|
|
n->type = T;
|
|
|
|
break;
|
|
|
|
}
|
2009-08-27 12:16:34 -06:00
|
|
|
if(n->val.ctype == CTSTR) {
|
|
|
|
n->type = types[TSTRING];
|
|
|
|
break;
|
|
|
|
}
|
2009-07-29 13:47:51 -06:00
|
|
|
yyerror("defaultlit: unknown literal: %#N", n);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
2009-09-21 16:45:55 -06:00
|
|
|
case CTBOOL:
|
|
|
|
n->type = types[TBOOL];
|
|
|
|
break;
|
2008-06-04 15:37:38 -06:00
|
|
|
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
|
2009-07-30 17:53:08 -06:00
|
|
|
defaultlit2(Node **lp, Node **rp, int force)
|
2009-03-12 20:04:38 -06:00
|
|
|
{
|
2009-07-17 14:38:16 -06:00
|
|
|
Node *l, *r;
|
|
|
|
|
|
|
|
l = *lp;
|
|
|
|
r = *rp;
|
2009-03-12 20:04:38 -06:00
|
|
|
if(l->type == T || r->type == T)
|
|
|
|
return;
|
2009-09-21 16:45:55 -06:00
|
|
|
if(!isideal(l->type)) {
|
2009-07-17 14:38:16 -06:00
|
|
|
convlit(rp, l->type);
|
2009-03-12 20:04:38 -06:00
|
|
|
return;
|
|
|
|
}
|
2009-09-21 16:45:55 -06:00
|
|
|
if(!isideal(r->type)) {
|
2009-07-17 14:38:16 -06:00
|
|
|
convlit(lp, r->type);
|
2009-03-12 20:04:38 -06:00
|
|
|
return;
|
|
|
|
}
|
2009-07-30 17:53:08 -06:00
|
|
|
if(!force)
|
|
|
|
return;
|
2009-03-12 20:04:38 -06:00
|
|
|
if(isconst(l, CTFLT) || isconst(r, CTFLT)) {
|
2009-07-17 14:38:16 -06:00
|
|
|
convlit(lp, types[TFLOAT]);
|
|
|
|
convlit(rp, types[TFLOAT]);
|
2009-03-12 20:04:38 -06:00
|
|
|
return;
|
|
|
|
}
|
2009-07-17 14:38:16 -06:00
|
|
|
convlit(lp, types[TINT]);
|
|
|
|
convlit(rp, 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)
|
|
|
|
{
|
2009-08-21 18:54:07 -06:00
|
|
|
if(n->op == OLITERAL && n->type != T)
|
2008-12-14 19:45:00 -07:00
|
|
|
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;
|
|
|
|
}
|
2009-05-21 14:46:07 -06:00
|
|
|
|
|
|
|
long
|
|
|
|
nonnegconst(Node *n)
|
|
|
|
{
|
2009-08-21 18:54:07 -06:00
|
|
|
if(n->op == OLITERAL && n->type != T)
|
2009-05-21 14:46:07 -06:00
|
|
|
switch(simtype[n->type->etype]) {
|
|
|
|
case TINT8:
|
|
|
|
case TUINT8:
|
|
|
|
case TINT16:
|
|
|
|
case TUINT16:
|
|
|
|
case TINT32:
|
|
|
|
case TUINT32:
|
|
|
|
case TINT64:
|
|
|
|
case TUINT64:
|
|
|
|
case TIDEAL:
|
|
|
|
// check negative and 2^31
|
|
|
|
if(mpcmpfixfix(n->val.u.xval, minintval[TUINT32]) < 0
|
|
|
|
|| mpcmpfixfix(n->val.u.xval, maxintval[TINT32]) > 0)
|
|
|
|
break;
|
|
|
|
return mpgetfix(n->val.u.xval);
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
2009-05-28 00:55:14 -06:00
|
|
|
|
|
|
|
/*
|
|
|
|
* convert x to type et and back to int64
|
|
|
|
* for sign extension and truncation.
|
|
|
|
*/
|
|
|
|
int64
|
|
|
|
iconv(int64 x, int et)
|
|
|
|
{
|
|
|
|
switch(et) {
|
|
|
|
case TINT8:
|
|
|
|
x = (int8)x;
|
|
|
|
break;
|
|
|
|
case TUINT8:
|
|
|
|
x = (uint8)x;
|
|
|
|
break;
|
|
|
|
case TINT16:
|
|
|
|
x = (int16)x;
|
|
|
|
break;
|
|
|
|
case TUINT16:
|
|
|
|
x = (uint64)x;
|
|
|
|
break;
|
|
|
|
case TINT32:
|
|
|
|
x = (int32)x;
|
|
|
|
break;
|
|
|
|
case TUINT32:
|
|
|
|
x = (uint32)x;
|
|
|
|
break;
|
|
|
|
case TINT64:
|
|
|
|
case TUINT64:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* convert constant val to type t; leave in con.
|
|
|
|
* for back end.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
convconst(Node *con, Type *t, Val *val)
|
|
|
|
{
|
|
|
|
int64 i;
|
|
|
|
int tt;
|
|
|
|
|
|
|
|
tt = simsimtype(t);
|
|
|
|
|
|
|
|
// copy the constant for conversion
|
|
|
|
nodconst(con, types[TINT8], 0);
|
|
|
|
con->type = t;
|
|
|
|
con->val = *val;
|
|
|
|
|
|
|
|
if(isint[tt]) {
|
|
|
|
con->val.ctype = CTINT;
|
|
|
|
con->val.u.xval = mal(sizeof *con->val.u.xval);
|
|
|
|
switch(val->ctype) {
|
|
|
|
default:
|
2009-05-28 16:48:47 -06:00
|
|
|
fatal("convconst ctype=%d %lT", val->ctype, t);
|
2009-05-28 00:55:14 -06:00
|
|
|
case CTINT:
|
|
|
|
i = mpgetfix(val->u.xval);
|
|
|
|
break;
|
|
|
|
case CTBOOL:
|
|
|
|
i = val->u.bval;
|
|
|
|
break;
|
|
|
|
case CTNIL:
|
|
|
|
i = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
i = iconv(i, tt);
|
|
|
|
mpmovecfix(con->val.u.xval, i);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(isfloat[tt]) {
|
|
|
|
if(con->val.ctype == CTINT) {
|
|
|
|
con->val.ctype = CTFLT;
|
|
|
|
con->val.u.fval = mal(sizeof *con->val.u.fval);
|
|
|
|
mpmovefixflt(con->val.u.fval, val->u.xval);
|
|
|
|
}
|
|
|
|
if(con->val.ctype != CTFLT)
|
|
|
|
fatal("convconst ctype=%d %T", con->val.ctype, t);
|
|
|
|
if(!isfloat[tt]) {
|
|
|
|
// easy to handle, but can it happen?
|
|
|
|
fatal("convconst CTINT %T", t);
|
|
|
|
}
|
|
|
|
if(tt == TFLOAT32)
|
|
|
|
con->val.u.fval = truncfltlit(con->val.u.fval, t);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fatal("convconst %lT constant", t);
|
|
|
|
|
|
|
|
}
|