mirror of
https://github.com/golang/go
synced 2024-11-17 22:34:47 -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())
|
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:
|
case OBYTES2STR:
|
||||||
// string([]byte(nil)) or string([]rune(nil))
|
// string([]byte(nil)) or string([]rune(nil))
|
||||||
if nl.Op == OLITERAL && nl.Val().Ctype() == CTNIL {
|
if nl.Op == OLITERAL && nl.Val().Ctype() == CTNIL {
|
||||||
@ -664,6 +671,56 @@ func evconst(n *Node) {
|
|||||||
} else {
|
} else {
|
||||||
n.List.Set(s)
|
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
|
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
|
// indexlit implements typechecking of untyped values as
|
||||||
// array/slice indexes. It is almost equivalent to defaultlit
|
// array/slice indexes. It is almost equivalent to defaultlit
|
||||||
// but also accepts untyped numeric values representable as
|
// 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]
|
n.Type = types.Types[TUINTPTR]
|
||||||
|
|
||||||
// any side effects disappear; ignore init
|
|
||||||
setintconst(n, evalunsafe(n))
|
|
||||||
|
|
||||||
case OCAP, OLEN:
|
case OCAP, OLEN:
|
||||||
ok |= ctxExpr
|
ok |= ctxExpr
|
||||||
if !onearg(n, "%v", n.Op) {
|
if !onearg(n, "%v", n.Op) {
|
||||||
@ -1436,23 +1400,6 @@ func typecheck1(n *Node, top int) (res *Node) {
|
|||||||
|
|
||||||
n.Type = types.Types[TINT]
|
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:
|
case OREAL, OIMAG:
|
||||||
ok |= ctxExpr
|
ok |= ctxExpr
|
||||||
if !onearg(n, "%v", n.Op) {
|
if !onearg(n, "%v", n.Op) {
|
||||||
@ -1484,36 +1431,6 @@ func typecheck1(n *Node, top int) (res *Node) {
|
|||||||
}
|
}
|
||||||
n.Type = types.Types[et]
|
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:
|
case OCOMPLEX:
|
||||||
ok |= ctxExpr
|
ok |= ctxExpr
|
||||||
var r *Node
|
var r *Node
|
||||||
@ -1586,14 +1503,6 @@ func typecheck1(n *Node, top int) (res *Node) {
|
|||||||
}
|
}
|
||||||
n.Type = t
|
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:
|
case OCLOSE:
|
||||||
if !onearg(n, "%v", n.Op) {
|
if !onearg(n, "%v", n.Op) {
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
@ -1817,10 +1726,7 @@ func typecheck1(n *Node, top int) (res *Node) {
|
|||||||
|
|
||||||
switch n.Op {
|
switch n.Op {
|
||||||
case OCONVNOP:
|
case OCONVNOP:
|
||||||
if n.Left.Op == OLITERAL && n.isGoConst() {
|
if t.Etype == n.Type.Etype {
|
||||||
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 {
|
|
||||||
switch t.Etype {
|
switch t.Etype {
|
||||||
case TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128:
|
case TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128:
|
||||||
// Floating point casts imply rounding and
|
// Floating point casts imply rounding and
|
||||||
|
Loading…
Reference in New Issue
Block a user