]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: clean up in preparation for expression Nodes
authorRuss Cox <rsc@golang.org>
Mon, 30 Nov 2020 02:11:07 +0000 (21:11 -0500)
committerRuss Cox <rsc@golang.org>
Mon, 30 Nov 2020 23:48:24 +0000 (23:48 +0000)
Using expression nodes restricts the set of valid SetOp operations,
because you can't SetOp across representation. Rewrite various code
to avoid crossing those as-yet-unintroduced boundaries.

This also includes choosing a single representation for any given Op.
For example, OCLOSE starts out as an OCALL, so it starts with a List
of one node and then moves that node to Left. That's no good with
real data structures, so the code picks a single canonical implementation
and prepares it during the conversion from one Op to the next.
In this case, the conversion of an OCALL to an OCLOSE now creates
a new node with Left initialized from the start. This pattern repeats.

Passes buildall w/ toolstash -cmp.

Change-Id: I55a0872c614d883cac9d64976c46aeeaa639e25d
Reviewed-on: https://go-review.googlesource.com/c/go/+/274107
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/gc/sinit.go
src/cmd/compile/internal/gc/subr.go
src/cmd/compile/internal/gc/typecheck.go
src/cmd/compile/internal/gc/walk.go

index ff3d3281ddfa563cdddecaf86f05d6a35ac3cdcc..8146f30377107c9b235229d63f83d8c34bdfd7e4 100644 (file)
@@ -686,8 +686,7 @@ func slicelit(ctxt initContext, n ir.Node, var_ ir.Node, init *ir.Nodes) {
 
                a = ir.Nod(ir.OADDR, a, nil)
        } else {
-               a = ir.Nod(ir.ONEW, nil, nil)
-               a.PtrList().Set1(ir.TypeNode(t))
+               a = ir.Nod(ir.ONEW, ir.TypeNode(t), nil)
        }
 
        a = ir.Nod(ir.OAS, vauto, a)
@@ -889,9 +888,8 @@ func anylit(n ir.Node, var_ ir.Node, init *ir.Nodes) {
                        r = ir.Nod(ir.OADDR, n.Right(), nil)
                        r = typecheck(r, ctxExpr)
                } else {
-                       r = ir.Nod(ir.ONEW, nil, nil)
-                       r.SetTypecheck(1)
-                       r.SetType(t)
+                       r = ir.Nod(ir.ONEW, ir.TypeNode(n.Left().Type()), nil)
+                       r = typecheck(r, ctxExpr)
                        r.SetEsc(n.Esc())
                }
 
index b1c9d24d991f2596e6ea1d4c302c3b311b81d443..0163653d3bd9ac650c434c54db648280c493d8c1 100644 (file)
@@ -1472,7 +1472,7 @@ func ifaceData(pos src.XPos, n ir.Node, t *types.Type) ir.Node {
        if t.IsInterface() {
                base.Fatalf("ifaceData interface: %v", t)
        }
-       ptr := nodlSym(pos, ir.OIDATA, n, nil)
+       ptr := ir.NodAt(pos, ir.OIDATA, n, nil)
        if isdirectiface(t) {
                ptr.SetType(t)
                ptr.SetTypecheck(1)
index b5ace765528224cf5d1d1eedb92999aae34a7c72..f021ea48b14af7fe64e18f1e75734204c9ec6e16 100644 (file)
@@ -1065,7 +1065,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
                        n.SetRight(assignconv(n.Right(), t.Key(), "map index"))
                        n.SetType(t.Elem())
                        n.SetOp(ir.OINDEXMAP)
-                       n.ResetAux()
+                       n.SetIndexMapLValue(false)
                }
 
        case ir.ORECV:
@@ -1099,27 +1099,22 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
                n.SetLeft(defaultlit(n.Left(), nil))
                t := n.Left().Type()
                if t == nil {
-                       n.SetType(nil)
                        return n
                }
                if !t.IsChan() {
                        base.Errorf("invalid operation: %v (send to non-chan type %v)", n, t)
-                       n.SetType(nil)
                        return n
                }
 
                if !t.ChanDir().CanSend() {
                        base.Errorf("invalid operation: %v (send to receive-only type %v)", n, t)
-                       n.SetType(nil)
                        return n
                }
 
                n.SetRight(assignconv(n.Right(), t.Elem(), "send"))
                if n.Right().Type() == nil {
-                       n.SetType(nil)
                        return n
                }
-               n.SetType(nil)
 
        case ir.OSLICEHEADER:
                // Errors here are Fatalf instead of Errorf because only the compiler
@@ -1299,9 +1294,44 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
                        }
 
                        // builtin: OLEN, OCAP, etc.
