]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: move all constant folding logic into evconst
authorMatthew Dempsky <mdempsky@google.com>
Thu, 28 Feb 2019 01:34:07 +0000 (17:34 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Wed, 13 Mar 2019 18:23:41 +0000 (18:23 +0000)
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>
src/cmd/compile/internal/gc/const.go
src/cmd/compile/internal/gc/typecheck.go

index 0e6d838eaa4fb2e1f165628da70088459a234350..218d1d1d7f8a4b6a8ad769977edf2a1a9bae08da 100644 (file)
@@ -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})
+               }
        }
 }
 
index 69ba9ef52a0412c12b8dfb7749a6332ddae45bc9..8ae6c112b60784dbef66ba64606be07e2772c26d 100644 (file)
@@ -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