]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: move some ONAME-specific flags from Node to Name
authorMatthew Dempsky <mdempsky@google.com>
Sat, 12 Oct 2019 23:21:55 +0000 (16:21 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Mon, 14 Oct 2019 18:57:11 +0000 (18:57 +0000)
The IsClosureVar, IsOutputParamHeapAddr, Assigned, Addrtaken,
InlFormal, and InlLocal flags are only interesting for ONAME nodes, so
it's better to set these flags on Name.flags instead of Node.flags.

Two caveats though:

1. Previously, we would set Assigned and Addrtaken on the entire
expression tree involved in an assignment or addressing operation.
However, the rest of the compiler only actually cares about knowing
whether the underlying ONAME (if any) was assigned/addressed.

2. This actually requires bumping Name.flags from bitset8 to bitset16,
whereas it doesn't allow shrinking Node.flags any. However, Name has
some trailing padding bytes, so expanding Name.flags doesn't cost any
memory.

Passes toolstash-check.

Change-Id: I7775d713566a38d5b9723360b1659b79391744c2
Reviewed-on: https://go-review.googlesource.com/c/go/+/200898
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
13 files changed:
src/cmd/compile/internal/gc/closure.go
src/cmd/compile/internal/gc/dcl.go
src/cmd/compile/internal/gc/esc.go
src/cmd/compile/internal/gc/escape.go
src/cmd/compile/internal/gc/fmt.go
src/cmd/compile/internal/gc/inl.go
src/cmd/compile/internal/gc/order.go
src/cmd/compile/internal/gc/pgen.go
src/cmd/compile/internal/gc/plive.go
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/gc/syntax.go
src/cmd/compile/internal/gc/typecheck.go
src/cmd/compile/internal/gc/walk.go

index 6080777e8ecda8286b0b4c435af10e064ee07eb9..055ddbae331dcf61256ad34828e7f4e9287b27eb 100644 (file)
@@ -101,7 +101,7 @@ func typecheckclosure(clo *Node, top int) {
                        // Ignore assignments to the variable in straightline code
                        // preceding the first capturing by a closure.
                        if n.Name.Decldepth == decldepth {
-                               n.SetAssigned(false)
+                               n.Name.SetAssigned(false)
                        }
                }
        }
