]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: make ir.Name the ONAME Node implementation
authorRuss Cox <rsc@golang.org>
Sat, 28 Nov 2020 06:41:13 +0000 (01:41 -0500)
committerRuss Cox <rsc@golang.org>
Mon, 30 Nov 2020 18:33:57 +0000 (18:33 +0000)
Before this CL, an ONAME Node was represented by three structs
linked together: a node, a Name, and a Param. Previous CLs removed
OLABEL and OPACK from the set of nodes that knew about Name.
Now Name can be repurposed to *be* the ONAME Node implementation,
replacing three linked structs totaling 152+64+88 = 304 bytes (64-bit)
with a single 232-byte struct.

Many expressions in the code become simpler as well, without having
to use .Param. and sometimes even .Name().
(For a node n where n.Name() != nil, n.Name() == n.(*Name) now.)

Passes buildall w/ toolstash -cmp.

Change-Id: Ie719f1285c05623b9fd2faaa059e5b360a64b3be
Reviewed-on: https://go-review.googlesource.com/c/go/+/274094
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
24 files changed:
src/cmd/compile/fmtmap_test.go
src/cmd/compile/internal/gc/alg.go
src/cmd/compile/internal/gc/align.go
src/cmd/compile/internal/gc/closure.go
src/cmd/compile/internal/gc/dcl.go
src/cmd/compile/internal/gc/embed.go
src/cmd/compile/internal/gc/escape.go
src/cmd/compile/internal/gc/gen.go
src/cmd/compile/internal/gc/iexport.go
src/cmd/compile/internal/gc/inl.go
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/gc/noder.go
src/cmd/compile/internal/gc/pgen.go
src/cmd/compile/internal/gc/plive.go
src/cmd/compile/internal/gc/subr.go
src/cmd/compile/internal/gc/typecheck.go
src/cmd/compile/internal/gc/universe.go
src/cmd/compile/internal/gc/walk.go
src/cmd/compile/internal/ir/expr.go [new file with mode: 0644]
src/cmd/compile/internal/ir/fmt.go
src/cmd/compile/internal/ir/mini.go
src/cmd/compile/internal/ir/name.go
src/cmd/compile/internal/ir/node.go
src/cmd/compile/internal/ir/sizeof_test.go