-                       n.SetOp(l.SubOp())
-                       n.SetLeft(n.Right())
-                       n.SetRight(nil)
+                       switch l.SubOp() {
+                       default:
+                               base.Fatalf("unknown builtin %v", l)
+                               return n
+
+                       case ir.OAPPEND, ir.ODELETE, ir.OMAKE, ir.OPRINT, ir.OPRINTN, ir.ORECOVER:
+                               n.SetOp(l.SubOp())
+                               n.SetLeft(nil)
+
+                       case ir.OCAP, ir.OCLOSE, ir.OIMAG, ir.OLEN, ir.OPANIC, ir.OREAL:
+                               typecheckargs(n)
+                               fallthrough
+                       case ir.ONEW, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF:
+                               arg, ok := needOneArg(n, "%v", n.Op())
+                               if !ok {
+                                       n.SetType(nil)
+                                       return n
+                               }
+                               old := n
+                               n = ir.NodAt(n.Pos(), l.SubOp(), arg, nil)
+                               n = addinit(n, old.Init().Slice()) // typecheckargs can add to old.Init
+                               if l.SubOp() == ir.ONEW {
+                                       // Bug-compatibility with earlier version.
+                                       // This extra node is unnecessary but raises the inlining cost by 1.
+                                       n.SetList(old.List())
+                               }
+
+                       case ir.OCOMPLEX, ir.OCOPY:
+                               typecheckargs(n)
+                               arg1, arg2, ok := needTwoArgs(n)
+                               if !ok {
+                                       n.SetType(nil)
+                                       return n
+                               }
+                               old := n
+                               n = ir.NodAt(n.Pos(), l.SubOp(), arg1, arg2)
+                               n = addinit(n, old.Init().Slice()) // typecheckargs can add to old.Init
+                       }
                        n = typecheck1(n, top)
                        return n
                }
@@ -1319,15 +1349,14 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
                        // pick off before type-checking arguments
                        ok |= ctxExpr
 
-                       // turn CALL(type, arg) into CONV(arg) w/ type
-                       n.SetLeft(nil)
-
-                       n.SetOp(ir.OCONV)
-                       n.SetType(l.Type())
-                       if !onearg(n, "conversion to %v", l.Type()) {
+                       arg, ok := needOneArg(n, "conversion to %v", l.Type())
+                       if !ok {
                                n.SetType(nil)
                                return n
                        }
+
+                       n = ir.NodAt(n.Pos(), ir.OCONV, arg, nil)
+                       n.SetType(l.Type())
                        n = typecheck1(n, top)
                        return n
                }
@@ -1406,19 +1435,10 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
 
        case ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF:
                ok |= ctxExpr
-               if !onearg(n, "%v", n.Op()) {
-                       n.SetType(nil)
-                       return n
-               }
                n.SetType(types.Types[types.TUINTPTR])
 
        case ir.OCAP, ir.OLEN:
                ok |= ctxExpr
-               if !onearg(n, "%v", n.Op()) {
-                       n.SetType(nil)
-                       return n
-               }
-
                n.SetLeft(typecheck(n.Left(), ctxExpr))
                n.SetLeft(defaultlit(n.Left(), nil))
                n.SetLeft(implicitstar(n.Left()))
@@ -1445,11 +1465,6 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
 
        case ir.OREAL, ir.OIMAG:
                ok |= ctxExpr
-               if !onearg(n, "%v", n.Op()) {
-                       n.SetType(nil)
-                       return n
-               }
-
                n.SetLeft(typecheck(n.Left(), ctxExpr))
                l := n.Left()
                t := l.Type()
@@ -1474,13 +1489,8 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
 
        case ir.OCOMPLEX:
                ok |= ctxExpr
