Commit 3def15cd authored by Matthew Dempsky's avatar Matthew Dempsky

cmd/compile: move all constant folding logic into evconst

All setconst calls now happen within evconst. While here, get rid of
callrecv, which (incompletely) duplicates the logic of hascallchan.

Passes toolstash-check.

Change-Id: Ic67b9dd2a1b397d4bc25e8c8b6f81daf4f6cfb75
Reviewed-on: https://go-review.googlesource.com/c/go/+/166980
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
parent 3aa7bbdb
......@@ -631,6 +631,13 @@ func evconst(n *Node) {
setconst(n, convlit1(nl, n.Type, true, false).Val())
}
case OCONVNOP:
if nl.Op == OLITERAL && nl.isGoConst() {
// set so n.Orig gets OCONV instead of OCONVNOP
n.Op = OCONV
setconst(n, nl.Val())
}
case OBYTES2STR:
// string([]byte(nil)) or string([]rune(nil))
if nl.Op == OLITERAL && nl.Val().Ctype() == CTNIL {
......@@ -664,6 +671,56 @@ func evconst(n *Node) {
} else {
n.List.Set(s)
}
case OCAP, OLEN:
switch nl.Type.Etype {
case TSTRING:
if Isconst(nl, CTSTR) {
setintconst(n, int64(len(nl.Val().U.(string))))
}
case TARRAY:
if !hascallchan(nl) {
setintconst(n, nl.Type.NumElem())
}
}
case OALIGNOF, OOFFSETOF, OSIZEOF:
setintconst(n, evalunsafe(n))
case OREAL, OIMAG:
if nl.Op == OLITERAL {
var re, im *Mpflt
switch consttype(nl) {
case CTINT, CTRUNE:
re = newMpflt()
re.SetInt(nl.Val().U.(*Mpint))
// im = 0
case CTFLT:
re = nl.Val().U.(*Mpflt)
// im = 0
case CTCPLX:
re = &nl.Val().U.(*Mpcplx).Real
im = &nl.Val().U.(*Mpcplx).Imag
default:
Fatalf("impossible")
}
if n.Op == OIMAG {
if im == nil {
im = newMpflt()
}
re = im
}
setconst(n, Val{re})
}
case OCOMPLEX:
if nl.Op == OLITERAL && nr.Op == OLITERAL {
// make it a complex literal
c := newMpcmplx()
c.Real.Set(toflt(nl.Val()).U.(*Mpflt))
c.Imag.Set(toflt(nr.Val()).U.(*Mpflt))
setconst(n, Val{c})
}
}
}
......
......@@ -307,39 +307,6 @@ func typecheck(n *Node, top int) (res *Node) {
return n
}
// does n contain a call or receive operation?
func callrecv(n *Node) bool {
if n == nil {
return false
}
switch n.Op {
case OCALL,
OCALLMETH,
OCALLINTER,
OCALLFUNC,
ORECV,
OCAP,
OLEN,
OCOPY,
ONEW,
OAPPEND,
ODELETE:
return true
}
return callrecv(n.Left) || callrecv(n.Right) || callrecvlist(n.Ninit) || callrecvlist(n.Nbody) || callrecvlist(n.List) || callrecvlist(n.Rlist)
}
func callrecvlist(l Nodes) bool {
for _, n := range l.Slice() {
if callrecv(n) {
return true
}
}
return false
}
// indexlit implements typechecking of untyped values as
// array/slice indexes. It is almost equivalent to defaultlit
// but also accepts untyped numeric values representable as
......@@ -1402,9 +1369,6 @@ func typecheck1(n *Node, top int) (res *Node) {
}
n.Type = types.Types[TUINTPTR]
// any side effects disappear; ignore init
setintconst(n, evalunsafe(n))
case OCAP, OLEN:
ok |= ctxExpr
if !onearg(n, "%v", n.Op) {
......@@ -1436,23 +1400,6 @@ func typecheck1(n *Node, top int) (res *Node) {
n.Type = types.Types[TINT]
// Result might be constant.
var res int64 = -1 // valid if >= 0
switch t.Etype {
case TSTRING:
if Isconst(l, CTSTR) {
res = int64(len(l.Val().U.(string)))
}
case TARRAY:
if !callrecv(l) {
res = t.NumElem()
}
}
if res >= 0 {
setintconst(n, res)
}
case OREAL, OIMAG:
ok |= ctxExpr
if !onearg(n, "%v", n.Op) {
......@@ -1484,36 +1431,6 @@ func typecheck1(n *Node, top int) (res *Node) {
}
n.Type = types.Types[et]
// if the argument is a constant, the result is a constant
// (any untyped numeric constant can be represented as a
// complex number)
if l.Op == OLITERAL {
var re, im *Mpflt
switch consttype(l) {
case CTINT, CTRUNE:
re = newMpflt()
re.SetInt(l.Val().U.(*Mpint))
// im = 0
case CTFLT:
re = l.Val().U.(*Mpflt)
// im = 0
case CTCPLX:
re = &l.Val().U.(*Mpcplx).Real
im = &l.Val().U.(*Mpcplx).Imag
default:
yyerror("invalid argument %L for %v", l, n.Op)
n.Type = nil
return n
}
if n.Op == OIMAG {
if im == nil {
im = newMpflt()
}
re = im
}
setconst(n, Val{re})
}
case OCOMPLEX:
ok |= ctxExpr
var r *Node
......@@ -1586,14 +1503,6 @@ func typecheck1(n *Node, top int) (res *Node) {
}
n.Type = t
if l.Op == OLITERAL && r.Op == OLITERAL {
// make it a complex literal
c := newMpcmplx()
c.Real.Set(toflt(l.Val()).U.(*Mpflt))
c.Imag.Set(toflt(r.Val()).U.(*Mpflt))
setconst(n, Val{c})
}
case OCLOSE:
if !onearg(n, "%v", n.Op) {
n.Type = nil
......@@ -1817,10 +1726,7 @@ func typecheck1(n *Node, top int) (res *Node) {
switch n.Op {
case OCONVNOP:
if n.Left.Op == OLITERAL && n.isGoConst() {
n.Op = OCONV // set so n.Orig gets OCONV instead of OCONVNOP
setconst(n, n.Left.Val()) // convert n to OLITERAL with the given value
} else if t.Etype == n.Type.Etype {
if t.Etype == n.Type.Etype {
switch t.Etype {
case TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128:
// Floating point casts imply rounding and
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment