diff options
Diffstat (limited to 'src/cmd/gc/const.c')
-rw-r--r-- | src/cmd/gc/const.c | 92 |
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; } |