summaryrefslogtreecommitdiff
path: root/src/cmd/gc/const.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc/const.c')
-rw-r--r--src/cmd/gc/const.c92
1 files changed, 72 insertions, 20 deletions
diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c
index cfb1f0ade..143c1730d 100644
--- a/src/cmd/gc/const.c
+++ b/src/cmd/gc/const.c
@@ -22,19 +22,22 @@ Mpflt*
truncfltlit(Mpflt *oldv, Type *t)
{
double d;
- float f;
Mpflt *fv;
+ Val v;
if(t == T)
return oldv;
+ memset(&v, 0, sizeof v);
+ v.ctype = CTFLT;
+ v.u.fval = oldv;
+ overflow(v, t);
+
fv = mal(sizeof *fv);
*fv = *oldv;
// 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);
@@ -42,10 +45,9 @@ truncfltlit(Mpflt *oldv, Type *t)
break;
case TFLOAT32:
- d = mpgetflt(fv);
- f = d;
- d = f;
+ d = mpgetflt32(fv);
mpmovecflt(fv, d);
+
break;
}
return fv;
@@ -235,7 +237,6 @@ convlit1(Node **np, Type *t, int explicit)
n->val = toflt(n->val);
// flowthrough
case CTFLT:
- overflow(n->val, t);
n->val.u.fval = truncfltlit(n->val.u.fval, t);
break;
}
@@ -521,6 +522,7 @@ evconst(Node *n)
int wl, wr, lno, et;
Val v, rv;
Mpint b;
+ NodeList *l1, *l2;
// pick off just the opcodes that can be
// constant evaluated.
@@ -528,7 +530,6 @@ evconst(Node *n)
default:
return;
case OADD:
- case OADDSTR:
case OAND:
case OANDAND:
case OANDNOT:
@@ -559,6 +560,47 @@ evconst(Node *n)
if(!okforconst[n->type->etype] && n->type->etype != TNIL)
return;
break;
+
+ case OADDSTR:
+ // merge adjacent constants in the argument list.
+ for(l1=n->list; l1 != nil; l1= l1->next) {
+ if(isconst(l1->n, CTSTR) && l1->next != nil && isconst(l1->next->n, CTSTR)) {
+ l2 = l1;
+ len = 0;
+ while(l2 != nil && isconst(l2->n, CTSTR)) {
+ nr = l2->n;
+ len += nr->val.u.sval->len;
+ l2 = l2->next;
+ }
+ // merge from l1 up to but not including l2
+ str = mal(sizeof(*str) + len);
+ str->len = len;
+ len = 0;
+ l2 = l1;
+ while(l2 != nil && isconst(l2->n, CTSTR)) {
+ nr = l2->n;
+ memmove(str->s+len, nr->val.u.sval->s, nr->val.u.sval->len);
+ len += nr->val.u.sval->len;
+ l2 = l2->next;
+ }
+ nl = nod(OXXX, N, N);
+ *nl = *l1->n;
+ nl->orig = nl;
+ nl->val.ctype = CTSTR;
+ nl->val.u.sval = str;
+ l1->n = nl;
+ l1->next = l2;
+ }
+ }
+ // fix list end pointer.
+ for(l2=n->list; l2 != nil; l2=l2->next)
+ n->list->end = l2;
+ // collapse single-constant list to single constant.
+ if(count(n->list) == 1 && isconst(n->list->n, CTSTR)) {
+ n->op = OLITERAL;
+ n->val = n->list->n->val;
+ }
+ return;
}
nl = n->left;
@@ -861,15 +903,6 @@ evconst(Node *n)
if(cmpslit(nl, nr) > 0)
goto settrue;
goto setfalse;
- case TUP(OADDSTR, CTSTR):
- len = v.u.sval->len + rv.u.sval->len;
- str = mal(sizeof(*str) + len);
- str->len = len;
- memcpy(str->s, v.u.sval->s, v.u.sval->len);
- memcpy(str->s+v.u.sval->len, rv.u.sval->s, rv.u.sval->len);
- str->len = len;
- v.u.sval = str;
- break;
case TUP(OOROR, CTBOOL):
if(v.u.bval || rv.u.bval)
@@ -918,6 +951,7 @@ unary:
case TUP(OCONV, CTFLT):
case TUP(OCONV, CTSTR):
convlit1(&nl, n->type, 1);
+ v = nl->val;
break;
case TUP(OPLUS, CTINT):
@@ -1144,7 +1178,10 @@ defaultlit(Node **np, Type *t)
}
if(n->val.ctype == CTNIL) {
lineno = lno;
- yyerror("use of untyped nil");
+ if(!n->diag) {
+ yyerror("use of untyped nil");
+ n->diag = 1;
+ }
n->type = T;
break;
}
@@ -1559,7 +1596,7 @@ isgoconst(Node *n)
case ONAME:
l = n->sym->def;
- if(l->op == OLITERAL && n->val.ctype != CTNIL)
+ if(l && l->op == OLITERAL && n->val.ctype != CTNIL)
return 1;
break;
@@ -1594,10 +1631,25 @@ hascallchan(Node *n)
if(n == N)
return 0;
switch(n->op) {
+ case OAPPEND:
case OCALL:
case OCALLFUNC:
- case OCALLMETH:
case OCALLINTER:
+ case OCALLMETH:
+ case OCAP:
+ case OCLOSE:
+ case OCOMPLEX:
+ case OCOPY:
+ case ODELETE:
+ case OIMAG:
+ case OLEN:
+ case OMAKE:
+ case ONEW:
+ case OPANIC:
+ case OPRINT:
+ case OPRINTN:
+ case OREAL:
+ case ORECOVER:
case ORECV:
return 1;
}