]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: cleanup for concrete types - import/export
authorRuss Cox <rsc@golang.org>
Thu, 10 Dec 2020 23:46:29 +0000 (18:46 -0500)
committerRuss Cox <rsc@golang.org>
Thu, 17 Dec 2020 04:43:15 +0000 (04:43 +0000)
An automated rewrite will add concrete type assertions after
a test of n.Op(), when n can be safely type-asserted
(meaning, n is not reassigned a different type, n is not reassigned
and then used outside the scope of the type assertion,
and so on).

This sequence of CLs handles the code that the automated
rewrite does not: adding specific types to function arguments,
adjusting code not to call n.Left() etc when n may have multiple
representations, and so on.

This CL focuses on iimport.go and iexport.go.

Passes buildall w/ toolstash -cmp.

Change-Id: I63edee54991ae5d982e99efa7a2894478d511910
Reviewed-on: https://go-review.googlesource.com/c/go/+/277925
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/gc/bexport.go
src/cmd/compile/internal/gc/bimport.go [deleted file]
src/cmd/compile/internal/gc/iexport.go
src/cmd/compile/internal/gc/iimport.go

index 43c4ce7150fe49928a0da7132a2ddd2c19c640cf..31fd251c5e0e1097fddb6338431c08de97eb6dae 100644 (file)
@@ -15,8 +15,11 @@ type exporter struct {
 
 // markObject visits a reachable object.
 func (p *exporter) markObject(n ir.Node) {
-       if n.Op() == ir.ONAME && n.Class() == ir.PFUNC {
-               inlFlood(n.(*ir.Name))
+       if n.Op() == ir.ONAME {
+               n := n.(*ir.Name)
+               if n.Class() == ir.PFUNC {
+                       inlFlood(n)
+               }
        }
 
        p.markType(n.Type())
diff --git a/src/cmd/compile/internal/gc/bimport.go b/src/cmd/compile/internal/gc/bimport.go
deleted file mode 100644 (file)
index 5a7018d..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package gc
-
-import (
-       "cmd/compile/internal/ir"
-       "cmd/compile/internal/types"
-       "cmd/internal/src"
-)
-
-func npos(pos src.XPos, n ir.Node) ir.Node {
-       n.SetPos(pos)
-       return n
-}
-
-func builtinCall(op ir.Op) ir.Node {
-       return ir.Nod(ir.OCALL, mkname(types.BuiltinPkg.Lookup(ir.OpNames[op])), nil)
-}
index 14356013de8bb99b9fdc6e96d7e33bbc4bf6bcb9..eac9f29e6550a9e7ffbfc5b0b9b395cdaf4870a7 100644 (file)
@@ -1069,7 +1069,7 @@ func (w *exportWriter) stmt(n ir.Node) {
                }
        }
 
-       switch op := n.Op(); op {
+       switch n.Op() {
        case ir.OBLOCK:
                // No OBLOCK in export data.
                // Inline content into this statement list,
@@ -1084,7 +1084,7 @@ func (w *exportWriter) stmt(n ir.Node) {
        case ir.ODCL:
                w.op(ir.ODCL)
                w.pos(n.Left().Pos())
-               w.localName(n.Left())
+               w.localName(n.Left().(*ir.Name))
                w.typ(n.Left().Type())
 
        case ir.OAS:
@@ -1099,9 +1099,10 @@ func (w *exportWriter) stmt(n ir.Node) {
                }
 
        case ir.OASOP:
+               n := n.(*ir.AssignOpStmt)
                w.op(ir.OASOP)
                w.pos(n.Pos())
-               w.op(n.SubOp())
+               w.op(n.AsOp)
                w.expr(n.Left())
                if w.bool(!n.Implicit()) {
                        w.expr(n.Right())
@@ -1122,7 +1123,7 @@ func (w *exportWriter) stmt(n ir.Node) {
        //      unreachable - generated by compiler for trampolin routines
 
        case ir.OGO, ir.ODEFER:
-               w.op(op)
+               w.op(n.Op())
                w.pos(n.Pos())
                w.expr(n.Left())
 
@@ -1148,8 +1149,15 @@ func (w *exportWriter) stmt(n ir.Node) {
                w.expr(n.Right())
                w.stmtList(n.Body())
 
-       case ir.OSELECT, ir.OSWITCH:
-               w.op(op)
+       case ir.OSELECT:
+               w.op(n.Op())
+               w.pos(n.Pos())
+               w.stmtList(n.Init())
+               w.exprsOrNil(nil, nil) // TODO(rsc): Delete (and fix importer).
+               w.caseList(n)
+
+       case ir.OSWITCH:
+               w.op(n.Op())
                w.pos(n.Pos())
                w.stmtList(n.Init())
                w.exprsOrNil(n.Left(), nil)
@@ -1163,7 +1171,7 @@ func (w *exportWriter) stmt(n ir.Node) {
                w.pos(n.Pos())
 
        case ir.OBREAK, ir.OCONTINUE, ir.OGOTO, ir.OLABEL:
-               w.op(op)
+               w.op(n.Op())
                w.pos(n.Pos())
                label := ""
                if sym := n.Sym(); sym != nil {
@@ -1176,19 +1184,34 @@ func (w *exportWriter) stmt(n ir.Node) {
        }
 }
 
+func isNamedTypeSwitch(n ir.Node) bool {
+       if n.Op() != ir.OSWITCH {
+               return false
+       }
+       sw := n.(*ir.SwitchStmt)
+       if sw.Left() == nil || sw.Left().Op() != ir.OTYPESW {
+               return false
+       }
+       guard := sw.Left().(*ir.TypeSwitchGuard)
+       return guard.Left() != nil
+}
+
 func (w *exportWriter) caseList(sw ir.Node) {
-       namedTypeSwitch := sw.Op() == ir.OSWITCH && sw.Left() != nil && sw.Left().Op() == ir.OTYPESW && sw.Left().Left() != nil
+       namedTypeSwitch := isNamedTypeSwitch(sw)
 
-       cases := sw.List().Slice()
+       var cases []ir.Node
+       if sw.Op() == ir.OSWITCH {
+               cases = sw.(*ir.SwitchStmt).List().Slice()
+       } else {
+               cases = sw.(*ir.SelectStmt).List().Slice()
+       }
        w.uint64(uint64(len(cases)))
        for _, cas := range cases {
-               if cas.Op() != ir.OCASE {
-                       base.Fatalf("expected OCASE, got %v", cas)
-               }
+               cas := cas.(*ir.CaseStmt)
                w.pos(cas.Pos())
                w.stmtList(cas.List())
                if namedTypeSwitch {
-                       w.localName(cas.Rlist().First())
+                       w.localName(cas.Rlist().First().(*ir.Name))
                }
                w.stmtList(cas.Body())
        }
@@ -1201,22 +1224,29 @@ func (w *exportWriter) exprList(list ir.Nodes) {
        w.op(ir.OEND)
 }
 
-func (w *exportWriter) expr(n ir.Node) {
-       // from nodefmt (fmt.go)
-       //
-       // nodefmt reverts nodes back to their original - we don't need to do
-       // it because we are not bound to produce valid Go syntax when exporting
-       //
-       // if (fmtmode != FExp || n.Op != OLITERAL) && n.Orig != nil {
-       //      n = n.Orig
-       // }
-
-       // from exprfmt (fmt.go)
-       for n.Op() == ir.OPAREN || n.Implicit() && (n.Op() == ir.ODEREF || n.Op() == ir.OADDR || n.Op() == ir.ODOT || n.Op() == ir.ODOTPTR) {
-               n = n.Left()
+func simplifyForExport(n ir.Node) ir.Node {
+       switch n.Op() {
+       case ir.OPAREN:
+               return simplifyForExport(n.Left())
+       case ir.ODEREF:
+               if n.Implicit() {
+                       return simplifyForExport(n.Left())
+               }
+       case ir.OADDR:
+               if n.Implicit() {
+                       return simplifyForExport(n.Left())
+               }
+       case ir.ODOT, ir.ODOTPTR:
+               if n.Implicit() {
+                       return simplifyForExport(n.Left())
+               }
        }
+       return n
+}
 
-       switch op := n.Op(); op {
+func (w *exportWriter) expr(n ir.Node) {
+       n = simplifyForExport(n)
+       switch n.Op() {
        // expressions
        // (somewhat closely following the structure of exprfmt in fmt.go)
        case ir.ONIL:
@@ -1243,6 +1273,7 @@ func (w *exportWriter) expr(n ir.Node) {
 
        case ir.ONAME:
                // Package scope name.
+               n := n.(*ir.Name)
                if (n.Class() == ir.PEXTERN || n.Class() == ir.PFUNC) && !ir.IsBlank(n) {
                        w.op(ir.ONONAME)
                        w.qualifiedIdent(n)
@@ -1291,7 +1322,7 @@ func (w *exportWriter) expr(n ir.Node) {
                w.op(ir.OSTRUCTLIT)
                w.pos(n.Pos())
                w.typ(n.Type())
-               w.elemList(n.List()) // special handling of field names
+               w.fieldList(n.List()) // special handling of field names
 
        case ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT:
                w.op(ir.OCOMPLIT)
@@ -1349,7 +1380,7 @@ func (w *exportWriter) expr(n ir.Node) {
 
        case ir.OCOPY, ir.OCOMPLEX:
                // treated like other builtin calls (see e.g., OREAL)
-               w.op(op)
+               w.op(n.Op())
                w.pos(n.Pos())
                w.expr(n.Left())
                w.expr(n.Right())
@@ -1361,20 +1392,21 @@ func (w *exportWriter) expr(n ir.Node) {
                w.expr(n.Left())
                w.typ(n.Type())
 
-       case ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.OCAP, ir.OCLOSE, ir.ODELETE, ir.OLEN, ir.OMAKE, ir.ONEW, ir.OPANIC, ir.ORECOVER, ir.OPRINT, ir.OPRINTN:
-               w.op(op)
+       case ir.OREAL, ir.OIMAG, ir.OCAP, ir.OCLOSE, ir.OLEN, ir.ONEW, ir.OPANIC:
+               w.op(n.Op())
                w.pos(n.Pos())
-               if n.Left() != nil {
-                       w.expr(n.Left())
-                       w.op(ir.OEND)
-               } else {
-                       w.exprList(n.List()) // emits terminating OEND
-               }
+               w.expr(n.Left())
+               w.op(ir.OEND)
+
+       case ir.OAPPEND, ir.ODELETE, ir.ORECOVER, ir.OPRINT, ir.OPRINTN:
+               w.op(n.Op())
+               w.pos(n.Pos())
+               w.exprList(n.List()) // emits terminating OEND
                // only append() calls may contain '...' arguments
-               if op == ir.OAPPEND {
+               if n.Op() == ir.OAPPEND {
                        w.bool(n.IsDDD())
                } else if n.IsDDD() {
-                       base.Fatalf("exporter: unexpected '...' with %v call", op)
+                       base.Fatalf("exporter: unexpected '...' with %v call", n.Op())
                }
 
        case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.OGETG:
@@ -1386,15 +1418,13 @@ func (w *exportWriter) expr(n ir.Node) {
                w.bool(n.IsDDD())
 
        case ir.OMAKEMAP, ir.OMAKECHAN, ir.OMAKESLICE:
-               w.op(op) // must keep separate from OMAKE for importer
+               w.op(n.Op()) // must keep separate from OMAKE for importer
                w.pos(n.Pos())
                w.typ(n.Type())
                switch {
                default:
                        // empty list
                        w.op(ir.OEND)
-               case n.List().Len() != 0: // pre-typecheck
-                       w.exprList(n.List()) // emits terminating OEND
                case n.Right() != nil:
                        w.expr(n.Left())
                        w.expr(n.Right())
@@ -1405,15 +1435,37 @@ func (w *exportWriter) expr(n ir.Node) {
                }
 
        // unary expressions
-       case ir.OPLUS, ir.ONEG, ir.OADDR, ir.OBITNOT, ir.ODEREF, ir.ONOT, ir.ORECV:
-               w.op(op)
+       case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.ORECV:
+               w.op(n.Op())
+               w.pos(n.Pos())
+               w.expr(n.Left())
+
+       case ir.OADDR:
+               w.op(n.Op())
                w.pos(n.Pos())
                w.expr(n.Left())
 
+       case ir.ODEREF:
+               w.op(n.Op())
+               w.pos(n.Pos())
+               w.expr(n.Left())
+
+       case ir.OSEND:
+               w.op(n.Op())
+               w.pos(n.Pos())
+               w.expr(n.Left())
+               w.expr(n.Right())
+
        // binary expressions
-       case ir.OADD, ir.OAND, ir.OANDAND, ir.OANDNOT, ir.ODIV, ir.OEQ, ir.OGE, ir.OGT, ir.OLE, ir.OLT,
-               ir.OLSH, ir.OMOD, ir.OMUL, ir.ONE, ir.OOR, ir.OOROR, ir.ORSH, ir.OSEND, ir.OSUB, ir.OXOR:
-               w.op(op)
+       case ir.OADD, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OEQ, ir.OGE, ir.OGT, ir.OLE, ir.OLT,
+               ir.OLSH, ir.OMOD, ir.OMUL, ir.ONE, ir.OOR, ir.ORSH, ir.OSUB, ir.OXOR:
+               w.op(n.Op())
+               w.pos(n.Pos())
+               w.expr(n.Left())
+               w.expr(n.Right())
+
+       case ir.OANDAND, ir.OOROR:
+               w.op(n.Op())
                w.pos(n.Pos())
                w.expr(n.Left())
                w.expr(n.Right())
@@ -1454,15 +1506,16 @@ func (w *exportWriter) exprsOrNil(a, b ir.Node) {
        }
 }
 
-func (w *exportWriter) elemList(list ir.Nodes) {
+func (w *exportWriter) fieldList(list ir.Nodes) {
        w.uint64(uint64(list.Len()))
        for _, n := range list.Slice() {
+               n := n.(*ir.StructKeyExpr)
                w.selector(n.Sym())
                w.expr(n.Left())
        }
 }
 
-func (w *exportWriter) localName(n ir.Node) {
+func (w *exportWriter) localName(n *ir.Name) {
        // Escape analysis happens after inline bodies are saved, but
        // we're using the same ONAME nodes, so we might still see
        // PAUTOHEAP here.
index 1096d7988e37ff92de813967fc6212bcd6dd3c31..154c4e3a84339af1459d442dde08419807c04878 100644 (file)
@@ -753,7 +753,7 @@ func (r *importReader) stmtList() []ir.Node {
 }
 
 func (r *importReader) caseList(sw ir.Node) []ir.Node {
-       namedTypeSwitch := sw.Op() == ir.OSWITCH && sw.Left() != nil && sw.Left().Op() == ir.OTYPESW && sw.Left().Left() != nil
+       namedTypeSwitch := isNamedTypeSwitch(sw)
 
        cases := make([]ir.Node, r.uint64())
        for i := range cases {
@@ -766,7 +766,7 @@ func (r *importReader) caseList(sw ir.Node) []ir.Node {
                        caseVar := ir.NewNameAt(cas.Pos(), r.ident())
                        declare(caseVar, dclcontext)
                        cas.PtrRlist().Set1(caseVar)
-                       caseVar.Defn = sw.Left()
+                       caseVar.Defn = sw.(*ir.SwitchStmt).Left()
                }
                cas.PtrBody().Set(r.stmtList())
                cases[i] = cas
@@ -915,14 +915,14 @@ func (r *importReader) node() ir.Node {
                return n
 
        case ir.OCOPY, ir.OCOMPLEX, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.OCAP, ir.OCLOSE, ir.ODELETE, ir.OLEN, ir.OMAKE, ir.ONEW, ir.OPANIC, ir.ORECOVER, ir.OPRINT, ir.OPRINTN:
-               n := npos(r.pos(), builtinCall(op))
+               n := builtinCall(r.pos(), op)
                n.PtrList().Set(r.exprList())
                if op == ir.OAPPEND {
                        n.SetIsDDD(r.bool())
                }
                return n
 
-       // case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG:
+       // case OCALLFUNC, OCALLMETH, OCALLINTER, OGETG:
        //      unreachable - mapped to OCALL case below by exporter
 
        case ir.OCALL:
@@ -934,7 +934,7 @@ func (r *importReader) node() ir.Node {
                return n
 
        case ir.OMAKEMAP, ir.OMAKECHAN, ir.OMAKESLICE:
-               n := npos(r.pos(), builtinCall(ir.OMAKE))
+               n := builtinCall(r.pos(), ir.OMAKE)
                n.PtrList().Append(ir.TypeNode(r.typ()))
                n.PtrList().Append(r.exprList()...)
                return n
@@ -1042,8 +1042,7 @@ func (r *importReader) node() ir.Node {
        case ir.OSELECT:
                n := ir.NodAt(r.pos(), ir.OSELECT, nil, nil)
                n.PtrInit().Set(r.stmtList())
-               left, _ := r.exprsOrNil()
-               n.SetLeft(left)
+               r.exprsOrNil() // TODO(rsc): Delete (and fix exporter). These are always nil.
                n.PtrList().Set(r.caseList(n))
                return n
 
@@ -1110,3 +1109,12 @@ func (r *importReader) exprsOrNil() (a, b ir.Node) {
        }
        return
 }
+
+func builtinCall(pos src.XPos, op ir.Op) *ir.CallExpr {
+       return ir.NewCallExpr(pos, ir.OCALL, mkname(types.BuiltinPkg.Lookup(ir.OpNames[op])), nil)
+}
+
+func npos(pos src.XPos, n ir.Node) ir.Node {
+       n.SetPos(pos)
+       return n
+}