@@ -192,10 +192,10 @@ func capturevars(xfunc *Node) {
                outermost := v.Name.Defn
 
                // out parameters will be assigned to implicitly upon return.
-               if outermost.Class() != PPARAMOUT && !outermost.Addrtaken() && !outermost.Assigned() && v.Type.Width <= 128 {
+               if outermost.Class() != PPARAMOUT && !outermost.Name.Addrtaken() && !outermost.Name.Assigned() && v.Type.Width <= 128 {
                        v.Name.SetByval(true)
                } else {
-                       outermost.SetAddrtaken(true)
+                       outermost.Name.SetAddrtaken(true)
                        outer = nod(OADDR, outer, nil)
                }
 
@@ -208,7 +208,7 @@ func capturevars(xfunc *Node) {
                        if v.Name.Byval() {
                                how = "value"
                        }
-                       Warnl(v.Pos, "%v capturing by %s: %v (addr=%v assign=%v width=%d)", name, how, v.Sym, outermost.Addrtaken(), outermost.Assigned(), int32(v.Type.Width))
+                       Warnl(v.Pos, "%v capturing by %s: %v (addr=%v assign=%v width=%d)", name, how, v.Sym, outermost.Name.Addrtaken(), outermost.Name.Assigned(), int32(v.Type.Width))
                }
 
                outer = typecheck(outer, ctxExpr)
index 8168f739f4439b13855f7826d011964973a9cfbc..54c6a24df54d5b7cbc0a34d9e5baa16d0b85d1b8 100644 (file)
@@ -278,7 +278,7 @@ func oldname(s *types.Sym) *Node {
                        // Do not have a closure var for the active closure yet; make one.
                        c = newname(s)
                        c.SetClass(PAUTOHEAP)
-                       c.SetIsClosureVar(true)
+                       c.Name.SetIsClosureVar(true)
                        c.SetIsDDD(n.IsDDD())
                        c.Name.Defn = n
 
index 92f229b97f0b0a1407bc1d3db762412c29e4d10a..ee2a27cb7ee1073480767bf9d302458048cf6f6a 100644 (file)
@@ -201,7 +201,7 @@ func addrescapes(n *Node) {
                }
 
                // If a closure reference escapes, mark the outer variable as escaping.
-               if n.IsClosureVar() {
+               if n.Name.IsClosureVar() {
                        addrescapes(n.Name.Defn)
                        break
                }
@@ -293,7 +293,7 @@ func moveToHeap(n *Node) {
                        // Thus, we need the pointer to the heap copy always available so the
                        // post-deferreturn code can copy the return value back to the stack.
                        // See issue 16095.
-                       heapaddr.SetIsOutputParamHeapAddr(true)
+                       heapaddr.Name.SetIsOutputParamHeapAddr(true)
                }
                n.Name.Param.Stackcopy = stackcopy
 
index 3d41c83627858155ce9205ae6a0c0c48900d6efb..b855f4a1748e53e5dc3593b7bfc5ddde71fc4ed1 100644 (file)
@@ -995,9 +995,9 @@ func (e *Escape) later(k EscHole) EscHole {
 // canonicalNode returns the canonical *Node that n logically
 // represents.
 func canonicalNode(n *Node) *Node {
-       if n != nil && n.IsClosureVar() {
+       if n != nil && n.Op == ONAME && n.Name.IsClosureVar() {
                n = n.Name.Defn
-               if n.IsClosureVar() {
+               if n.Name.IsClosureVar() {
                        Fatalf("still closure var")
                }
        }
index 877bbe44692ba6a27d0bac7cb5dbf59ae7fe65b4..fd6b9ce53cc449782631a1be74cea17d82ca9fcf 100644 (file)
@@ -483,12 +483,13 @@ func (n *Node) jconv(s fmt.State, flag FmtFlag) {
                fmt.Fprintf(s, " embedded")
        }
 
-       if n.Addrtaken() {
-               fmt.Fprint(s, " addrtaken")
-       }
-
-       if n.Assigned() {
-               fmt.Fprint(s, " assigned")
+       if n.Op == ONAME {
+               if n.Name.Addrtaken() {
+                       fmt.Fprint(s, " addrtaken")
+               }
+               if n.Name.Assigned() {
+                       fmt.Fprint(s, " assigned")
+               }
        }
        if n.Bounded() {
                fmt.Fprint(s, " bounded")
index 4a376305bb3091d8480f1548ce402abaae27749d..9b2ecc073b720c904504b32e412a5b1ad1d3e0d1 100644 (file)
@@ -655,7 +655,7 @@ func inlnode(n *Node, maxCost int32) *Node {
                                        // NB: this check is necessary to prevent indirect re-assignment of the variable
                                        // having the address taken after the invocation or only used for reads is actually fine
                                        // but we have no easy way to distinguish the safe cases
-                                       if d.Left.Addrtaken() {
+                                       if d.Left.Name.Addrtaken() {
                                                if Debug['m'] > 1 {
                                                        fmt.Printf("%v: cannot inline escaping closure variable %v\n", n.Line(), n.Left)
                                                }
@@ -919,9 +919,9 @@ func mkinlcall(n, fn *Node, maxCost int32) *Node {
                if genDwarfInline > 0 {
                        inlf := inlvars[ln]
                        if ln.Class() == PPARAM {
-                               inlf.SetInlFormal(true)
+                               inlf.Name.SetInlFormal(true)
                        } else {
-                               inlf.SetInlLocal(true)
+                               inlf.Name.SetInlLocal(true)
                        }
                        inlf.Pos = ln.Pos
                        inlfvars = append(inlfvars, inlf)
@@ -947,7 +947,7 @@ func mkinlcall(n, fn *Node, maxCost int32) *Node {
                        // was manufactured by the inliner (e.g. "~R2"); such vars
                        // were not part of the original callee.
                        if !strings.HasPrefix(m.Sym.Name, "~R") {
-                               m.SetInlFormal(true)
+                               m.Name.SetInlFormal(true)
                                m.Pos = mpos
                                inlfvars = append(inlfvars, m)
                        }
@@ -1125,7 +1125,7 @@ func inlvar(var_ *Node) *Node {
        n.SetClass(PAUTO)
        n.Name.SetUsed(true)
        n.Name.Curfn = Curfn // the calling function, not the called one
-       n.SetAddrtaken(var_.Addrtaken())
+       n.Name.SetAddrtaken(var_.Name.Addrtaken())
 
        Curfn.Func.Dcl = append(Curfn.Func.Dcl, n)
        return n
index 939f3df93abba0d4517aaadb5896ed27f4c144c0..6822be413783e82d5745a53ffbdccb2c4b02981d 100644 (file)
@@ -298,7 +298,7 @@ func (o *Order) cleanTempNoPop(mark ordermarker) []*Node {
                n := o.temp[i]
                if n.Name.Keepalive() {
                        n.Name.SetKeepalive(false)
-                       n.SetAddrtaken(true) // ensure SSA keeps the n variable
+                       n.Name.SetAddrtaken(true) // ensure SSA keeps the n variable
                        live := nod(OVARLIVE, n, nil)
                        live = typecheck(live, ctxStmt)
                        out = append(out, live)
index b1f9bc9d55adb3e86e052ec96ad8b44d49b82f98..ec25277a2bf391e84093c36b8ccab57d3502eac1 100644 (file)
@@ -262,7 +262,7 @@ func compile(fn *Node) {
        for _, n := range fn.Func.Dcl {
                switch n.Class() {
                case PPARAM, PPARAMOUT, PAUTO:
-                       if livenessShouldTrack(n) && n.Addrtaken() {
+                       if livenessShouldTrack(n) && n.Name.Addrtaken() {
                                dtypesym(n.Type)
                                // Also make sure we allocate a linker symbol
                                // for the stack object data, for the same reason.
@@ -498,9 +498,9 @@ func createSimpleVar(n *Node) *dwarf.Var {
        typename := dwarf.InfoPrefix + typesymname(n.Type)
        inlIndex := 0
        if genDwarfInline > 1 {
-               if n.InlFormal() || n.InlLocal() {
+               if n.Name.InlFormal() || n.Name.InlLocal() {
                        inlIndex = posInlIndex(n.Pos) + 1
-                       if n.InlFormal() {
+                       if n.Name.InlFormal() {
                                abbrev = dwarf.DW_ABRV_PARAM
                        }
                }
@@ -509,7 +509,7 @@ func createSimpleVar(n *Node) *dwarf.Var {
        return &dwarf.Var{
                Name:          n.Sym.Name,
                IsReturnValue: n.Class() == PPARAMOUT,
-               IsInlFormal:   n.InlFormal(),
+               IsInlFormal:   n.Name.InlFormal(),
                Abbrev:        abbrev,
                StackOffset:   int32(offs),
                Type:          Ctxt.Lookup(typename),
@@ -619,9 +619,9 @@ func createDwarfVars(fnsym *obj.LSym, fn *Func, apDecls []*Node) ([]*Node, []*dw
                }
                inlIndex := 0
                if genDwarfInline > 1 {
-                       if n.InlFormal() || n.InlLocal() {
+                       if n.Name.InlFormal() || n.Name.InlLocal() {
                                inlIndex = posInlIndex(n.Pos) + 1
-                               if n.InlFormal() {
+                               if n.Name.InlFormal() {
                                        abbrev = dwarf.DW_ABRV_PARAM_LOCLIST
                                }
                        }
@@ -707,9 +707,9 @@ func createComplexVar(fn *Func, varID ssa.VarID) *dwarf.Var {
        typename := dwarf.InfoPrefix + gotype.Name[len("type."):]
        inlIndex := 0
        if genDwarfInline > 1 {
-               if n.InlFormal() || n.InlLocal() {
+               if n.Name.InlFormal() || n.Name.InlLocal() {
                        inlIndex = posInlIndex(n.Pos) + 1
-                       if n.InlFormal() {
+                       if n.Name.InlFormal() {
                                abbrev = dwarf.DW_ABRV_PARAM_LOCLIST
                        }
                }
@@ -718,7 +718,7 @@ func createComplexVar(fn *Func, varID ssa.VarID) *dwarf.Var {
        dvar := &dwarf.Var{
                Name:          n.Sym.Name,
                IsReturnValue: n.Class() == PPARAMOUT,
-               IsInlFormal:   n.InlFormal(),
+               IsInlFormal:   n.Name.InlFormal(),
                Abbrev:        abbrev,
                Type:          Ctxt.Lookup(typename),
                // The stack offset is used as a sorting key, so for decomposed
index 8809a644d5a4713f4a585c84b260160c7079d30b..1745b92e6b3f1f2d18014808fcaeca5075d883f6 100644 (file)
@@ -908,7 +908,7 @@ func (lv *Liveness) epilogue() {
        if lv.fn.Func.HasDefer() {
                for i, n := range lv.vars {
                        if n.Class() == PPARAMOUT {
-                               if n.IsOutputParamHeapAddr() {
+                               if n.Name.IsOutputParamHeapAddr() {
                                        // Just to be paranoid.  Heap addresses are PAUTOs.
                                        Fatalf("variable %v both output param and heap output param", n)
                                }
@@ -920,7 +920,7 @@ func (lv *Liveness) epilogue() {
                                // Note: zeroing is handled by zeroResults in walk.go.
                                livedefer.Set(int32(i))
                        }
-                       if n.IsOutputParamHeapAddr() {
+                       if n.Name.IsOutputParamHeapAddr() {
                                // This variable will be overwritten early in the function
                                // prologue (from the result of a mallocgc) but we need to
                                // zero it in case that malloc causes a stack scan.
index be09fc5f83e89d348dc3a381e5d7fb2e0b1beba8..c833d8eff2cefc32ccb133d7acadd366c787af60 100644 (file)
@@ -1264,7 +1264,7 @@ func (s *state) stmt(n *Node) {
 
        case OVARLIVE:
                // Insert a varlive op to record that a variable is still live.
-               if !n.Left.Addrtaken() {
+               if !n.Left.Name.Addrtaken() {
                        s.Fatalf("VARLIVE variable %v must have Addrtaken set", n.Left)
                }
                switch n.Left.Class() {
@@ -4090,7 +4090,7 @@ func (s *state) canSSA(n *Node) bool {
        if n.Op != ONAME {
                return false
        }
-       if n.Addrtaken() {
+       if n.Name.Addrtaken() {
                return false
        }
        if n.isParamHeapCopy() {
@@ -5257,7 +5257,7 @@ func (s byXoffset) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
 func emitStackObjects(e *ssafn, pp *Progs) {
        var vars []*Node
        for _, n := range e.curfn.Func.Dcl {
-               if livenessShouldTrack(n) && n.Addrtaken() {
+               if livenessShouldTrack(n) && n.Name.Addrtaken() {
                        vars = append(vars, n)
                }
        }
@@ -6015,7 +6015,7 @@ func (e *ssafn) SplitString(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) {
        n := name.N.(*Node)
        ptrType := types.NewPtr(types.Types[TUINT8])
        lenType := types.Types[TINT]
-       if n.Class() == PAUTO && !n.Addrtaken() {
+       if n.Class() == PAUTO && !n.Name.Addrtaken() {
                // Split this string up into two separate variables.
                p := e.splitSlot(&name, ".ptr", 0, ptrType)
                l := e.splitSlot(&name, ".len", ptrType.Size(), lenType)
@@ -6029,7 +6029,7 @@ func (e *ssafn) SplitInterface(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot
        n := name.N.(*Node)
        u := types.Types[TUINTPTR]
        t := types.NewPtr(types.Types[TUINT8])
-       if n.Class() == PAUTO && !n.Addrtaken() {
+       if n.Class() == PAUTO && !n.Name.Addrtaken() {
                // Split this interface up into two separate variables.
                f := ".itab"
                if n.Type.IsEmptyInterface() {
@@ -6047,7 +6047,7 @@ func (e *ssafn) SplitSlice(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot, ss
        n := name.N.(*Node)
        ptrType := types.NewPtr(name.Type.Elem())
        lenType := types.Types[TINT]
-       if n.Class() == PAUTO && !n.Addrtaken() {
+       if n.Class() == PAUTO && !n.Name.Addrtaken() {
                // Split this slice up into three separate variables.
                p := e.splitSlot(&name, ".ptr", 0, ptrType)
                l := e.splitSlot(&name, ".len", ptrType.Size(), lenType)
@@ -6069,7 +6069,7 @@ func (e *ssafn) SplitComplex(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot)
        } else {
                t = types.Types[TFLOAT32]
        }
-       if n.Class() == PAUTO && !n.Addrtaken() {
+       if n.Class() == PAUTO && !n.Name.Addrtaken() {
                // Split this complex up into two separate variables.
                r := e.splitSlot(&name, ".real", 0, t)
                i := e.splitSlot(&name, ".imag", t.Size(), t)
@@ -6087,7 +6087,7 @@ func (e *ssafn) SplitInt64(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) {
        } else {
                t = types.Types[TUINT32]
        }
-       if n.Class() == PAUTO && !n.Addrtaken() {
+       if n.Class() == PAUTO && !n.Name.Addrtaken() {
                // Split this int64 up into two separate variables.
                if thearch.LinkArch.ByteOrder == binary.BigEndian {
                        return e.splitSlot(&name, ".hi", 0, t), e.splitSlot(&name, ".lo", t.Size(), types.Types[TUINT32])
@@ -6109,7 +6109,7 @@ func (e *ssafn) SplitStruct(name ssa.LocalSlot, i int) ssa.LocalSlot {
        for f := 0; f < i; f++ {
                offset += st.FieldType(f).Size()
        }
-       if n.Class() == PAUTO && !n.Addrtaken() {
+       if n.Class() == PAUTO && !n.Name.Addrtaken() {
                // Note: the _ field may appear several times.  But
                // have no fear, identically-named but distinct Autos are
                // ok, albeit maybe confusing for a debugger.
@@ -6125,7 +6125,7 @@ func (e *ssafn) SplitArray(name ssa.LocalSlot) ssa.LocalSlot {
                e.Fatalf(n.Pos, "bad array size")
        }
        et := at.Elem()
-       if n.Class() == PAUTO && !n.Addrtaken() {
+       if n.Class() == PAUTO && !n.Name.Addrtaken() {
                return e.splitSlot(&name, "[0]", 0, et)
        }
        return ssa.LocalSlot{N: n, Type: et, Off: name.Off}
index 69d8a5590b828b50fd5acc4f377d738e14badd28..98903100fc0ccbe72426ec13a573218588d85521 100644 (file)
@@ -141,11 +141,7 @@ const (
        nodeInitorder, _                   // tracks state during init1; two bits
        _, _                               // second nodeInitorder bit
        _, nodeHasBreak
-       _, nodeIsClosureVar
-       _, nodeIsOutputParamHeapAddr
-       _, nodeNoInline  // used internally by inliner to indicate that a function call should not be inlined; set for OCALLFUNC and OCALLMETH only
-       _, nodeAssigned  // is the variable ever assigned to
-       _, nodeAddrtaken // address taken, even if not moved to heap
+       _, nodeNoInline // used internally by inliner to indicate that a function call should not be inlined; set for OCALLFUNC and OCALLMETH only
        _, nodeImplicit
        _, nodeIsDDD     // is the argument variadic
        _, nodeDiag      // already printed error about this
@@ -158,8 +154,6 @@ const (
        _, nodeHasVal    // node.E contains a Val
        _, nodeHasOpt    // node.E contains an Opt
        _, nodeEmbedded  // ODCLFIELD embedded type
-       _, nodeInlFormal // OPAUTO created by inliner, derived from callee formal
-       _, nodeInlLocal  // OPAUTO created by inliner, derived from callee local
 )
 
 func (n *Node) Class() Class     { return Class(n.flags.get3(nodeClass)) }
@@ -167,52 +161,40 @@ func (n *Node) Walkdef() uint8   { return n.flags.get2(nodeWalkdef) }
 func (n *Node) Typecheck() uint8 { return n.flags.get2(nodeTypecheck) }
 func (n *Node) Initorder() uint8 { return n.flags.get2(nodeInitorder) }
 
-func (n *Node) HasBreak() bool              { return n.flags&nodeHasBreak != 0 }
-func (n *Node) IsClosureVar() bool          { return n.flags&nodeIsClosureVar != 0 }
-func (n *Node) NoInline() bool              { return n.flags&nodeNoInline != 0 }
-func (n *Node) IsOutputParamHeapAddr() bool { return n.flags&nodeIsOutputParamHeapAddr != 0 }
-func (n *Node) Assigned() bool              { return n.flags&nodeAssigned != 0 }
-func (n *Node) Addrtaken() bool             { return n.flags&nodeAddrtaken != 0 }
-func (n *Node) Implicit() bool              { return n.flags&nodeImplicit != 0 }
-func (n *Node) IsDDD() bool                 { return n.flags&nodeIsDDD != 0 }
-func (n *Node) Diag() bool                  { return n.flags&nodeDiag != 0 }
-func (n *Node) Colas() bool                 { return n.flags&nodeColas != 0 }
-func (n *Node) NonNil() bool                { return n.flags&nodeNonNil != 0 }
-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) InlFormal() bool             { return n.flags&nodeInlFormal != 0 }
-func (n *Node) InlLocal() bool              { return n.flags&nodeInlLocal != 0 }
+func (n *Node) HasBreak() bool  { return n.flags&nodeHasBreak != 0 }
+func (n *Node) NoInline() bool  { return n.flags&nodeNoInline != 0 }
+func (n *Node) Implicit() bool  { return n.flags&nodeImplicit != 0 }
+func (n *Node) IsDDD() bool     { return n.flags&nodeIsDDD != 0 }
+func (n *Node) Diag() bool      { return n.flags&nodeDiag != 0 }
+func (n *Node) Colas() bool     { return n.flags&nodeColas != 0 }
+func (n *Node) NonNil() bool    { return n.flags&nodeNonNil != 0 }
+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)) }
 func (n *Node) SetWalkdef(b uint8)   { n.flags.set2(nodeWalkdef, b) }
 func (n *Node) SetTypecheck(b uint8) { n.flags.set2(nodeTypecheck, b) }
 func (n *Node) SetInitorder(b uint8) { n.flags.set2(nodeInitorder, b) }
 
-func (n *Node) SetHasBreak(b bool)              { n.flags.set(nodeHasBreak, b) }
-func (n *Node) SetIsClosureVar(b bool)          { n.flags.set(nodeIsClosureVar, b) }
-func (n *Node) SetNoInline(b bool)              { n.flags.set(nodeNoInline, b) }
-func (n *Node) SetIsOutputParamHeapAddr(b bool) { n.flags.set(nodeIsOutputParamHeapAddr, b) }
-func (n *Node) SetAssigned(b bool)              { n.flags.set(nodeAssigned, b) }
-func (n *Node) SetAddrtaken(b bool)             { n.flags.set(nodeAddrtaken, b) }
-func (n *Node) SetImplicit(b bool)              { n.flags.set(nodeImplicit, b) }
-func (n *Node) SetIsDDD(b bool)                 { n.flags.set(nodeIsDDD, b) }
-func (n *Node) SetDiag(b bool)                  { n.flags.set(nodeDiag, b) }
-func (n *Node) SetColas(b bool)                 { n.flags.set(nodeColas, b) }
-func (n *Node) SetNonNil(b bool)                { n.flags.set(nodeNonNil, b) }
-func (n *Node) SetTransient(b bool)             { n.flags.set(nodeTransient, b) }
-func (n *Node) SetBounded(b bool)               { n.flags.set(nodeBounded, 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) }
-func (n *Node) SetInlFormal(b bool)             { n.flags.set(nodeInlFormal, b) }
-func (n *Node) SetInlLocal(b bool)              { n.flags.set(nodeInlLocal, b) }
+func (n *Node) SetHasBreak(b bool)  { n.flags.set(nodeHasBreak, b) }
+func (n *Node) SetNoInline(b bool)  { n.flags.set(nodeNoInline, b) }
+func (n *Node) SetImplicit(b bool)  { n.flags.set(nodeImplicit, b) }
+func (n *Node) SetIsDDD(b bool)     { n.flags.set(nodeIsDDD, b) }
+func (n *Node) SetDiag(b bool)      { n.flags.set(nodeDiag, b) }
+func (n *Node) SetColas(b bool)     { n.flags.set(nodeColas, b) }
+func (n *Node) SetNonNil(b bool)    { n.flags.set(nodeNonNil, b) }
+func (n *Node) SetTransient(b bool) { n.flags.set(nodeTransient, b) }
+func (n *Node) SetBounded(b bool)   { n.flags.set(nodeBounded, 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) }
 
 // Val returns the Val for the node.
 func (n *Node) Val() Val {
@@ -296,34 +278,52 @@ type Name struct {
        Param     *Param     // additional fields for ONAME, OTYPE
        Decldepth int32      // declaration loop depth, increased for every loop or label
        Vargen    int32      // unique name for ONAME within a function.  Function outputs are numbered starting at one.
-       flags     bitset8
+       flags     bitset16
 }
 
 const (
        nameCaptured = 1 << iota // is the variable captured by a closure
        nameReadonly
-       nameByval     // is the variable captured by value or by reference
-       nameNeedzero  // if it contains pointers, needs to be zeroed on function entry
-       nameKeepalive // mark value live across unknown assembly call
-       nameAutoTemp  // is the variable a temporary (implies no dwarf info. reset if escapes to heap)
-       nameUsed      // for variable declared and not used error
+       nameByval                 // is the variable captured by value or by reference
+       nameNeedzero              // if it contains pointers, needs to be zeroed on function entry
+       nameKeepalive             // mark value live across unknown assembly call
+       nameAutoTemp              // is the variable a temporary (implies no dwarf info. reset if escapes to heap)
+       nameUsed                  // for variable declared and not used error
+       nameIsClosureVar          // PAUTOHEAP closure pseudo-variable; original at n.Name.Defn
+       nameIsOutputParamHeapAddr // pointer to a result parameter's heap copy
+       nameAssigned              // is the variable ever assigned to
+       nameAddrtaken             // address taken, even if not moved to heap
+       nameInlFormal             // OPAUTO created by inliner, derived from callee formal
+       nameInlLocal              // OPAUTO created by inliner, derived from callee local
 )
 
-func (n *Name) Captured() bool  { return n.flags&nameCaptured != 0 }
-func (n *Name) Readonly() bool  { return n.flags&nameReadonly != 0 }
-func (n *Name) Byval() bool     { return n.flags&nameByval != 0 }
-func (n *Name) Needzero() bool  { return n.flags&nameNeedzero != 0 }
-func (n *Name) Keepalive() bool { return n.flags&nameKeepalive != 0 }
-func (n *Name) AutoTemp() bool  { return n.flags&nameAutoTemp != 0 }
-func (n *Name) Used() bool      { return n.flags&nameUsed != 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) SetByval(b bool)     { n.flags.set(nameByval, b) }
-func (n *Name) SetNeedzero(b bool)  { n.flags.set(nameNeedzero, b) }
-func (n *Name) SetKeepalive(b bool) { n.flags.set(nameKeepalive, b) }
-func (n *Name) SetAutoTemp(b bool)  { n.flags.set(nameAutoTemp, b) }
-func (n *Name) SetUsed(b bool)      { n.flags.set(nameUsed, b) }
+func (n *Name) Captured() bool              { return n.flags&nameCaptured != 0 }
+func (n *Name) Readonly() bool              { return n.flags&nameReadonly != 0 }
+func (n *Name) Byval() bool                 { return n.flags&nameByval != 0 }
+func (n *Name) Needzero() bool              { return n.flags&nameNeedzero != 0 }
+func (n *Name) Keepalive() bool             { return n.flags&nameKeepalive != 0 }
+func (n *Name) AutoTemp() bool              { return n.flags&nameAutoTemp != 0 }
+func (n *Name) Used() bool                  { return n.flags&nameUsed != 0 }
+func (n *Name) IsClosureVar() bool          { return n.flags&nameIsClosureVar != 0 }
+func (n *Name) IsOutputParamHeapAddr() bool { return n.flags&nameIsOutputParamHeapAddr != 0 }
+func (n *Name) Assigned() bool              { return n.flags&nameAssigned != 0 }
+func (n *Name) Addrtaken() bool             { return n.flags&nameAddrtaken != 0 }
+func (n *Name) InlFormal() bool             { return n.flags&nameInlFormal != 0 }
+func (n *Name) InlLocal() bool              { return n.flags&nameInlLocal != 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) SetByval(b bool)                 { n.flags.set(nameByval, b) }
+func (n *Name) SetNeedzero(b bool)              { n.flags.set(nameNeedzero, b) }
+func (n *Name) SetKeepalive(b bool)             { n.flags.set(nameKeepalive, b) }
+func (n *Name) SetAutoTemp(b bool)              { n.flags.set(nameAutoTemp, b) }
+func (n *Name) SetUsed(b bool)                  { n.flags.set(nameUsed, b) }
+func (n *Name) SetIsClosureVar(b bool)          { n.flags.set(nameIsClosureVar, b) }
+func (n *Name) SetIsOutputParamHeapAddr(b bool) { n.flags.set(nameIsOutputParamHeapAddr, b) }
+func (n *Name) SetAssigned(b bool)              { n.flags.set(nameAssigned, b) }
+func (n *Name) SetAddrtaken(b bool)             { n.flags.set(nameAddrtaken, b) }
+func (n *Name) SetInlFormal(b bool)             { n.flags.set(nameInlFormal, b) }
+func (n *Name) SetInlLocal(b bool)              { n.flags.set(nameInlLocal, b) }
 
 type Param struct {
        Ntype    *Node
index d5483c9ce51f5fe371bdb60944f95f69cb00e992..6067454a3c328292001ee8cdb50572726fe51319 100644 (file)
@@ -828,20 +828,17 @@ func typecheck1(n *Node, top int) (res *Node) {
                default:
                        checklvalue(n.Left, "take the address of")
                        r := outervalue(n.Left)
-                       if r.Orig != r && r.Op == ONAME {
-                               Fatalf("found non-orig name node %v", r) // TODO(mdempsky): What does this mean?
-                       }
-                       for l := n.Left; ; l = l.Left {
-                               l.SetAddrtaken(true)
-                               if l.IsClosureVar() && !capturevarscomplete {
+                       if r.Op == ONAME {
+                               if r.Orig != r {
+                                       Fatalf("found non-orig name node %v", r) // TODO(mdempsky): What does this mean?
+                               }
+                               r.Name.SetAddrtaken(true)
+                               if r.Name.IsClosureVar() && !capturevarscomplete {
                                        // Mark the original variable as Addrtaken so that capturevars
                                        // knows not to pass it by value.
                                        // But if the capturevars phase is complete, don't touch it,
                                        // in case l.Name's containing function has not yet been compiled.
-                                       l.Name.Defn.SetAddrtaken(true)
-                               }
-                               if l == r {
-                                       break
+                                       r.Name.Defn.Name.SetAddrtaken(true)
                                }
                        }
                        n.Left = defaultlit(n.Left, nil)
@@ -3061,18 +3058,12 @@ func checkassign(stmt *Node, n *Node) {
        // Variables declared in ORANGE are assigned on every iteration.
        if n.Name == nil || n.Name.Defn != stmt || stmt.Op == ORANGE {
                r := outervalue(n)
-               var l *Node
-               for l = n; l != r; l = l.Left {
-                       l.SetAssigned(true)
-                       if l.IsClosureVar() {
-                               l.Name.Defn.SetAssigned(true)
+               if r.Op == ONAME {
+                       r.Name.SetAssigned(true)
+                       if r.Name.IsClosureVar() {
+                               r.Name.Defn.Name.SetAssigned(true)
                        }
                }
-
-               l.SetAssigned(true)
-               if l.IsClosureVar() {
-                       l.Name.Defn.SetAssigned(true)
-               }
        }
 
        if islvalue(n) {
index 325eea019fc8cdfe53113d7f89f691384bca6baa..bebb9b6afe55cba7d90f52a29079262fb4323be2 100644 (file)
@@ -97,7 +97,7 @@ func paramoutheap(fn *Node) bool {
        for _, ln := range fn.Func.Dcl {
                switch ln.Class() {
                case PPARAMOUT:
-                       if ln.isParamStackCopy() || ln.Addrtaken() {
+                       if ln.isParamStackCopy() || ln.Name.Addrtaken() {
                                return true
                        }
 
@@ -2097,7 +2097,7 @@ func aliased(n *Node, all []*Node, i int) bool {
                        continue
 
                case PAUTO, PPARAM, PPARAMOUT:
-                       if n.Addrtaken() {
+                       if n.Name.Addrtaken() {
                                varwrite = true
                                continue
                        }
@@ -2145,7 +2145,7 @@ func varexpr(n *Node) bool {
        case ONAME:
                switch n.Class() {
                case PAUTO, PPARAM, PPARAMOUT:
-                       if !n.Addrtaken() {
+                       if !n.Name.Addrtaken() {
                                return true
                        }
                }