index 7a375604fd9f2ff9f2402d260a0b6628b2a5db72..978c83e5c2128cda028a806745afa5a091d709aa 100644 (file)
@@ -22,6 +22,7 @@ package main_test
 var knownFormats = map[string]string{
        "*bytes.Buffer %s":                                "",
        "*cmd/compile/internal/gc.EscLocation %v":         "",
+       "*cmd/compile/internal/ir.Name %v":                "",
        "*cmd/compile/internal/ir.node %v":                "",
        "*cmd/compile/internal/ssa.Block %s":              "",
        "*cmd/compile/internal/ssa.Block %v":              "",
index d2762126ade37623d8b68f5dcef35a623b2f8506..356f0eada76f97e253de48841da8ec72b3ff606c 100644 (file)
@@ -311,7 +311,7 @@ func genhash(t *types.Type) *obj.LSym {
                hashel := hashfor(t.Elem())
 
                n := ir.Nod(ir.ORANGE, nil, ir.Nod(ir.ODEREF, np, nil))
-               ni := NewName(lookup("i"))
+               ni := ir.Node(NewName(lookup("i")))
                ni.SetType(types.Types[types.TINT])
                n.PtrList().Set1(ni)
                n.SetColas(true)
index edf7d263a33cb53fc3bf2266c8e43c074ba723a4..4f8f04d73d004262e416cacfe5407aecc2da6e27 100644 (file)
@@ -126,8 +126,8 @@ func widstruct(errtype *types.Type, t *types.Type, o int64, flag int) int64 {
                        // NOTE(rsc): This comment may be stale.
                        // It's possible the ordering has changed and this is
                        // now the common case. I'm not sure.
-                       if n.Name().Param.Stackcopy != nil {
-                               n.Name().Param.Stackcopy.SetOffset(o)
+                       if n.Name().Stackcopy != nil {
+                               n.Name().Stackcopy.SetOffset(o)
                                n.SetOffset(0)
                        } else {
                                n.SetOffset(o)
@@ -198,8 +198,10 @@ func findTypeLoop(t *types.Type, path *[]*types.Type) bool {
                }
 
                *path = append(*path, t)
-               if p := ir.AsNode(t.Nod).Name().Param; p != nil && findTypeLoop(p.Ntype.Type(), path) {
-                       return true
+               if n := ir.AsNode(t.Nod); n != nil {
+                       if name := n.Name(); name != nil && name.Ntype != nil && findTypeLoop(name.Ntype.Type(), path) {
+                               return true
+                       }
                }
                *path = (*path)[:len(*path)-1]
        } else {
index 2901ae41d6eba5689c0bf8756d5af090797ab3e0..7a1078326dee4eb96823ad92ba10273c28ff3a12 100644 (file)
@@ -21,7 +21,7 @@ func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node {
        fn := dcl.Func()
        fn.SetIsHiddenClosure(Curfn != nil)
        fn.Nname = newfuncnamel(p.pos(expr), ir.BlankNode.Sym(), fn) // filled in by typecheckclosure
-       fn.Nname.Name().Param.Ntype = xtype
+       fn.Nname.Name().Ntype = xtype
        fn.Nname.Name().Defn = dcl
 
        clo := p.nod(expr, ir.OCLOSURE, nil, nil)
@@ -38,7 +38,7 @@ func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node {
        for _, v := range fn.ClosureVars.Slice() {
                // Unlink from v1; see comment in syntax.go type Param for these fields.
                v1 := v.Name().Defn
-               v1.Name().Param.Innermost = v.Name().Param.Outer
+               v1.Name().Innermost = v.Name().Outer
 
                // If the closure usage of v is not dense,
                // we need to make it dense; now that we're out
@@ -68,7 +68,7 @@ func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node {
                // obtains f3's v, creating it if necessary (as it is in the example).
                //
                // capturevars will decide whether to use v directly or &v.
-               v.Name().Param.Outer = oldname(v.Sym())
+               v.Name().Outer = oldname(v.Sym()).(*ir.Name)
        }
 
        return clo
@@ -194,7 +194,8 @@ func capturevars(dcl ir.Node) {
                // so that the outer frame also grabs them and knows they escape.
                dowidth(v.Type())
 
-               outer := v.Name().Param.Outer
+               var outer ir.Node
+               outer = v.Name().Outer
                outermost := v.Name().Defn
 
                // out parameters will be assigned to implicitly upon return.
@@ -262,7 +263,7 @@ func transformclosure(dcl ir.Node) {
                                // (accesses will implicitly deref &v).
                                addr := NewName(lookup("&" + v.Sym().Name))
                                addr.SetType(types.NewPtr(v.Type()))
-                               v.Name().Param.Heapaddr = addr
+                               v.Name().Heapaddr = addr
                                v = addr
                        }
 
@@ -312,7 +313,7 @@ func transformclosure(dcl ir.Node) {
                                addr.Name().SetUsed(true)
                                addr.Name().Curfn = dcl
                                fn.Dcl = append(fn.Dcl, addr)
-                               v.Name().Param.Heapaddr = addr
+                               v.Name().Heapaddr = addr
                                if v.Name().Byval() {
                                        cv = ir.Nod(ir.OADDR, cv, nil)
                                }
index 2a7be137c0698db5fb4e19472f220bfd6f306939..04e6e7a596a7c04ebd91e3fe87abada1dd5bb7c1 100644 (file)
@@ -12,7 +12,6 @@ import (
        "cmd/internal/obj"
        "cmd/internal/src"
        "fmt"
-       "go/constant"
        "strings"
 )
 
@@ -64,11 +63,6 @@ func declare(n ir.Node, ctxt ir.Class) {
                return
        }
 
-       if n.Name() == nil {
-               // named OLITERAL needs Name; most OLITERALs don't.
-               n.SetName(new(ir.Name))
-       }
-
        s := n.Sym()
 
        // kludgy: typecheckok means we're past parsing. Eg genwrapper may declare out of package names later.
@@ -152,7 +146,7 @@ func variter(vl []ir.Node, t ir.Node, el []ir.Node) []ir.Node {
                for _, v := range vl {
                        v.SetOp(ir.ONAME)
                        declare(v, dclcontext)
-                       v.Name().Param.Ntype = t
+                       v.Name().Ntype = t
                        v.Name().Defn = as2
                        if Curfn != nil {
                                init = append(init, ir.Nod(ir.ODCL, v, nil))
@@ -176,7 +170,7 @@ func variter(vl []ir.Node, t ir.Node, el []ir.Node) []ir.Node {
 
                v.SetOp(ir.ONAME)
                declare(v, dclcontext)
-               v.Name().Param.Ntype = t
+               v.Name().Ntype = t
 
                if e != nil || Curfn != nil || ir.IsBlank(v) {
                        if Curfn != nil {
@@ -201,9 +195,8 @@ func newnoname(s *types.Sym) ir.Node {
        if s == nil {
                base.Fatalf("newnoname nil")
        }
-       n := ir.Nod(ir.ONONAME, nil, nil)
-       n.SetSym(s)
-       n.SetOffset(0)
+       n := ir.NewNameAt(base.Pos, s)
+       n.SetOp(ir.ONONAME)
        return n
 }
 
@@ -220,7 +213,7 @@ func newfuncnamel(pos src.XPos, s *types.Sym, fn *ir.Func) ir.Node {
 
 // this generates a new name node for a name
 // being declared.
-func dclname(s *types.Sym) ir.Node {
+func dclname(s *types.Sym) *ir.Name {
        n := NewName(s)
        n.SetOp(ir.ONONAME) // caller will correct it
        return n
@@ -277,7 +270,7 @@ func oldname(s *types.Sym) ir.Node {
                // are parsing x := 5 inside the closure, until we get to
                // the := it looks like a reference to the outer x so we'll
                // make x a closure variable unnecessarily.
-               c := n.Name().Param.Innermost
+               c := n.Name().Innermost
                if c == nil || c.Name().Curfn != Curfn {
                        // Do not have a closure var for the active closure yet; make one.
                        c = NewName(s)
@@ -288,8 +281,8 @@ func oldname(s *types.Sym) ir.Node {
 
                        // Link into list of active closure variables.
                        // Popped from list in func funcLit.
-                       c.Name().Param.Outer = n.Name().Param.Innermost
-                       n.Name().Param.Innermost = c
+                       c.Name().Outer = n.Name().Innermost
+                       n.Name().Innermost = c
 
                        Curfn.Func().ClosureVars.Append(c)
                }
@@ -392,8 +385,8 @@ func funchdr(n ir.Node) {
 
        types.Markdcl()
 
-       if n.Func().Nname != nil && n.Func().Nname.Name().Param.Ntype != nil {
-               funcargs(n.Func().Nname.Name().Param.Ntype)
+       if n.Func().Nname != nil && n.Func().Nname.Name().Ntype != nil {
+               funcargs(n.Func().Nname.Name().Ntype)
        } else {
                funcargs2(n.Type())
        }
@@ -458,7 +451,7 @@ func funcarg(n ir.Node, ctxt ir.Class) {
        }
 
        n.SetRight(ir.NewNameAt(n.Pos(), n.Sym()))
-       n.Right().Name().Param.Ntype = n.Left()
+       n.Right().Name().Ntype = n.Left()
        n.Right().SetIsDDD(n.IsDDD())
        declare(n.Right(), ctxt)
 
@@ -554,8 +547,8 @@ func structfield(n ir.Node) *types.Field {
                checkembeddedtype(n.Type())
                f.Embedded = 1
        }
-       if n.HasVal() {
-               f.Note = constant.StringVal(n.Val())
+       if n.Opt() != nil {
+               f.Note = n.Opt().(string)
        }
 
        base.Pos = lno
@@ -640,7 +633,7 @@ func interfacefield(n ir.Node) *types.Field {
                base.Fatalf("interfacefield: oops %v\n", n)
        }
 
-       if n.HasVal() {
+       if n.Opt() != nil {
                base.Errorf("interface method cannot have annotation")
        }
 
@@ -952,10 +945,10 @@ func dclfunc(sym *types.Sym, tfn ir.Node) ir.Node {
        fn := ir.Nod(ir.ODCLFUNC, nil, nil)
        fn.Func().Nname = newfuncnamel(base.Pos, sym, fn.Func())
        fn.Func().Nname.Name().Defn = fn
-       fn.Func().Nname.Name().Param.Ntype = tfn
+       fn.Func().Nname.Name().Ntype = tfn
        setNodeNameFunc(fn.Func().Nname)
        funchdr(fn)
-       fn.Func().Nname.Name().Param.Ntype = typecheck(fn.Func().Nname.Name().Param.Ntype, ctxType)
+       fn.Func().Nname.Name().Ntype = typecheck(fn.Func().Nname.Name().Ntype, ctxType)
        return fn
 }
 
index 33b05a5bf08898bc7cc21f3d03f221d935474e72..1c8ccdadefeb5b8ffeaef92f1ab3300477b5afc3 100644 (file)
@@ -115,13 +115,13 @@ func varEmbed(p *noder, names []ir.Node, typ ir.Node, exprs []ir.Node, embeds []
                numLocalEmbed++
                v = ir.NewNameAt(v.Pos(), lookupN("embed.", numLocalEmbed))
                v.Sym().Def = v
-               v.Name().Param.Ntype = typ
+               v.Name().Ntype = typ
                v.SetClass(ir.PEXTERN)
                externdcl = append(externdcl, v)
                exprs = []ir.Node{v}
        }
 
-       v.Name().Param.SetEmbedFiles(list)
+       v.Name().SetEmbedFiles(list)
        embedlist = append(embedlist, v)
        return exprs
 }
@@ -193,7 +193,7 @@ func dumpembeds() {
 // initEmbed emits the init data for a //go:embed variable,
 // which is either a string, a []byte, or an embed.FS.
 func initEmbed(v ir.Node) {
-       files := v.Name().Param.EmbedFiles()
+       files := v.Name().EmbedFiles()
        switch kind := embedKind(v.Type()); kind {
        case embedUnknown:
                base.ErrorfAt(v.Pos(), "go:embed cannot apply to var of type %v", v.Type())
index e3ac883e958cbec79341143d79990a437cc20b15..351643ef5d4c34900423c489d7144858d97c53bb 100644 (file)
@@ -1895,7 +1895,7 @@ func moveToHeap(n ir.Node) {
                stackcopy.SetType(n.Type())
                stackcopy.SetOffset(n.Offset())
                stackcopy.SetClass(n.Class())
-               stackcopy.Name().Param.Heapaddr = heapaddr
+               stackcopy.Name().Heapaddr = heapaddr
                if n.Class() == ir.PPARAMOUT {
                        // Make sure the pointer to the heap copy is kept live throughout the function.
                        // The function could panic at any point, and then a defer could recover.
@@ -1904,7 +1904,7 @@ func moveToHeap(n ir.Node) {
                        // See issue 16095.
                        heapaddr.Name().SetIsOutputParamHeapAddr(true)
                }
-               n.Name().Param.Stackcopy = stackcopy
+               n.Name().Stackcopy = stackcopy
 
                // Substitute the stackcopy into the function variable list so that
                // liveness and other analyses use the underlying stack slot
@@ -1931,7 +1931,7 @@ func moveToHeap(n ir.Node) {
        // Modify n in place so that uses of n now mean indirection of the heapaddr.
        n.SetClass(ir.PAUTOHEAP)
        n.SetOffset(0)
-       n.Name().Param.Heapaddr = heapaddr
+       n.Name().Heapaddr = heapaddr
        n.SetEsc(EscHeap)
        if base.Flag.LowerM != 0 {
                base.WarnfAt(n.Pos(), "moved to heap: %v", n)
index cb640c7ccf76ffa459854b7e4ca902f246437516..cf9e0d58bfcfd6457c104e2c456046a09e456dc5 100644 (file)
@@ -31,13 +31,13 @@ func sysvar(name string) *obj.LSym {
 // isParamStackCopy reports whether this is the on-stack copy of a
 // function parameter that moved to the heap.
 func isParamStackCopy(n ir.Node) bool {
-       return n.Op() == ir.ONAME && (n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT) && n.Name().Param.Heapaddr != nil
+       return n.Op() == ir.ONAME && (n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT) && n.Name().Heapaddr != nil
 }
 
 // isParamHeapCopy reports whether this is the on-heap copy of
 // a function parameter that moved to the heap.
 func isParamHeapCopy(n ir.Node) bool {
-       return n.Op() == ir.ONAME && n.Class() == ir.PAUTOHEAP && n.Name().Param.Stackcopy != nil
+       return n.Op() == ir.ONAME && n.Class() == ir.PAUTOHEAP && n.Name().Stackcopy != nil
 }
 
 // autotmpname returns the name for an autotmp variable numbered n.
@@ -52,7 +52,7 @@ func autotmpname(n int) string {
 }
 
 // make a new Node off the books
-func tempAt(pos src.XPos, curfn ir.Node, t *types.Type) ir.Node {
+func tempAt(pos src.XPos, curfn ir.Node, t *types.Type) *ir.Name {
        if curfn == nil {
                base.Fatalf("no curfn for tempAt")
        }
@@ -80,9 +80,9 @@ func tempAt(pos src.XPos, curfn ir.Node, t *types.Type) ir.Node {
 
        dowidth(t)
 
-       return ir.Orig(n)
+       return n
 }
 
-func temp(t *types.Type) ir.Node {
+func temp(t *types.Type) *ir.Name {
        return tempAt(base.Pos, Curfn, t)
 }
index c2ea599af40e3ac7a35295b4fd9be310c1141985..88d3a6477c0cf2b5d9be6bc5d2d9960d8e916575 100644 (file)
@@ -1463,7 +1463,7 @@ func (w *exportWriter) localName(n ir.Node) {
        // PPARAM/PPARAMOUT, because we only want to include vargen in
        // non-param names.
        var v int32
-       if n.Class() == ir.PAUTO || (n.Class() == ir.PAUTOHEAP && n.Name().Param.Stackcopy == nil) {
+       if n.Class() == ir.PAUTO || (n.Class() == ir.PAUTOHEAP && n.Name().Stackcopy == nil) {
                v = n.Name().Vargen
        }
 
index d43d0d06af4595a5de53a49fdeb68e94e5a81269..102144aedf42dc6cfdfed75d02ab345d35bc6171 100644 (file)
@@ -982,7 +982,7 @@ func mkinlcall(n, fn ir.Node, maxCost int32, inlMap map[ir.Node]bool) ir.Node {
                                        continue
                                }
 
-                               o := v.Name().Param.Outer
+                               o := v.Name().Outer
                                // make sure the outer param matches the inlining location
                                // NB: if we enabled inlining of functions containing OCLOSURE or refined
                                // the reassigned check via some sort of copy propagation this would most
index 7d2933f3602d869c4235477c336867224a6a00c7..931626159d9d078842ee47cef471fd651239a95d 100644 (file)
@@ -253,7 +253,7 @@ func Main(archInit func(*Arch)) {
        timings.Start("fe", "typecheck", "top1")
        for i := 0; i < len(xtop); i++ {
                n := xtop[i]
-               if op := n.Op(); op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.Left().Name().Param.Alias()) {
+               if op := n.Op(); op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.Left().Name().Alias()) {
                        xtop[i] = typecheck(n, ctxStmt)
                }
        }
@@ -265,7 +265,7 @@ func Main(archInit func(*Arch)) {
        timings.Start("fe", "typecheck", "top2")
        for i := 0; i < len(xtop); i++ {
                n := xtop[i]
-               if op := n.Op(); op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.Left().Name().Param.Alias() {
+               if op := n.Op(); op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.Left().Name().Alias() {
                        xtop[i] = typecheck(n, ctxStmt)
                }
        }
index 54915d76931fb57b6924ac13b34db5653bd34a98..cbe8a2405164b1e163fd2a7604dd66ee8964140b 100644 (file)
@@ -456,7 +456,7 @@ func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []ir.Node {
                n.SetOp(ir.OLITERAL)
                declare(n, dclcontext)
 
-               n.Name().Param.Ntype = typ
+               n.Name().Ntype = typ
                n.Name().Defn = v
                n.SetIota(cs.iota)
 
@@ -480,19 +480,18 @@ func (p *noder) typeDecl(decl *syntax.TypeDecl) ir.Node {
        // decl.Type may be nil but in that case we got a syntax error during parsing
        typ := p.typeExprOrNil(decl.Type)
 
-       param := n.Name().Param
-       param.Ntype = typ
-       param.SetAlias(decl.Alias)
+       n.Ntype = typ
+       n.SetAlias(decl.Alias)
        if pragma, ok := decl.Pragma.(*Pragma); ok {
                if !decl.Alias {
-                       param.SetPragma(pragma.Flag & TypePragmas)
+                       n.SetPragma(pragma.Flag & TypePragmas)
                        pragma.Flag &^= TypePragmas
                }
                p.checkUnused(pragma)
        }
 
        nod := p.nod(decl, ir.ODCLTYPE, n, nil)
-       if param.Alias() && !langSupported(1, 9, ir.LocalPkg) {
+       if n.Alias() && !langSupported(1, 9, ir.LocalPkg) {
                base.ErrorfAt(nod.Pos(), "type aliases only supported as of -lang=go1.9")
        }
        return nod
@@ -506,7 +505,7 @@ func (p *noder) declNames(names []*syntax.Name) []ir.Node {
        return nodes
 }
 
-func (p *noder) declName(name *syntax.Name) ir.Node {
+func (p *noder) declName(name *syntax.Name) *ir.Name {
        n := dclname(p.name(name))
        n.SetPos(p.pos(name))
        return n
@@ -537,7 +536,7 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node {
 
        f.Func().Nname = newfuncnamel(p.pos(fun.Name), name, f.Func())
        f.Func().Nname.Name().Defn = f
-       f.Func().Nname.Name().Param.Ntype = t
+       f.Func().Nname.Name().Ntype = t
 
        if pragma, ok := fun.Pragma.(*Pragma); ok {
                f.Func().Pragma = pragma.Flag & FuncPragmas
@@ -872,7 +871,7 @@ func (p *noder) structType(expr *syntax.StructType) ir.Node {
                        n = p.nodSym(field, ir.ODCLFIELD, p.typeExpr(field.Type), p.name(field.Name))
                }
                if i < len(expr.TagList) && expr.TagList[i] != nil {
-                       n.SetVal(p.basicLit(expr.TagList[i]))
+                       n.SetOpt(constant.StringVal(p.basicLit(expr.TagList[i])))
                }
                l = append(l, n)
        }
index 221b733a070a6144c9d110eb29cb5d5ec6fb1b41..b74b132632b9bc222b0118a6e7fdb8377b831794 100644 (file)
@@ -667,7 +667,7 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []ir.
                        // misleading location for the param (we want pointer-to-heap
                        // and not stack).
                        // TODO(thanm): generate a better location expression
-                       stackcopy := n.Name().Param.Stackcopy
+                       stackcopy := n.Name().Stackcopy
                        if stackcopy != nil && (stackcopy.Class() == ir.PPARAM || stackcopy.Class() == ir.PPARAMOUT) {
                                abbrev = dwarf.DW_ABRV_PARAM_LOCLIST
                                isReturnValue = (stackcopy.Class() == ir.PPARAMOUT)
index bd7696d859c212df8a05777fc515751611d9310e..e3a9b2a1988d6bb54da05a1cfc05db6a2574372a 100644 (file)
@@ -795,7 +795,7 @@ func (lv *Liveness) epilogue() {
                                        // Just to be paranoid.  Heap addresses are PAUTOs.
                                        base.Fatalf("variable %v both output param and heap output param", n)
                                }
-                               if n.Name().Param.Heapaddr != nil {
+                               if n.Name().Heapaddr != nil {
                                        // If this variable moved to the heap, then
                                        // its stack copy is not live.
                                        continue
index 5c410ce3ba5e595ee2475bc5f48ac909e53a829a..28703205d665571c49abe0cc044e1e7a734ecd7a 100644 (file)
@@ -136,7 +136,7 @@ func importdot(opkg *types.Pkg, pack *ir.PkgName) {
 }
 
 // newname returns a new ONAME Node associated with symbol s.
-func NewName(s *types.Sym) ir.Node {
+func NewName(s *types.Sym) *ir.Name {
        n := ir.NewNameAt(base.Pos, s)
        n.Name().Curfn = Curfn
        return n
index 0c4a3ad833a51e92dd25e4aee0ed20bb796d603e..4ab47fb4069a96a7dcba8eccbf98adb2f73a61db 100644 (file)
@@ -259,12 +259,12 @@ func typecheck(n ir.Node, top int) (res ir.Node) {
                                // are substituted.
                                cycle := cycleFor(n)
                                for _, n1 := range cycle {
-                                       if n1.Name() != nil && !n1.Name().Param.Alias() {
+                                       if n1.Name() != nil && !n1.Name().Alias() {
                                                // Cycle is ok. But if n is an alias type and doesn't
                                                // have a type yet, we have a recursive type declaration
                                                // with aliases that we can't handle properly yet.
                                                // Report an error rather than crashing later.
-                                               if n.Name() != nil && n.Name().Param.Alias() && n.Type() == nil {
+                                               if n.Name() != nil && n.Name().Alias() && n.Type() == nil {
                                                        base.Pos = n.Pos()
                                                        base.Fatalf("cannot handle alias type declaration (issue #25838): %v", n)
                                                }
@@ -2412,9 +2412,6 @@ func typecheckMethodExpr(n ir.Node) (res ir.Node) {
        }
 
        n.SetOp(ir.OMETHEXPR)
-       if n.Name() == nil {
-               n.SetName(new(ir.Name))
-       }
        n.SetRight(NewName(n.Sym()))
        n.SetSym(methodSym(t, n.Sym()))
        n.SetType(methodfunc(m.Type, n.Left().Type()))
@@ -3228,7 +3225,7 @@ func typecheckas(n ir.Node) {
        // so that the conversion below happens).
        n.SetLeft(resolve(n.Left()))
 
-       if n.Left().Name() == nil || n.Left().Name().Defn != n || n.Left().Name().Param.Ntype != nil {
+       if n.Left().Name() == nil || n.Left().Name().Defn != n || n.Left().Name().Ntype != nil {
                n.SetLeft(typecheck(n.Left(), ctxExpr|ctxAssign))
        }
 
@@ -3247,7 +3244,7 @@ func typecheckas(n ir.Node) {
                }
        }
 
-       if n.Left().Name() != nil && n.Left().Name().Defn == n && n.Left().Name().Param.Ntype == nil {
+       if n.Left().Name() != nil && n.Left().Name().Defn == n && n.Left().Name().Ntype == nil {
                n.SetRight(defaultlit(n.Right(), nil))
                n.Left().SetType(n.Right().Type())
        }
@@ -3283,7 +3280,7 @@ func typecheckas2(n ir.Node) {
                n1 = resolve(n1)
                ls[i1] = n1
 
-               if n1.Name() == nil || n1.Name().Defn != n || n1.Name().Param.Ntype != nil {
+               if n1.Name() == nil || n1.Name().Defn != n || n1.Name().Ntype != nil {
                        ls[i1] = typecheck(ls[i1], ctxExpr|ctxAssign)
                }
        }
@@ -3308,7 +3305,7 @@ func typecheckas2(n ir.Node) {
                        if nl.Type() != nil && nr.Type() != nil {
                                rs[il] = assignconv(nr, nl.Type(), "assignment")
                        }
-                       if nl.Name() != nil && nl.Name().Defn == n && nl.Name().Param.Ntype == nil {
+                       if nl.Name() != nil && nl.Name().Defn == n && nl.Name().Ntype == nil {
                                rs[il] = defaultlit(rs[il], nil)
                                nl.SetType(rs[il].Type())
                        }
@@ -3342,7 +3339,7 @@ func typecheckas2(n ir.Node) {
                                if f.Type != nil && l.Type() != nil {
                                        checkassignto(f.Type, l)
                                }
-                               if l.Name() != nil && l.Name().Defn == n && l.Name().Param.Ntype == nil {
+                               if l.Name() != nil && l.Name().Defn == n && l.Name().Ntype == nil {
                                        l.SetType(f.Type)
                                }
                        }
@@ -3378,7 +3375,7 @@ func typecheckas2(n ir.Node) {
                        if l.Type() != nil && !l.Type().IsBoolean() {
                                checkassignto(types.Types[types.TBOOL], l)
                        }
-                       if l.Name() != nil && l.Name().Defn == n && l.Name().Param.Ntype == nil {
+                       if l.Name() != nil && l.Name().Defn == n && l.Name().Ntype == nil {
                                l.SetType(types.Types[types.TBOOL])
                        }
                        goto out
@@ -3502,7 +3499,7 @@ func setUnderlying(t, underlying *types.Type) {
        }
 
        // Propagate go:notinheap pragma from the Name to the Type.
-       if n.Name() != nil && n.Name().Param != nil && n.Name().Param.Pragma()&ir.NotInHeap != 0 {
+       if n.Name() != nil && n.Name().Pragma()&ir.NotInHeap != 0 {
                t.SetNotInHeap(true)
        }
 
@@ -3525,8 +3522,8 @@ func typecheckdeftype(n ir.Node) {
        }
 
        n.SetTypecheck(1)
-       n.Name().Param.Ntype = typecheck(n.Name().Param.Ntype, ctxType)
-       t := n.Name().Param.Ntype.Type()
+       n.Name().Ntype = typecheck(n.Name().Ntype, ctxType)
+       t := n.Name().Ntype.Type()
        if t == nil {
                n.SetDiag(true)
                n.SetType(nil)
@@ -3586,10 +3583,10 @@ func typecheckdef(n ir.Node) {
                base.Fatalf("typecheckdef %v", n.Op())
 
        case ir.OLITERAL:
-               if n.Name().Param.Ntype != nil {
-                       n.Name().Param.Ntype = typecheck(n.Name().Param.Ntype, ctxType)
-                       n.SetType(n.Name().Param.Ntype.Type())
-                       n.Name().Param.Ntype = nil
+               if n.Name().Ntype != nil {
+                       n.Name().Ntype = typecheck(n.Name().Ntype, ctxType)
+                       n.SetType(n.Name().Ntype.Type())
+                       n.Name().Ntype = nil
                        if n.Type() == nil {
                                n.SetDiag(true)
                                goto ret
@@ -3640,9 +3637,9 @@ func typecheckdef(n ir.Node) {
                }
 
        case ir.ONAME:
-               if n.Name().Param.Ntype != nil {
-                       n.Name().Param.Ntype = typecheck(n.Name().Param.Ntype, ctxType)
-                       n.SetType(n.Name().Param.Ntype.Type())
+               if n.Name().Ntype != nil {
+                       n.Name().Ntype = typecheck(n.Name().Ntype, ctxType)
+                       n.SetType(n.Name().Ntype.Type())
                        if n.Type() == nil {
                                n.SetDiag(true)
                                goto ret
@@ -3676,21 +3673,22 @@ func typecheckdef(n ir.Node) {
                n.Name().Defn = typecheck(n.Name().Defn, ctxStmt) // fills in n.Type
 
        case ir.OTYPE:
-               if p := n.Name().Param; p.Alias() {
+               n := n.(*ir.Name)
+               if n.Alias() {
                        // Type alias declaration: Simply use the rhs type - no need
                        // to create a new type.
                        // If we have a syntax error, p.Ntype may be nil.
-                       if p.Ntype != nil {
-                               p.Ntype = typecheck(p.Ntype, ctxType)
-                               n.SetType(p.Ntype.Type())
+                       if n.Ntype != nil {
+                               n.Ntype = typecheck(n.Ntype, ctxType)
+                               n.SetType(n.Ntype.Type())
                                if n.Type() == nil {
                                        n.SetDiag(true)
                                        goto ret
                                }
                                // For package-level type aliases, set n.Sym.Def so we can identify
                                // it as a type alias during export. See also #31959.
-                               if n.Name().Curfn == nil {
-                                       n.Sym().Def = p.Ntype
+                               if n.Curfn == nil {
+                                       n.Sym().Def = n.Ntype
                                }
                        }
                        break
index 978e53ac159a72e61595933d3bb58208b076eaf3..1068720748002cf5fcfd9d0112957ff834ae8a85 100644 (file)
@@ -110,7 +110,6 @@ func lexinit() {
                        types.Types[etype] = t
                }
                s2.Def = typenod(t)
-               ir.AsNode(s2.Def).SetName(new(ir.Name))
        }
 
        for _, s := range &builtinFuncs {
@@ -132,13 +131,11 @@ func lexinit() {
        s := ir.BuiltinPkg.Lookup("true")
        s.Def = nodbool(true)
        ir.AsNode(s.Def).SetSym(lookup("true"))
-       ir.AsNode(s.Def).SetName(new(ir.Name))
        ir.AsNode(s.Def).SetType(types.UntypedBool)
 
        s = ir.BuiltinPkg.Lookup("false")
        s.Def = nodbool(false)
        ir.AsNode(s.Def).SetSym(lookup("false"))
-       ir.AsNode(s.Def).SetName(new(ir.Name))
        ir.AsNode(s.Def).SetType(types.UntypedBool)
 
        s = lookup("_")
@@ -158,12 +155,10 @@ func lexinit() {
        s = ir.BuiltinPkg.Lookup("nil")
        s.Def = nodnil()
        ir.AsNode(s.Def).SetSym(s)
-       ir.AsNode(s.Def).SetName(new(ir.Name))
 
        s = ir.BuiltinPkg.Lookup("iota")
        s.Def = ir.Nod(ir.OIOTA, nil, nil)
        ir.AsNode(s.Def).SetSym(s)
-       ir.AsNode(s.Def).SetName(new(ir.Name))
 }
 
 func typeinit() {
@@ -182,7 +177,6 @@ func typeinit() {
        types.Types[types.TUNSAFEPTR] = t
        t.Sym = unsafepkg.Lookup("Pointer")
        t.Sym.Def = typenod(t)
-       ir.AsNode(t.Sym.Def).SetName(new(ir.Name))
        dowidth(types.Types[types.TUNSAFEPTR])
 
        for et := types.TINT8; et <= types.TUINT64; et++ {
@@ -359,7 +353,6 @@ func lexinit1() {
        types.Bytetype = types.New(types.TUINT8)
        types.Bytetype.Sym = s
        s.Def = typenod(types.Bytetype)
-       ir.AsNode(s.Def).SetName(new(ir.Name))
        dowidth(types.Bytetype)
 
        // rune alias
@@ -367,7 +360,6 @@ func lexinit1() {
        types.Runetype = types.New(types.TINT32)
        types.Runetype.Sym = s
        s.Def = typenod(types.Runetype)
-       ir.AsNode(s.Def).SetName(new(ir.Name))
        dowidth(types.Runetype)
 
        // backend-dependent builtin types (e.g. int).
@@ -385,7 +377,6 @@ func lexinit1() {
                t.Sym = s1
                types.Types[s.etype] = t
                s1.Def = typenod(t)
-               ir.AsNode(s1.Def).SetName(new(ir.Name))
                s1.Origpkg = ir.BuiltinPkg
 
                dowidth(t)
index 87fe36b08a0104a0dc5015e2ce3c1a46dc2e5753..c05aa0c37217c4f669f306e32a334829a0eb4152 100644 (file)
@@ -196,7 +196,7 @@ func walkstmt(n ir.Node) ir.Node {
                        if prealloc[v] == nil {
                                prealloc[v] = callnew(v.Type())
                        }
-                       nn := ir.Nod(ir.OAS, v.Name().Param.Heapaddr, prealloc[v])
+                       nn := ir.Nod(ir.OAS, v.Name().Heapaddr, prealloc[v])
                        nn.SetColas(true)
                        nn = typecheck(nn, ctxStmt)
                        return walkstmt(nn)
@@ -286,7 +286,7 @@ func walkstmt(n ir.Node) ir.Node {
                                }
                                if cl == ir.PPARAMOUT {
                                        if isParamStackCopy(ln) {
-                                               ln = walkexpr(typecheck(ir.Nod(ir.ODEREF, ln.Name().Param.Heapaddr, nil), ctxExpr), nil)
+                                               ln = walkexpr(typecheck(ir.Nod(ir.ODEREF, ln.Name().Heapaddr, nil), ctxExpr), nil)
                                        }
                                        rl = append(rl, ln)
                                }
@@ -314,7 +314,7 @@ func walkstmt(n ir.Node) ir.Node {
                for i, nl := range lhs.FieldSlice() {
                        nname := ir.AsNode(nl.Nname)
                        if isParamHeapCopy(nname) {
-                               nname = nname.Name().Param.Stackcopy
+                               nname = nname.Name().Stackcopy
                        }
                        a := ir.Nod(ir.OAS, nname, rhs[i])
                        res[i] = convas(a, n.PtrInit())
@@ -456,7 +456,7 @@ func walkexpr(n ir.Node, init *ir.Nodes) ir.Node {
        }
 
        if n.Op() == ir.ONAME && n.Class() == ir.PAUTOHEAP {
-               nn := ir.Nod(ir.ODEREF, n.Name().Param.Heapaddr, nil)
+               nn := ir.Nod(ir.ODEREF, n.Name().Heapaddr, nil)
                nn = typecheck(nn, ctxExpr)
                nn = walkexpr(nn, init)
                nn.Left().MarkNonNil()
@@ -1160,7 +1160,7 @@ opswitch:
                        if n.Type().Elem().Width >= maxImplicitStackVarSize {
                                base.Fatalf("large ONEW with EscNone: %v", n)
                        }
-                       r := temp(n.Type().Elem())
+                       r := ir.Node(temp(n.Type().Elem()))
                        r = ir.Nod(ir.OAS, r, nil) // zero temp
                        r = typecheck(r, ctxStmt)
                        init.Append(r)
@@ -1776,7 +1776,7 @@ func ascompatet(nl ir.Nodes, nr *types.Type) []ir.Node {
                // Any assignment to an lvalue that might cause a function call must be
                // deferred until all the returned values have been read.
                if fncall(l, r.Type) {
-                       tmp := temp(r.Type)
+                       tmp := ir.Node(temp(r.Type))
                        tmp = typecheck(tmp, ctxExpr)
                        a := ir.Nod(ir.OAS, l, tmp)
                        a = convas(a, &mm)
@@ -2174,7 +2174,7 @@ func reorder3save(n ir.Node, all []ir.Node, i int, early *[]ir.Node) ir.Node {
                return n
        }
 
-       q := temp(n.Type())
+       q := ir.Node(temp(n.Type()))
        q = ir.Nod(ir.OAS, q, n)
        q = typecheck(q, ctxStmt)
        *early = append(*early, q)
@@ -2411,7 +2411,7 @@ func paramstoheap(params *types.Type) []ir.Node {
                        continue
                }
 
-               if stackcopy := v.Name().Param.Stackcopy; stackcopy != nil {
+               if stackcopy := v.Name().Stackcopy; stackcopy != nil {
                        nn = append(nn, walkstmt(ir.Nod(ir.ODCL, v, nil)))
                        if stackcopy.Class() == ir.PPARAM {
                                nn = append(nn, walkstmt(typecheck(ir.Nod(ir.OAS, v, stackcopy), ctxStmt)))
@@ -2432,7 +2432,7 @@ func paramstoheap(params *types.Type) []ir.Node {
 func zeroResults() {
        for _, f := range Curfn.Type().Results().Fields().Slice() {
                v := ir.AsNode(f.Nname)
-               if v != nil && v.Name().Param.Heapaddr != nil {
+               if v != nil && v.Name().Heapaddr != nil {
                        // The local which points to the return value is the
                        // thing that needs zeroing. This is already handled
                        // by a Needzero annotation in plive.go:livenessepilogue.
@@ -2445,7 +2445,7 @@ func zeroResults() {
                        // I don't think the zeroing below matters.
                        // The stack return value will never be marked as live anywhere in the function.
                        // It is not written to until deferreturn returns.
-                       v = v.Name().Param.Stackcopy
+                       v = v.Name().Stackcopy
                }
                // Zero the stack location containing f.
                Curfn.Func().Enter.Append(ir.NodAt(Curfn.Pos(), ir.OAS, v, nil))
@@ -2461,7 +2461,7 @@ func returnsfromheap(params *types.Type) []ir.Node {
                if v == nil {
                        continue
                }
-               if stackcopy := v.Name().Param.Stackcopy; stackcopy != nil && stackcopy.Class() == ir.PPARAMOUT {
+               if stackcopy := v.Name().Stackcopy; stackcopy != nil && stackcopy.Class() == ir.PPARAMOUT {
                        nn = append(nn, walkstmt(typecheck(ir.Nod(ir.OAS, stackcopy, v), ctxStmt)))
                }
        }
@@ -3155,7 +3155,7 @@ func copyany(n ir.Node, init *ir.Nodes, runtimecall bool) ir.Node {
 
        fn := syslook("memmove")
        fn = substArgTypes(fn, nl.Type().Elem(), nl.Type().Elem())
-       nwid := temp(types.Types[types.TUINTPTR])
+       nwid := ir.Node(temp(types.Types[types.TUINTPTR]))
        setwid := ir.Nod(ir.OAS, nwid, conv(nlen, types.Types[types.TUINTPTR]))
        ne.PtrBody().Append(setwid)
        nwid = ir.Nod(ir.OMUL, nwid, nodintconst(nl.Type().Elem().Width))
diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go
new file mode 100644 (file)
index 0000000..4183517
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2020 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 ir
+
+import (
+       "cmd/compile/internal/types"
+)
+
+// A miniStmt is a miniNode with extra fields common to expressions.
+// TODO(rsc): Once we are sure about the contents, compact the bools
+// into a bit field and leave extra bits available for implementations
+// embedding miniExpr. Right now there are ~60 unused bits sitting here.
+type miniExpr struct {
+       miniNode
+       typ   *types.Type
+       init  Nodes       // TODO(rsc): Don't require every Node to have an init
+       opt   interface{} // TODO(rsc): Don't require every Node to have an opt?
+       flags bitset8
+}
+
+const (
+       miniExprHasCall = 1 << iota
+       miniExprImplicit
+       miniExprNonNil
+       miniExprTransient
+       miniExprBounded
+)
+
+func (n *miniExpr) Type() *types.Type     { return n.typ }
+func (n *miniExpr) SetType(x *types.Type) { n.typ = x }
+func (n *miniExpr) Opt() interface{}      { return n.opt }
+func (n *miniExpr) SetOpt(x interface{})  { n.opt = x }
+func (n *miniExpr) HasCall() bool         { return n.flags&miniExprHasCall != 0 }
+func (n *miniExpr) SetHasCall(b bool)     { n.flags.set(miniExprHasCall, b) }
+func (n *miniExpr) Implicit() bool        { return n.flags&miniExprImplicit != 0 }
+func (n *miniExpr) SetImplicit(b bool)    { n.flags.set(miniExprImplicit, b) }
+func (n *miniExpr) NonNil() bool          { return n.flags&miniExprNonNil != 0 }
+func (n *miniExpr) MarkNonNil()           { n.flags |= miniExprNonNil }
+func (n *miniExpr) Transient() bool       { return n.flags&miniExprTransient != 0 }
+func (n *miniExpr) SetTransient(b bool)   { n.flags.set(miniExprTransient, b) }
+func (n *miniExpr) Bounded() bool         { return n.flags&miniExprBounded != 0 }
+func (n *miniExpr) SetBounded(b bool)     { n.flags.set(miniExprBounded, b) }
+func (n *miniExpr) Init() Nodes           { return n.init }
+func (n *miniExpr) PtrInit() *Nodes       { return &n.init }
+func (n *miniExpr) SetInit(x Nodes)       { n.init = x }
index 24318d501f5f6ef7d6c2023df2c4387474a4b5bd..e749778030c97fa4573c8b8e2826741797e70e13 100644 (file)
@@ -1615,9 +1615,9 @@ func nodeDumpFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) {
                } else {
                        mode.Fprintf(s, "%v%j", n.Op(), n)
                }
-               if recur && n.Type() == nil && n.Name() != nil && n.Name().Param != nil && n.Name().Param.Ntype != nil {
+               if recur && n.Type() == nil && n.Name() != nil && n.Name().Ntype != nil {
                        indent(s)
-                       mode.Fprintf(s, "%v-ntype%v", n.Op(), n.Name().Param.Ntype)
+                       mode.Fprintf(s, "%v-ntype%v", n.Op(), n.Name().Ntype)
                }
 
        case OASOP:
@@ -1625,9 +1625,9 @@ func nodeDumpFmt(n Node, s fmt.State, flag FmtFlag, mode FmtMode) {
 
        case OTYPE:
                mode.Fprintf(s, "%v %v%j type=%v", n.Op(), n.Sym(), n, n.Type())
-               if recur && n.Type() == nil && n.Name() != nil && n.Name().Param != nil && n.Name().Param.Ntype != nil {
+               if recur && n.Type() == nil && n.Name() != nil && n.Name().Ntype != nil {
                        indent(s)
-                       mode.Fprintf(s, "%v-ntype%v", n.Op(), n.Name().Param.Ntype)
+                       mode.Fprintf(s, "%v-ntype%v", n.Op(), n.Name().Ntype)
                }
        }
 
index 608c2bed8116098e6f85158f308f06dde5c7d6c8..248fe232cb88d177a52c57d3b805d796c1123b12 100644 (file)
@@ -130,7 +130,6 @@ func (n *miniNode) SetType(*types.Type) { panic(n.no("SetType")) }
 func (n *miniNode) Func() *Func         { return nil }
 func (n *miniNode) SetFunc(*Func)       { panic(n.no("SetFunc")) }
 func (n *miniNode) Name() *Name         { return nil }
-func (n *miniNode) SetName(*Name)       { panic(n.no("SetName")) }
 func (n *miniNode) Sym() *types.Sym     { return nil }
 func (n *miniNode) SetSym(*types.Sym)   { panic(n.no("SetSym")) }
 func (n *miniNode) Offset() int64       { return types.BADWIDTH }
@@ -164,7 +163,6 @@ func (n *miniNode) SetIndexMapLValue(bool)    { panic(n.no("SetIndexMapLValue"))
 func (n *miniNode) ResetAux()                 { panic(n.no("ResetAux")) }
 func (n *miniNode) HasBreak() bool            { panic(n.no("HasBreak")) }
 func (n *miniNode) SetHasBreak(bool)          { panic(n.no("SetHasBreak")) }
-func (n *miniNode) HasVal() bool              { return false }
 func (n *miniNode) Val() constant.Value       { panic(n.no("Val")) }
 func (n *miniNode) SetVal(v constant.Value)   { panic(n.no("SetVal")) }
 func (n *miniNode) Int64Val() int64           { panic(n.no("Int64Val")) }
index 64d5d2a2ed56b733e85cbace9b91603c45eb91f4..d330745cfbb1873c9e4f59f9e12cc28d97bf1600 100644 (file)
@@ -15,29 +15,38 @@ import (
 
 // Name holds Node fields used only by named nodes (ONAME, OTYPE, some OLITERAL).
 type Name struct {
+       miniExpr
+       subOp      Op    // uint8
+       class      Class // uint8
+       flags      bitset16
+       pragma     PragmaFlag // int16
+       sym        *types.Sym
+       typ        *types.Type
+       fn         *Func
+       offset     int64
+       val        constant.Value
+       orig       Node
+       embedFiles *[]string // list of embedded files, for ONAME var
+
        PkgName *PkgName // real package for import . names
        // For a local variable (not param) or extern, the initializing assignment (OAS or OAS2).
        // For a closure var, the ONAME node of the outer captured variable
        Defn Node
        // The ODCLFUNC node (for a static function/method or a closure) in which
        // local variable or param is declared.
-       Curfn     Node
-       Param     *Param // additional fields for ONAME, OTYPE
-       Decldepth int32  // declaration loop depth, increased for every loop or label
+       Curfn Node
        // Unique number for ONAME nodes within a function. Function outputs
        // (results) are numbered starting at one, followed by function inputs
        // (parameters), and then local variables. Vargen is used to distinguish
        // local variables/params with the same name.
-       Vargen int32
-       flags  bitset16
-}
+       Vargen    int32
+       Decldepth int32 // declaration loop depth, increased for every loop or label
 
-type Param struct {
        Ntype    Node
-       Heapaddr Node // temp holding heap address of param
+       Heapaddr *Name // temp holding heap address of param
 
        // ONAME PAUTOHEAP
-       Stackcopy Node // the PPARAM/PPARAMOUT on-stack slot (moved func params only)
+       Stackcopy *Name // the PPARAM/PPARAMOUT on-stack slot (moved func params only)
 
        // ONAME closure linkage
        // Consider:
@@ -108,114 +117,88 @@ type Param struct {
        //
        // Because of the sharding of pieces of the node, x.Defn means x.Name.Defn
        // and x.Innermost/Outer means x.Name.Param.Innermost/Outer.
-       Innermost Node
-       Outer     Node
-
-       // OTYPE & ONAME //go:embed info,
-       // sharing storage to reduce gc.Param size.
-       // Extra is nil, or else *Extra is a *paramType or an *embedFileList.
-       Extra *interface{}
+       Innermost *Name
+       Outer     *Name
 }
 
 // NewNameAt returns a new ONAME Node associated with symbol s at position pos.
 // The caller is responsible for setting n.Name.Curfn.
-func NewNameAt(pos src.XPos, s *types.Sym) Node {
-       if s == nil {
-               base.Fatalf("newnamel nil")
+func NewNameAt(pos src.XPos, sym *types.Sym) *Name {
+       if sym == nil {
+               base.Fatalf("NewNameAt nil")
        }
+       return newNameAt(pos, sym)
+}
 
-       var x struct {
-               n node
-               m Name
-               p Param
-       }
-       n := &x.n
-       n.SetName(&x.m)
-       n.Name().Param = &x.p
-
-       n.SetOp(ONAME)
-       n.SetPos(pos)
-       n.SetOrig(n)
-
-       n.SetSym(s)
+// newNameAt is like NewNameAt but allows sym == nil.
+func newNameAt(pos src.XPos, sym *types.Sym) *Name {
+       n := new(Name)
+       n.op = ONAME
+       n.pos = pos
+       n.orig = n
+       n.sym = sym
        return n
 }
 
-type paramType struct {
-       flag  PragmaFlag
-       alias bool
+func (n *Name) String() string                { return fmt.Sprint(n) }
+func (n *Name) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *Name) RawCopy() Node                 { c := *n; return &c }
+func (n *Name) Name() *Name                   { return n }
+func (n *Name) Sym() *types.Sym               { return n.sym }
+func (n *Name) SetSym(x *types.Sym)           { n.sym = x }
+func (n *Name) Orig() Node                    { return n.orig }
+func (n *Name) SetOrig(x Node)                { n.orig = x }
+func (n *Name) SubOp() Op                     { return n.subOp }
+func (n *Name) SetSubOp(x Op)                 { n.subOp = x }
+func (n *Name) Class() Class                  { return n.class }
+func (n *Name) SetClass(x Class)              { n.class = x }
+func (n *Name) Func() *Func                   { return n.fn }
+func (n *Name) SetFunc(x *Func)               { n.fn = x }
+func (n *Name) Offset() int64                 { return n.offset }
+func (n *Name) SetOffset(x int64)             { n.offset = x }
+func (n *Name) Iota() int64                   { return n.offset }
+func (n *Name) SetIota(x int64)               { n.offset = x }
+
+func (n *Name) SetOp(op Op) {
+       switch op {
+       default:
+               panic(n.no("SetOp " + op.String()))
+       case OLITERAL, ONONAME, ONAME, OTYPE, OIOTA:
+               n.op = op
+       }
 }
 
 // Pragma returns the PragmaFlag for p, which must be for an OTYPE.
-func (p *Param) Pragma() PragmaFlag {
-       if p.Extra == nil {
-               return 0
-       }
-       return (*p.Extra).(*paramType).flag
-}
+func (n *Name) Pragma() PragmaFlag { return n.pragma }
 
 // SetPragma sets the PragmaFlag for p, which must be for an OTYPE.
-func (p *Param) SetPragma(flag PragmaFlag) {
-       if p.Extra == nil {
-               if flag == 0 {
-                       return
-               }
-               p.Extra = new(interface{})
-               *p.Extra = &paramType{flag: flag}
-               return
-       }
-       (*p.Extra).(*paramType).flag = flag
-}
+func (n *Name) SetPragma(flag PragmaFlag) { n.pragma = flag }
 
 // Alias reports whether p, which must be for an OTYPE, is a type alias.
-func (p *Param) Alias() bool {
-       if p.Extra == nil {
-               return false
-       }
-       t, ok := (*p.Extra).(*paramType)
-       if !ok {
-               return false
-       }
-       return t.alias
-}
+func (n *Name) Alias() bool { return n.flags&nameAlias != 0 }
 
 // SetAlias sets whether p, which must be for an OTYPE, is a type alias.
-func (p *Param) SetAlias(alias bool) {
-       if p.Extra == nil {
-               if !alias {
-                       return
-               }
-               p.Extra = new(interface{})
-               *p.Extra = &paramType{alias: alias}
-               return
-       }
-       (*p.Extra).(*paramType).alias = alias
-}
-
-type embedFileList []string
+func (n *Name) SetAlias(alias bool) { n.flags.set(nameAlias, alias) }
 
 // EmbedFiles returns the list of embedded files for p,
 // which must be for an ONAME var.
-func (p *Param) EmbedFiles() []string {
-       if p.Extra == nil {
+func (n *Name) EmbedFiles() []string {
+       if n.embedFiles == nil {
                return nil
        }
-       return *(*p.Extra).(*embedFileList)
+       return *n.embedFiles
 }
 
 // SetEmbedFiles sets the list of embedded files for p,
 // which must be for an ONAME var.
-func (p *Param) SetEmbedFiles(list []string) {
-       if p.Extra == nil {
-               if len(list) == 0 {
-                       return
-               }
-               f := embedFileList(list)
-               p.Extra = new(interface{})
-               *p.Extra = &f
+func (n *Name) SetEmbedFiles(list []string) {
+       if n.embedFiles == nil && list == nil {
                return
        }
-       *(*p.Extra).(*embedFileList) = list
+       if n.embedFiles == nil {
+               n.embedFiles = new([]string)
+       }
+       *n.embedFiles = list
 }
 
 const (
@@ -233,6 +216,8 @@ const (
        nameInlLocal              // PAUTO created by inliner, derived from callee local
        nameOpenDeferSlot         // if temporary var storing info for open-coded defers
        nameLibfuzzerExtraCounter // if PEXTERN should be assigned to __libfuzzer_extra_counters section
+       nameIsDDD                 // is function argument a ...
+       nameAlias                 // is type name an alias
 )
 
 func (n *Name) Captured() bool              { return n.flags&nameCaptured != 0 }
@@ -249,9 +234,10 @@ func (n *Name) InlFormal() bool             { return n.flags&nameInlFormal != 0
 func (n *Name) InlLocal() bool              { return n.flags&nameInlLocal != 0 }
 func (n *Name) OpenDeferSlot() bool         { return n.flags&nameOpenDeferSlot != 0 }
 func (n *Name) LibfuzzerExtraCounter() bool { return n.flags&nameLibfuzzerExtraCounter != 0 }
+func (n *Name) IsDDD() bool                 { return n.flags&nameIsDDD != 0 }
 
 func (n *Name) SetCaptured(b bool)              { n.flags.set(nameCaptured, b) }
-func (n *Name) SetReadonly(b bool)              { n.flags.set(nameReadonly, b) }
+func (n *Name) setReadonly(b bool)              { n.flags.set(nameReadonly, b) }
 func (n *Name) SetByval(b bool)                 { n.flags.set(nameByval, b) }
 func (n *Name) SetNeedzero(b bool)              { n.flags.set(nameNeedzero, b) }
 func (n *Name) SetAutoTemp(b bool)              { n.flags.set(nameAutoTemp, b) }
@@ -264,13 +250,14 @@ func (n *Name) SetInlFormal(b bool)             { n.flags.set(nameInlFormal, b)
 func (n *Name) SetInlLocal(b bool)              { n.flags.set(nameInlLocal, b) }
 func (n *Name) SetOpenDeferSlot(b bool)         { n.flags.set(nameOpenDeferSlot, b) }
 func (n *Name) SetLibfuzzerExtraCounter(b bool) { n.flags.set(nameLibfuzzerExtraCounter, b) }
+func (n *Name) SetIsDDD(b bool)                 { n.flags.set(nameIsDDD, b) }
 
 // MarkReadonly indicates that n is an ONAME with readonly contents.
-func (n *node) MarkReadonly() {
+func (n *Name) MarkReadonly() {
        if n.Op() != ONAME {
                base.Fatalf("Node.MarkReadonly %v", n.Op())
        }
-       n.Name().SetReadonly(true)
+       n.Name().setReadonly(true)
        // Mark the linksym as readonly immediately
        // so that the SSA backend can use this information.
        // It will be overridden later during dumpglobls.
@@ -278,31 +265,26 @@ func (n *node) MarkReadonly() {
 }
 
 // Val returns the constant.Value for the node.
-func (n *node) Val() constant.Value {
-       if !n.HasVal() {
+func (n *Name) Val() constant.Value {
+       if n.val == nil {
                return constant.MakeUnknown()
        }
-       return *n.e.(*constant.Value)
+       return n.val
 }
 
 // SetVal sets the constant.Value for the node,
 // which must not have been used with SetOpt.
-func (n *node) SetVal(v constant.Value) {
-       if n.hasOpt() {
-               base.Flag.LowerH = 1
-               Dump("have Opt", n)
-               base.Fatalf("have Opt")
-       }
-       if n.Op() == OLITERAL {
-               AssertValidTypeForConst(n.Type(), v)
+func (n *Name) SetVal(v constant.Value) {
+       if n.op != OLITERAL {
+               panic(n.no("SetVal"))
        }
-       n.setHasVal(true)
-       n.e = &v
+       AssertValidTypeForConst(n.Type(), v)
+       n.val = v
 }
 
 // Int64Val returns n as an int64.
 // n must be an integer or rune constant.
-func (n *node) Int64Val() int64 {
+func (n *Name) Int64Val() int64 {
        if !IsConst(n, constant.Int) {
                base.Fatalf("Int64Val(%v)", n)
        }
@@ -314,7 +296,7 @@ func (n *node) Int64Val() int64 {
 }
 
 // CanInt64 reports whether it is safe to call Int64Val() on n.
-func (n *node) CanInt64() bool {
+func (n *Name) CanInt64() bool {
        if !IsConst(n, constant.Int) {
                return false
        }
@@ -327,7 +309,7 @@ func (n *node) CanInt64() bool {
 
 // Uint64Val returns n as an uint64.
 // n must be an integer or rune constant.
-func (n *node) Uint64Val() uint64 {
+func (n *Name) Uint64Val() uint64 {
        if !IsConst(n, constant.Int) {
                base.Fatalf("Uint64Val(%v)", n)
        }
@@ -340,7 +322,7 @@ func (n *node) Uint64Val() uint64 {
 
 // BoolVal returns n as a bool.
 // n must be a boolean constant.
-func (n *node) BoolVal() bool {
+func (n *Name) BoolVal() bool {
        if !IsConst(n, constant.Bool) {
                base.Fatalf("BoolVal(%v)", n)
        }
@@ -349,7 +331,7 @@ func (n *node) BoolVal() bool {
 
 // StringVal returns the value of a literal string Node as a string.
 // n must be a string constant.
-func (n *node) StringVal() string {
+func (n *Name) StringVal() string {
        if !IsConst(n, constant.String) {
                base.Fatalf("StringVal(%v)", n)
        }
index 0023df97a80ef6d2d778093647bb68127e3a64e2..a6a24774b5c671a9d92583068c31669f7807f917 100644 (file)
@@ -59,7 +59,6 @@ type Node interface {
        Func() *Func
        SetFunc(x *Func)
        Name() *Name
-       SetName(x *Name)
        Sym() *types.Sym
        SetSym(x *types.Sym)
        Offset() int64
@@ -93,7 +92,6 @@ type Node interface {
        SetHasBreak(x bool)
        MarkReadonly()
        Val() constant.Value
-       HasVal() bool
        SetVal(v constant.Value)
        Int64Val() int64
        Uint64Val() uint64
@@ -149,11 +147,8 @@ type node struct {
        // func
        fn *Func
 
-       // ONAME, OTYPE, OPACK, OLABEL, some OLITERAL
-       name *Name
-
-       sym *types.Sym  // various
-       e   interface{} // Opt or Val, see methods below
+       sym *types.Sym // various
+       opt interface{}
 
        // Various. Usually an offset into a struct. For example:
        // - ONAME nodes that refer to local variables use it to identify their stack frame position.
@@ -185,8 +180,7 @@ func (n *node) Type() *types.Type     { return n.typ }
 func (n *node) SetType(x *types.Type) { n.typ = x }
 func (n *node) Func() *Func           { return n.fn }
 func (n *node) SetFunc(x *Func)       { n.fn = x }
-func (n *node) Name() *Name           { return n.name }
-func (n *node) SetName(x *Name)       { n.name = x }
+func (n *node) Name() *Name           { return nil }
 func (n *node) Sym() *types.Sym       { return n.sym }
 func (n *node) SetSym(x *types.Sym)   { n.sym = x }
 func (n *node) Pos() src.XPos         { return n.pos }
@@ -208,6 +202,14 @@ func (n *node) PtrList() *Nodes       { return &n.list }
 func (n *node) Rlist() Nodes          { return n.rlist }
 func (n *node) SetRlist(x Nodes)      { n.rlist = x }
 func (n *node) PtrRlist() *Nodes      { return &n.rlist }
+func (n *node) MarkReadonly()         { panic("node.MarkReadOnly") }
+func (n *node) Val() constant.Value   { panic("node.Val") }
+func (n *node) SetVal(constant.Value) { panic("node.SetVal") }
+func (n *node) Int64Val() int64       { panic("node.Int64Val") }
+func (n *node) CanInt64() bool        { return false }
+func (n *node) Uint64Val() uint64     { panic("node.Uint64Val") }
+func (n *node) BoolVal() bool         { panic("node.BoolVal") }
+func (n *node) StringVal() string     { panic("node.StringVal") }
 
 func (n *node) SetOp(op Op) {
        if !okForNod[op] {
@@ -305,8 +307,6 @@ const (
        _, nodeBounded   // bounds check unnecessary
        _, nodeHasCall   // expression contains a function call
        _, nodeLikely    // if statement condition likely
-       _, nodeHasVal    // node.E contains a Val
-       _, nodeHasOpt    // node.E contains an Opt
        _, nodeEmbedded  // ODCLFIELD embedded type
 )
 
@@ -326,8 +326,6 @@ func (n *node) Transient() bool { return n.flags&nodeTransient != 0 }
 func (n *node) Bounded() bool   { return n.flags&nodeBounded != 0 }
 func (n *node) HasCall() bool   { return n.flags&nodeHasCall != 0 }
 func (n *node) Likely() bool    { return n.flags&nodeLikely != 0 }
-func (n *node) HasVal() bool    { return n.flags&nodeHasVal != 0 }
-func (n *node) hasOpt() bool    { return n.flags&nodeHasOpt != 0 }
 func (n *node) Embedded() bool  { return n.flags&nodeEmbedded != 0 }
 
 func (n *node) SetClass(b Class)     { n.flags.set3(nodeClass, uint8(b)) }
@@ -344,8 +342,6 @@ func (n *node) SetColas(b bool)     { n.flags.set(nodeColas, b) }
 func (n *node) SetTransient(b bool) { n.flags.set(nodeTransient, b) }
 func (n *node) SetHasCall(b bool)   { n.flags.set(nodeHasCall, b) }
 func (n *node) SetLikely(b bool)    { n.flags.set(nodeLikely, b) }
-func (n *node) setHasVal(b bool)    { n.flags.set(nodeHasVal, b) }
-func (n *node) setHasOpt(b bool)    { n.flags.set(nodeHasOpt, b) }
 func (n *node) SetEmbedded(b bool)  { n.flags.set(nodeEmbedded, b) }
 
 // MarkNonNil marks a pointer n as being guaranteed non-nil,
@@ -380,29 +376,13 @@ func (n *node) SetBounded(b bool) {
 
 // Opt returns the optimizer data for the node.
 func (n *node) Opt() interface{} {
-       if !n.hasOpt() {
-               return nil
-       }
-       return n.e
+       return n.opt
 }
 
 // SetOpt sets the optimizer data for the node, which must not have been used with SetVal.
 // SetOpt(nil) is ignored for Vals to simplify call sites that are clearing Opts.
 func (n *node) SetOpt(x interface{}) {
-       if x == nil {
-               if n.hasOpt() {
-                       n.setHasOpt(false)
-                       n.e = nil
-               }
-               return
-       }
-       if n.HasVal() {
-               base.Flag.LowerH = 1
-               Dump("have Val", n)
-               base.Fatalf("have Val")
-       }
-       n.setHasOpt(true)
-       n.e = x
+       n.opt = x
 }
 
 func (n *node) Iota() int64 {
@@ -1344,6 +1324,10 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node {
                return NewEmptyStmt(pos)
        case OBREAK, OCONTINUE, OFALL, OGOTO:
                return NewBranchStmt(pos, op, nil)
+       case OLITERAL, OTYPE, OIOTA:
+               n := newNameAt(pos, nil)
+               n.SetOp(op)
+               return n
        case OLABEL:
                return NewLabelStmt(pos, nil)
        default:
@@ -1428,13 +1412,11 @@ var okForNod = [OEND]bool{
        OINDEXMAP:      true,
        OINLCALL:       true,
        OINLMARK:       true,
-       OIOTA:          true,
        OITAB:          true,
        OKEY:           true,
        OLABEL:         true,
        OLE:            true,
        OLEN:           true,
-       OLITERAL:       true,
        OLSH:           true,
        OLT:            true,
        OMAKE:          true,
@@ -1446,13 +1428,11 @@ var okForNod = [OEND]bool{
        OMETHEXPR:      true,
        OMOD:           true,
        OMUL:           true,
-       ONAME:          true,
        ONE:            true,
        ONEG:           true,
        ONEW:           true,
        ONEWOBJ:        true,
        ONIL:           true,
-       ONONAME:        true,
        ONOT:           true,
        OOFFSETOF:      true,
        OOR:            true,
@@ -1499,7 +1479,7 @@ var okForNod = [OEND]bool{
        OTINTER:        true,
        OTMAP:          true,
        OTSTRUCT:       true,
-       OTYPE:          true,
+       OTYPE:          true, // TODO: Remove once setTypeNode is gone.
        OTYPESW:        true,
        OVARDEF:        true,
        OVARKILL:       true,
index a025cb59868ef31e44dbee56eb498161fcc23174..8a0b078b9b9f65547245242e7b6d11aa63062cb8 100644 (file)
@@ -21,9 +21,8 @@ func TestSizeof(t *testing.T) {
                _64bit uintptr     // size on 64bit platforms
        }{
                {Func{}, 152, 280},
-               {Name{}, 36, 64},
-               {Param{}, 44, 88},
-               {node{}, 88, 152},
+               {Name{}, 132, 232},
+               {node{}, 84, 144},
        }
 
        for _, tt := range tests {