-               typecheckargs(n)
-               if !twoarg(n) {
-                       n.SetType(nil)
-                       return n
-               }
-               l := n.Left()
-               r := n.Right()
+               l := typecheck(n.Left(), ctxExpr)
+               r := typecheck(n.Right(), ctxExpr)
                if l.Type() == nil || r.Type() == nil {
                        n.SetType(nil)
                        return n
@@ -1518,10 +1528,6 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
                n.SetType(t)
 
        case ir.OCLOSE:
-               if !onearg(n, "%v", n.Op()) {
-                       n.SetType(nil)
-                       return n
-               }
                n.SetLeft(typecheck(n.Left(), ctxExpr))
                n.SetLeft(defaultlit(n.Left(), nil))
                l := n.Left()
@@ -1638,17 +1644,10 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
 
        case ir.OCOPY:
                ok |= ctxStmt | ctxExpr
-               typecheckargs(n)
-               if !twoarg(n) {
-                       n.SetType(nil)
-                       return n
-               }
                n.SetType(types.Types[types.TINT])
-               if n.Left().Type() == nil || n.Right().Type() == nil {
-                       n.SetType(nil)
-                       return n
-               }
+               n.SetLeft(typecheck(n.Left(), ctxExpr))
                n.SetLeft(defaultlit(n.Left(), nil))
+               n.SetRight(typecheck(n.Right(), ctxExpr))
                n.SetRight(defaultlit(n.Right(), nil))
                if n.Left().Type() == nil || n.Right().Type() == nil {
                        n.SetType(nil)
@@ -1746,6 +1745,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
                }
 
                i := 1
+               var nn ir.Node
                switch t.Etype {
                default:
                        base.Errorf("cannot make type %v", t)
@@ -1782,10 +1782,7 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
                                n.SetType(nil)
                                return n
                        }
-
-                       n.SetLeft(l)
-                       n.SetRight(r)
-                       n.SetOp(ir.OMAKESLICE)
+                       nn = ir.NodAt(n.Pos(), ir.OMAKESLICE, l, r)
 
                case types.TMAP:
                        if i < len(args) {
@@ -1801,11 +1798,11 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
                                        n.SetType(nil)
                                        return n
                                }
-                               n.SetLeft(l)
                        } else {
-                               n.SetLeft(nodintconst(0))
+                               l = nodintconst(0)
                        }
-                       n.SetOp(ir.OMAKEMAP)
+                       nn = ir.NodAt(n.Pos(), ir.OMAKEMAP, l, nil)
+                       nn.SetEsc(n.Esc())
 
                case types.TCHAN:
                        l = nil
@@ -1822,44 +1819,35 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
                                        n.SetType(nil)
                                        return n
                                }
-                               n.SetLeft(l)
                        } else {
-                               n.SetLeft(nodintconst(0))
+                               l = nodintconst(0)
                        }
-                       n.SetOp(ir.OMAKECHAN)
+                       nn = ir.NodAt(n.Pos(), ir.OMAKECHAN, l, nil)
                }
 
                if i < len(args) {
                        base.Errorf("too many arguments to make(%v)", t)
-                       n.SetOp(ir.OMAKE)
                        n.SetType(nil)
                        return n
                }
 
-               n.SetType(t)
+               nn.SetType(t)
+               n = nn
 
        case ir.ONEW:
                ok |= ctxExpr
