mirror of
https://github.com/golang/go
synced 2024-11-17 19:54:45 -07:00
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: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
3aa7bbdbcb
commit
3def15cd20
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user