-               args := n.List()
-               if args.Len() == 0 {
-                       base.Errorf("missing argument to new")
-                       n.SetType(nil)
-                       return n
+               if n.Left() == nil {
+                       // Fatalf because the OCALL above checked for us,
+                       // so this must be an internally-generated mistake.
+                       base.Fatalf("missing argument to new")
                }
-
-               l := args.First()
+               l := n.Left()
                l = typecheck(l, ctxType)
                t := l.Type()
                if t == nil {
                        n.SetType(nil)
                        return n
                }
-               if args.Len() > 1 {
-                       base.Errorf("too many arguments to new(%v)", t)
-                       n.SetType(nil)
-                       return n
-               }
-
                n.SetLeft(l)
                n.SetType(types.NewPtr(t))
 
@@ -1878,10 +1866,6 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
 
        case ir.OPANIC:
                ok |= ctxStmt
-               if !onearg(n, "panic") {
-                       n.SetType(nil)
-                       return n
-               }
                n.SetLeft(typecheck(n.Left(), ctxExpr))
                n.SetLeft(defaultlit(n.Left(), types.Types[types.TINTER]))
                if n.Left().Type() == nil {
@@ -2286,45 +2270,32 @@ func implicitstar(n ir.Node) ir.Node {
        return n
 }
 
-func onearg(n ir.Node, f string, args ...interface{}) bool {
-       if n.Left() != nil {
-               return true
-       }
+func needOneArg(n ir.Node, f string, args ...interface{}) (ir.Node, bool) {
        if n.List().Len() == 0 {
                p := fmt.Sprintf(f, args...)
                base.Errorf("missing argument to %s: %v", p, n)
-               return false
+               return nil, false
        }
 
        if n.List().Len() > 1 {
                p := fmt.Sprintf(f, args...)
                base.Errorf("too many arguments to %s: %v", p, n)
-               n.SetLeft(n.List().First())
-               n.PtrList().Set(nil)
-               return false
+               return n.List().First(), false
        }
 
-       n.SetLeft(n.List().First())
-       n.PtrList().Set(nil)
-       return true
+       return n.List().First(), true
 }
 
-func twoarg(n ir.Node) bool {
-       if n.Left() != nil {
-               return true
-       }
+func needTwoArgs(n ir.Node) (ir.Node, ir.Node, bool) {
        if n.List().Len() != 2 {
                if n.List().Len() < 2 {
                        base.Errorf("not enough arguments in call to %v", n)
                } else {
                        base.Errorf("too many arguments in call to %v", n)
                }
-               return false
+               return nil, nil, false
        }
-       n.SetLeft(n.List().First())
-       n.SetRight(n.List().Second())
-       n.PtrList().Set(nil)
-       return true
+       return n.List().First(), n.List().Second(), true
 }
 
 func lookdot1(errnode ir.Node, s *types.Sym, t *types.Type, fs *types.Fields, dostrcmp int) *types.Field {
@@ -2411,21 +2382,19 @@ func typecheckMethodExpr(n ir.Node) (res ir.Node) {
                return n
        }
 
-       n.SetOp(ir.OMETHEXPR)
-       n.SetRight(NewName(n.Sym()))
-       n.SetSym(methodSym(t, n.Sym()))
-       n.SetType(methodfunc(m.Type, n.Left().Type()))
-       n.SetOffset(0)
-       n.SetClass(ir.PFUNC)
-       n.SetOpt(m)
-       // methodSym already marked n.Sym as a function.
+       me := ir.NodAt(n.Pos(), ir.OMETHEXPR, n.Left(), NewName(n.Sym()))
+       me.SetSym(methodSym(t, n.Sym()))
+       me.SetType(methodfunc(m.Type, n.Left().Type()))
+       me.SetOffset(0)
+       me.SetClass(ir.PFUNC)
+       me.SetOpt(m)
 
        // Issue 25065. Make sure that we emit the symbol for a local method.
        if base.Ctxt.Flag_dynlink && !inimport && (t.Sym == nil || t.Sym.Pkg == ir.LocalPkg) {
-               makefuncsym(n.Sym())
+               makefuncsym(me.Sym())
        }
 
-       return n
+       return me
 }
 
 // isMethodApplicable reports whether method m can be called on a
index 0a77cfbb3848f33e51eaebb3b85dda187f49182e..511cdd3685e4df18964fc8f3c6d16c7695c1f32b 100644 (file)
@@ -1515,9 +1515,10 @@ opswitch:
                        }
 
                        // Slice the [n]byte to a []byte.
-                       n.SetOp(ir.OSLICEARR)
-                       n.SetLeft(p)
-                       n = walkexpr(n, init)
+                       slice := ir.NodAt(n.Pos(), ir.OSLICEARR, p, nil)
+                       slice.SetType(n.Type())
+                       slice.SetTypecheck(1)
+                       n = walkexpr(slice, init)
                        break
                }