Commit b66a8923 authored by Ian Lance Taylor's avatar Ian Lance Taylor

cmd/compile: change Func.{Dcl,Inldcl} from NodeList to slice

A slice uses less memory than a NodeList, and has better memory locality
when walking the list.

This uncovered a tricky case involving closures: the escape analysis
pass when run on a closure was appending to the Dcl list of the OCLOSURE
rather than the ODCLFUNC.  This happened to work because they shared the
same NodeList.  Fixed with a change to addrescapes, and a check to
Tempname to catch any recurrences.

This removes the last use of the listsort function outside of tests.
I'll send a separate CL to remove it.

Unfortunately, while this passes all tests, it does not pass toolstash
-cmp.  The problem is that cmpstackvarlt does not fully determine the
sort order, and the change from listsort to sort.Sort, while generally
desirable, produces a different ordering.  I could stage this by first
making cmpstackvarlt fully determined, but no matter what toolstash -cmp
is going to break at some point.

In my casual testing the compiler is 2.2% faster.

Update #14473.

Change-Id: I367d66daa4ec73ed95c14c66ccda3a2133ad95d5
Reviewed-on: https://go-review.googlesource.com/19919Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 67dbde0d
...@@ -14,8 +14,6 @@ import ( ...@@ -14,8 +14,6 @@ import (
var isPlan9 = obj.Getgoos() == "plan9" var isPlan9 = obj.Getgoos() == "plan9"
func defframe(ptxt *obj.Prog) { func defframe(ptxt *obj.Prog) {
var n *gc.Node
// fill in argument size, stack size // fill in argument size, stack size
ptxt.To.Type = obj.TYPE_TEXTSIZE ptxt.To.Type = obj.TYPE_TEXTSIZE
...@@ -34,8 +32,7 @@ func defframe(ptxt *obj.Prog) { ...@@ -34,8 +32,7 @@ func defframe(ptxt *obj.Prog) {
x0 := uint32(0) x0 := uint32(0)
// iterate through declarations - they are sorted in decreasing xoffset order. // iterate through declarations - they are sorted in decreasing xoffset order.
for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next { for _, n := range gc.Curfn.Func.Dcl {
n = l.N
if !n.Name.Needzero { if !n.Name.Needzero {
continue continue
} }
......
...@@ -11,8 +11,6 @@ import ( ...@@ -11,8 +11,6 @@ import (
) )
func defframe(ptxt *obj.Prog) { func defframe(ptxt *obj.Prog) {
var n *gc.Node
// fill in argument size, stack size // fill in argument size, stack size
ptxt.To.Type = obj.TYPE_TEXTSIZE ptxt.To.Type = obj.TYPE_TEXTSIZE
...@@ -28,8 +26,7 @@ func defframe(ptxt *obj.Prog) { ...@@ -28,8 +26,7 @@ func defframe(ptxt *obj.Prog) {
hi := int64(0) hi := int64(0)
lo := hi lo := hi
r0 := uint32(0) r0 := uint32(0)
for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next { for _, n := range gc.Curfn.Func.Dcl {
n = l.N
if !n.Name.Needzero { if !n.Name.Needzero {
continue continue
} }
......
...@@ -12,8 +12,6 @@ import ( ...@@ -12,8 +12,6 @@ import (
) )
func defframe(ptxt *obj.Prog) { func defframe(ptxt *obj.Prog) {
var n *gc.Node
// fill in argument size, stack size // fill in argument size, stack size
ptxt.To.Type = obj.TYPE_TEXTSIZE ptxt.To.Type = obj.TYPE_TEXTSIZE
...@@ -37,8 +35,7 @@ func defframe(ptxt *obj.Prog) { ...@@ -37,8 +35,7 @@ func defframe(ptxt *obj.Prog) {
lo := hi lo := hi
// iterate through declarations - they are sorted in decreasing xoffset order. // iterate through declarations - they are sorted in decreasing xoffset order.
for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next { for _, n := range gc.Curfn.Func.Dcl {
n = l.N
if !n.Name.Needzero { if !n.Name.Needzero {
continue continue
} }
......
...@@ -2263,9 +2263,9 @@ func sgen_wb(n *Node, ns *Node, w int64, wb bool) { ...@@ -2263,9 +2263,9 @@ func sgen_wb(n *Node, ns *Node, w int64, wb bool) {
// If copying .args, that's all the results, so record definition sites // If copying .args, that's all the results, so record definition sites
// for them for the liveness analysis. // for them for the liveness analysis.
if ns.Op == ONAME && ns.Sym.Name == ".args" { if ns.Op == ONAME && ns.Sym.Name == ".args" {
for l := Curfn.Func.Dcl; l != nil; l = l.Next { for _, ln := range Curfn.Func.Dcl {
if l.N.Class == PPARAMOUT { if ln.Class == PPARAMOUT {
Gvardef(l.N) Gvardef(ln)
} }
} }
} }
......
...@@ -96,9 +96,9 @@ func typecheckclosure(func_ *Node, top int) { ...@@ -96,9 +96,9 @@ func typecheckclosure(func_ *Node, top int) {
} }
} }
for l := func_.Func.Dcl; l != nil; l = l.Next { for _, ln := range func_.Func.Dcl {
if l.N.Op == ONAME && (l.N.Class == PPARAM || l.N.Class == PPARAMOUT) { if ln.Op == ONAME && (ln.Class == PPARAM || ln.Class == PPARAMOUT) {
l.N.Name.Decldepth = 1 ln.Name.Decldepth = 1
} }
} }
...@@ -198,7 +198,8 @@ func makeclosure(func_ *Node) *Node { ...@@ -198,7 +198,8 @@ func makeclosure(func_ *Node) *Node {
makefuncsym(xfunc.Func.Nname.Sym) makefuncsym(xfunc.Func.Nname.Sym)
xfunc.Nbody = func_.Nbody xfunc.Nbody = func_.Nbody
xfunc.Func.Dcl = concat(func_.Func.Dcl, xfunc.Func.Dcl) xfunc.Func.Dcl = append(func_.Func.Dcl, xfunc.Func.Dcl...)
func_.Func.Dcl = nil
if xfunc.Nbody == nil { if xfunc.Nbody == nil {
Fatalf("empty body - won't generate any code") Fatalf("empty body - won't generate any code")
} }
...@@ -341,13 +342,13 @@ func transformclosure(xfunc *Node) { ...@@ -341,13 +342,13 @@ func transformclosure(xfunc *Node) {
fld.Sym = fld.Nname.Sym fld.Sym = fld.Nname.Sym
// Declare the new param and add it the first part of the input arguments. // Declare the new param and add it the first part of the input arguments.
xfunc.Func.Dcl = list(xfunc.Func.Dcl, fld.Nname) xfunc.Func.Dcl = append(xfunc.Func.Dcl, fld.Nname)
*param = fld *param = fld
param = &fld.Down param = &fld.Down
} }
*param = original_args *param = original_args
xfunc.Func.Dcl = concat(xfunc.Func.Dcl, original_dcl) xfunc.Func.Dcl = append(xfunc.Func.Dcl, original_dcl...)
// Recalculate param offsets. // Recalculate param offsets.
if f.Type.Width > 0 { if f.Type.Width > 0 {
...@@ -386,7 +387,7 @@ func transformclosure(xfunc *Node) { ...@@ -386,7 +387,7 @@ func transformclosure(xfunc *Node) {
// If it is a small variable captured by value, downgrade it to PAUTO. // If it is a small variable captured by value, downgrade it to PAUTO.
v.Class = PAUTO v.Class = PAUTO
v.Ullman = 1 v.Ullman = 1
xfunc.Func.Dcl = list(xfunc.Func.Dcl, v) xfunc.Func.Dcl = append(xfunc.Func.Dcl, v)
body = list(body, Nod(OAS, v, cv)) body = list(body, Nod(OAS, v, cv))
} else { } else {
// Declare variable holding addresses taken from closure // Declare variable holding addresses taken from closure
...@@ -396,7 +397,7 @@ func transformclosure(xfunc *Node) { ...@@ -396,7 +397,7 @@ func transformclosure(xfunc *Node) {
addr.Class = PAUTO addr.Class = PAUTO
addr.Used = true addr.Used = true
addr.Name.Curfn = xfunc addr.Name.Curfn = xfunc
xfunc.Func.Dcl = list(xfunc.Func.Dcl, addr) xfunc.Func.Dcl = append(xfunc.Func.Dcl, addr)
v.Name.Heapaddr = addr v.Name.Heapaddr = addr
if v.Name.Byval { if v.Name.Byval {
cv = Nod(OADDR, cv, nil) cv = Nod(OADDR, cv, nil)
...@@ -551,7 +552,7 @@ func makepartialcall(fn *Node, t0 *Type, meth *Node) *Node { ...@@ -551,7 +552,7 @@ func makepartialcall(fn *Node, t0 *Type, meth *Node) *Node {
n = newname(Lookupf("a%d", i)) n = newname(Lookupf("a%d", i))
i++ i++
n.Class = PPARAM n.Class = PPARAM
xfunc.Func.Dcl = list(xfunc.Func.Dcl, n) xfunc.Func.Dcl = append(xfunc.Func.Dcl, n)
callargs = list(callargs, n) callargs = list(callargs, n)
fld = Nod(ODCLFIELD, n, typenod(t.Type)) fld = Nod(ODCLFIELD, n, typenod(t.Type))
if t.Isddd { if t.Isddd {
...@@ -570,7 +571,7 @@ func makepartialcall(fn *Node, t0 *Type, meth *Node) *Node { ...@@ -570,7 +571,7 @@ func makepartialcall(fn *Node, t0 *Type, meth *Node) *Node {
n = newname(Lookupf("r%d", i)) n = newname(Lookupf("r%d", i))
i++ i++
n.Class = PPARAMOUT n.Class = PPARAMOUT
xfunc.Func.Dcl = list(xfunc.Func.Dcl, n) xfunc.Func.Dcl = append(xfunc.Func.Dcl, n)
retargs = list(retargs, n) retargs = list(retargs, n)
l = list(l, Nod(ODCLFIELD, n, typenod(t.Type))) l = list(l, Nod(ODCLFIELD, n, typenod(t.Type)))
} }
...@@ -600,7 +601,7 @@ func makepartialcall(fn *Node, t0 *Type, meth *Node) *Node { ...@@ -600,7 +601,7 @@ func makepartialcall(fn *Node, t0 *Type, meth *Node) *Node {
ptr.Ullman = 1 ptr.Ullman = 1
ptr.Used = true ptr.Used = true
ptr.Name.Curfn = xfunc ptr.Name.Curfn = xfunc
xfunc.Func.Dcl = list(xfunc.Func.Dcl, ptr) xfunc.Func.Dcl = append(xfunc.Func.Dcl, ptr)
var body *NodeList var body *NodeList
if Isptr[rcvrtype.Etype] || Isinter(rcvrtype) { if Isptr[rcvrtype.Etype] || Isinter(rcvrtype) {
ptr.Name.Param.Ntype = typenod(rcvrtype) ptr.Name.Param.Ntype = typenod(rcvrtype)
......
...@@ -187,7 +187,7 @@ func declare(n *Node, ctxt Class) { ...@@ -187,7 +187,7 @@ func declare(n *Node, ctxt Class) {
Fatalf("automatic outside function") Fatalf("automatic outside function")
} }
if Curfn != nil { if Curfn != nil {
Curfn.Func.Dcl = list(Curfn.Func.Dcl, n) Curfn.Func.Dcl = append(Curfn.Func.Dcl, n)
} }
if n.Op == OTYPE { if n.Op == OTYPE {
declare_typegen++ declare_typegen++
......
...@@ -476,35 +476,35 @@ func escfunc(e *EscState, func_ *Node) { ...@@ -476,35 +476,35 @@ func escfunc(e *EscState, func_ *Node) {
savefn := Curfn savefn := Curfn
Curfn = func_ Curfn = func_
for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next { for _, ln := range Curfn.Func.Dcl {
if ll.N.Op != ONAME { if ln.Op != ONAME {
continue continue
} }
llNE := e.nodeEscState(ll.N) llNE := e.nodeEscState(ln)
switch ll.N.Class { switch ln.Class {
// out params are in a loopdepth between the sink and all local variables // out params are in a loopdepth between the sink and all local variables
case PPARAMOUT: case PPARAMOUT:
llNE.Escloopdepth = 0 llNE.Escloopdepth = 0
case PPARAM: case PPARAM:
llNE.Escloopdepth = 1 llNE.Escloopdepth = 1
if ll.N.Type != nil && !haspointers(ll.N.Type) { if ln.Type != nil && !haspointers(ln.Type) {
break break
} }
if Curfn.Nbody == nil && !Curfn.Noescape { if Curfn.Nbody == nil && !Curfn.Noescape {
ll.N.Esc = EscHeap ln.Esc = EscHeap
} else { } else {
ll.N.Esc = EscNone // prime for escflood later ln.Esc = EscNone // prime for escflood later
} }
e.noesc = list(e.noesc, ll.N) e.noesc = list(e.noesc, ln)
} }
} }
// in a mutually recursive group we lose track of the return values // in a mutually recursive group we lose track of the return values
if e.recursive { if e.recursive {
for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next { for _, ln := range Curfn.Func.Dcl {
if ll.N.Op == ONAME && ll.N.Class == PPARAMOUT { if ln.Op == ONAME && ln.Class == PPARAMOUT {
escflows(e, &e.theSink, ll.N) escflows(e, &e.theSink, ln)
} }
} }
} }
...@@ -779,11 +779,14 @@ func esc(e *EscState, n *Node, up *Node) { ...@@ -779,11 +779,14 @@ func esc(e *EscState, n *Node, up *Node) {
ll = e.nodeEscState(n.List.N).Escretval ll = e.nodeEscState(n.List.N).Escretval
} }
for lr := Curfn.Func.Dcl; lr != nil && ll != nil; lr = lr.Next { for _, lrn := range Curfn.Func.Dcl {
if lr.N.Op != ONAME || lr.N.Class != PPARAMOUT { if ll == nil {
break
}
if lrn.Op != ONAME || lrn.Class != PPARAMOUT {
continue continue
} }
escassign(e, lr.N, ll.N) escassign(e, lrn, ll.N)
ll = ll.Next ll = ll.Next
} }
...@@ -1870,16 +1873,16 @@ func esctag(e *EscState, func_ *Node) { ...@@ -1870,16 +1873,16 @@ func esctag(e *EscState, func_ *Node) {
savefn := Curfn savefn := Curfn
Curfn = func_ Curfn = func_
for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next { for _, ln := range Curfn.Func.Dcl {
if ll.N.Op != ONAME { if ln.Op != ONAME {
continue continue
} }
switch ll.N.Esc & EscMask { switch ln.Esc & EscMask {
case EscNone, // not touched by escflood case EscNone, // not touched by escflood
EscReturn: EscReturn:
if haspointers(ll.N.Type) { // don't bother tagging for scalars if haspointers(ln.Type) { // don't bother tagging for scalars
ll.N.Name.Param.Field.Note = mktag(int(ll.N.Esc)) ln.Name.Param.Field.Note = mktag(int(ln.Esc))
} }
case EscHeap, // touched by escflood, moved to heap case EscHeap, // touched by escflood, moved to heap
......
...@@ -76,6 +76,9 @@ func addrescapes(n *Node) { ...@@ -76,6 +76,9 @@ func addrescapes(n *Node) {
oldfn := Curfn oldfn := Curfn
Curfn = n.Name.Curfn Curfn = n.Name.Curfn
if Curfn.Func.Closure != nil && Curfn.Op == OCLOSURE {
Curfn = Curfn.Func.Closure
}
n.Name.Heapaddr = temp(Ptrto(n.Type)) n.Name.Heapaddr = temp(Ptrto(n.Type))
buf := fmt.Sprintf("&%v", n.Sym) buf := fmt.Sprintf("&%v", n.Sym)
n.Name.Heapaddr.Sym = Lookup(buf) n.Name.Heapaddr.Sym = Lookup(buf)
...@@ -585,6 +588,10 @@ func Tempname(nn *Node, t *Type) { ...@@ -585,6 +588,10 @@ func Tempname(nn *Node, t *Type) {
if Curfn == nil { if Curfn == nil {
Fatalf("no curfn for tempname") Fatalf("no curfn for tempname")
} }
if Curfn.Func.Closure != nil && Curfn.Op == OCLOSURE {
Dump("Tempname", Curfn)
Fatalf("adding tempname to wrong closure function")
}
if t == nil { if t == nil {
Yyerror("tempname called with nil type") Yyerror("tempname called with nil type")
...@@ -604,7 +611,7 @@ func Tempname(nn *Node, t *Type) { ...@@ -604,7 +611,7 @@ func Tempname(nn *Node, t *Type) {
n.Ullman = 1 n.Ullman = 1
n.Esc = EscNever n.Esc = EscNever
n.Name.Curfn = Curfn n.Name.Curfn = Curfn
Curfn.Func.Dcl = list(Curfn.Func.Dcl, n) Curfn.Func.Dcl = append(Curfn.Func.Dcl, n)
dowidth(t) dowidth(t)
n.Xoffset = 0 n.Xoffset = 0
......
...@@ -556,9 +556,7 @@ func nodarg(t *Type, fp int) *Node { ...@@ -556,9 +556,7 @@ func nodarg(t *Type, fp int) *Node {
} }
if fp == 1 { if fp == 1 {
var n *Node for _, n := range Curfn.Func.Dcl {
for l := Curfn.Func.Dcl; l != nil; l = l.Next {
n = l.N
if (n.Class == PPARAM || n.Class == PPARAMOUT) && !isblanksym(t.Sym) && n.Sym == t.Sym { if (n.Class == PPARAM || n.Class == PPARAMOUT) && !isblanksym(t.Sym) && n.Sym == t.Sym {
return n return n
} }
......
...@@ -150,7 +150,7 @@ func caninl(fn *Node) { ...@@ -150,7 +150,7 @@ func caninl(fn *Node) {
fn.Func.Nname.Func.Inl = fn.Nbody fn.Func.Nname.Func.Inl = fn.Nbody
fn.Nbody = inlcopylist(fn.Func.Nname.Func.Inl) fn.Nbody = inlcopylist(fn.Func.Nname.Func.Inl)
fn.Func.Nname.Func.Inldcl = inlcopylist(fn.Func.Nname.Name.Defn.Func.Dcl) fn.Func.Nname.Func.Inldcl = inlcopyslice(fn.Func.Nname.Name.Defn.Func.Dcl)
fn.Func.Nname.Func.InlCost = int32(maxBudget - budget) fn.Func.Nname.Func.InlCost = int32(maxBudget - budget)
// hack, TODO, check for better way to link method nodes back to the thing with the ->inl // hack, TODO, check for better way to link method nodes back to the thing with the ->inl
...@@ -275,6 +275,18 @@ func inlcopy(n *Node) *Node { ...@@ -275,6 +275,18 @@ func inlcopy(n *Node) *Node {
return m return m
} }
// Inlcopyslice is like inlcopylist, but for a slice.
func inlcopyslice(ll []*Node) []*Node {
r := make([]*Node, 0, len(ll))
for _, ln := range ll {
c := inlcopy(ln)
if c != nil {
r = append(r, c)
}
}
return r
}
// Inlcalls/nodelist/node walks fn's statements and expressions and substitutes any // Inlcalls/nodelist/node walks fn's statements and expressions and substitutes any
// calls made to inlineable functions. This is the external entry point. // calls made to inlineable functions. This is the external entry point.
func inlcalls(fn *Node) { func inlcalls(fn *Node) {
...@@ -556,7 +568,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -556,7 +568,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
//dumplist("ninit pre", ninit); //dumplist("ninit pre", ninit);
var dcl *NodeList var dcl []*Node
if fn.Name.Defn != nil { // local function if fn.Name.Defn != nil { // local function
dcl = fn.Func.Inldcl // imported function dcl = fn.Func.Inldcl // imported function
} else { } else {
...@@ -567,18 +579,18 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -567,18 +579,18 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
i := 0 i := 0
// Make temp names to use instead of the originals // Make temp names to use instead of the originals
for ll := dcl; ll != nil; ll = ll.Next { for _, ln := range dcl {
if ll.N.Class == PPARAMOUT { // return values handled below. if ln.Class == PPARAMOUT { // return values handled below.
continue continue
} }
if ll.N.Op == ONAME { if ln.Op == ONAME {
ll.N.Name.Inlvar = inlvar(ll.N) ln.Name.Inlvar = inlvar(ln)
// Typecheck because inlvar is not necessarily a function parameter. // Typecheck because inlvar is not necessarily a function parameter.
typecheck(&ll.N.Name.Inlvar, Erv) typecheck(&ln.Name.Inlvar, Erv)
if ll.N.Class&^PHEAP != PAUTO { if ln.Class&^PHEAP != PAUTO {
ninit = list(ninit, Nod(ODCL, ll.N.Name.Inlvar, nil)) // otherwise gen won't emit the allocations for heapallocs ninit = list(ninit, Nod(ODCL, ln.Name.Inlvar, nil)) // otherwise gen won't emit the allocations for heapallocs
} }
} }
} }
...@@ -852,7 +864,7 @@ func inlvar(var_ *Node) *Node { ...@@ -852,7 +864,7 @@ func inlvar(var_ *Node) *Node {
addrescapes(n) addrescapes(n)
} }
Curfn.Func.Dcl = list(Curfn.Func.Dcl, n) Curfn.Func.Dcl = append(Curfn.Func.Dcl, n)
return n return n
} }
...@@ -863,7 +875,7 @@ func retvar(t *Type, i int) *Node { ...@@ -863,7 +875,7 @@ func retvar(t *Type, i int) *Node {
n.Class = PAUTO n.Class = PAUTO
n.Used = true n.Used = true
n.Name.Curfn = Curfn // the calling function, not the called one n.Name.Curfn = Curfn // the calling function, not the called one
Curfn.Func.Dcl = list(Curfn.Func.Dcl, n) Curfn.Func.Dcl = append(Curfn.Func.Dcl, n)
return n return n
} }
...@@ -875,7 +887,7 @@ func argvar(t *Type, i int) *Node { ...@@ -875,7 +887,7 @@ func argvar(t *Type, i int) *Node {
n.Class = PAUTO n.Class = PAUTO
n.Used = true n.Used = true
n.Name.Curfn = Curfn // the calling function, not the called one n.Name.Curfn = Curfn // the calling function, not the called one
Curfn.Func.Dcl = list(Curfn.Func.Dcl, n) Curfn.Func.Dcl = append(Curfn.Func.Dcl, n)
return n return n
} }
......
...@@ -2564,15 +2564,15 @@ func (p *parser) stmt() *Node { ...@@ -2564,15 +2564,15 @@ func (p *parser) stmt() *Node {
stmt := Nod(ORETURN, nil, nil) stmt := Nod(ORETURN, nil, nil)
stmt.List = results stmt.List = results
if stmt.List == nil && Curfn != nil { if stmt.List == nil && Curfn != nil {
for l := Curfn.Func.Dcl; l != nil; l = l.Next { for _, ln := range Curfn.Func.Dcl {
if l.N.Class == PPARAM { if ln.Class == PPARAM {
continue continue
} }
if l.N.Class != PPARAMOUT { if ln.Class != PPARAMOUT {
break break
} }
if l.N.Sym.Def != l.N { if ln.Sym.Def != ln {
Yyerror("%s is shadowed during return", l.N.Sym.Name) Yyerror("%s is shadowed during return", ln.Sym.Name)
} }
} }
} }
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"cmd/internal/obj" "cmd/internal/obj"
"crypto/md5" "crypto/md5"
"fmt" "fmt"
"sort"
"strings" "strings"
) )
...@@ -217,6 +218,13 @@ func cmpstackvarlt(a, b *Node) bool { ...@@ -217,6 +218,13 @@ func cmpstackvarlt(a, b *Node) bool {
return a.Sym.Name < b.Sym.Name return a.Sym.Name < b.Sym.Name
} }
// byStackvar implements sort.Interface for []*Node using cmpstackvarlt.
type byStackVar []*Node
func (s byStackVar) Len() int { return len(s) }
func (s byStackVar) Less(i, j int) bool { return cmpstackvarlt(s[i], s[j]) }
func (s byStackVar) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// stkdelta records the stack offset delta for a node // stkdelta records the stack offset delta for a node
// during the compaction of the stack frame to remove // during the compaction of the stack frame to remove
// unused stack slots. // unused stack slots.
...@@ -227,25 +235,23 @@ func allocauto(ptxt *obj.Prog) { ...@@ -227,25 +235,23 @@ func allocauto(ptxt *obj.Prog) {
Stksize = 0 Stksize = 0
stkptrsize = 0 stkptrsize = 0
if Curfn.Func.Dcl == nil { if len(Curfn.Func.Dcl) == 0 {
return return
} }
// Mark the PAUTO's unused. // Mark the PAUTO's unused.
for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next { for _, ln := range Curfn.Func.Dcl {
if ll.N.Class == PAUTO { if ln.Class == PAUTO {
ll.N.Used = false ln.Used = false
} }
} }
markautoused(ptxt) markautoused(ptxt)
listsort(&Curfn.Func.Dcl, cmpstackvarlt) sort.Sort(byStackVar(Curfn.Func.Dcl))
// Unused autos are at the end, chop 'em off. // Unused autos are at the end, chop 'em off.
ll := Curfn.Func.Dcl n := Curfn.Func.Dcl[0]
n := ll.N
if n.Class == PAUTO && n.Op == ONAME && !n.Used { if n.Class == PAUTO && n.Op == ONAME && !n.Used {
// No locals used at all // No locals used at all
Curfn.Func.Dcl = nil Curfn.Func.Dcl = nil
...@@ -254,19 +260,17 @@ func allocauto(ptxt *obj.Prog) { ...@@ -254,19 +260,17 @@ func allocauto(ptxt *obj.Prog) {
return return
} }
for ll := Curfn.Func.Dcl; ll.Next != nil; ll = ll.Next { for i := 1; i < len(Curfn.Func.Dcl); i++ {
n = ll.Next.N n = Curfn.Func.Dcl[i]
if n.Class == PAUTO && n.Op == ONAME && !n.Used { if n.Class == PAUTO && n.Op == ONAME && !n.Used {
ll.Next = nil Curfn.Func.Dcl = Curfn.Func.Dcl[:i]
Curfn.Func.Dcl.End = ll
break break
} }
} }
// Reassign stack offsets of the locals that are still there. // Reassign stack offsets of the locals that are still there.
var w int64 var w int64
for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next { for _, n := range Curfn.Func.Dcl {
n = ll.N
if n.Class != PAUTO || n.Op != ONAME { if n.Class != PAUTO || n.Op != ONAME {
continue continue
} }
...@@ -298,12 +302,12 @@ func allocauto(ptxt *obj.Prog) { ...@@ -298,12 +302,12 @@ func allocauto(ptxt *obj.Prog) {
fixautoused(ptxt) fixautoused(ptxt)
// The debug information needs accurate offsets on the symbols. // The debug information needs accurate offsets on the symbols.
for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next { for _, ln := range Curfn.Func.Dcl {
if ll.N.Class != PAUTO || ll.N.Op != ONAME { if ln.Class != PAUTO || ln.Op != ONAME {
continue continue
} }
ll.N.Xoffset += stkdelta[ll.N] ln.Xoffset += stkdelta[ln]
delete(stkdelta, ll.N) delete(stkdelta, ln)
} }
} }
...@@ -455,16 +459,15 @@ func compile(fn *Node) { ...@@ -455,16 +459,15 @@ func compile(fn *Node) {
gtrack(tracksym(t)) gtrack(tracksym(t))
} }
for l := fn.Func.Dcl; l != nil; l = l.Next { for _, n := range fn.Func.Dcl {
n = l.N
if n.Op != ONAME { // might be OTYPE or OLITERAL if n.Op != ONAME { // might be OTYPE or OLITERAL
continue continue
} }
switch n.Class { switch n.Class {
case PAUTO, PPARAM, PPARAMOUT: case PAUTO, PPARAM, PPARAMOUT:
Nodconst(&nod1, Types[TUINTPTR], l.N.Type.Width) Nodconst(&nod1, Types[TUINTPTR], n.Type.Width)
p = Thearch.Gins(obj.ATYPE, l.N, &nod1) p = Thearch.Gins(obj.ATYPE, n, &nod1)
p.From.Gotype = Linksym(ngotype(l.N)) p.From.Gotype = Linksym(ngotype(n))
} }
} }
......
...@@ -197,8 +197,8 @@ func blockany(bb *BasicBlock, f func(*obj.Prog) bool) bool { ...@@ -197,8 +197,8 @@ func blockany(bb *BasicBlock, f func(*obj.Prog) bool) bool {
// variables. // variables.
func getvariables(fn *Node) []*Node { func getvariables(fn *Node) []*Node {
result := make([]*Node, 0, 0) result := make([]*Node, 0, 0)
for ll := fn.Func.Dcl; ll != nil; ll = ll.Next { for _, ln := range fn.Func.Dcl {
if ll.N.Op == ONAME { if ln.Op == ONAME {
// In order for GODEBUG=gcdead=1 to work, each bitmap needs // In order for GODEBUG=gcdead=1 to work, each bitmap needs
// to contain information about all variables covered by the bitmap. // to contain information about all variables covered by the bitmap.
// For local variables, the bitmap only covers the stkptrsize // For local variables, the bitmap only covers the stkptrsize
...@@ -218,24 +218,24 @@ func getvariables(fn *Node) []*Node { ...@@ -218,24 +218,24 @@ func getvariables(fn *Node) []*Node {
// Later, when we want to find the index of a node in the variables list, // Later, when we want to find the index of a node in the variables list,
// we will check that n->curfn == curfn and n->opt > 0. Then n->opt - 1 // we will check that n->curfn == curfn and n->opt > 0. Then n->opt - 1
// is the index in the variables list. // is the index in the variables list.
ll.N.SetOpt(nil) ln.SetOpt(nil)
// The compiler doesn't emit initializations for zero-width parameters or results. // The compiler doesn't emit initializations for zero-width parameters or results.
if ll.N.Type.Width == 0 { if ln.Type.Width == 0 {
continue continue
} }
ll.N.Name.Curfn = Curfn ln.Name.Curfn = Curfn
switch ll.N.Class { switch ln.Class {
case PAUTO: case PAUTO:
if haspointers(ll.N.Type) { if haspointers(ln.Type) {
ll.N.SetOpt(int32(len(result))) ln.SetOpt(int32(len(result)))
result = append(result, ll.N) result = append(result, ln)
} }
case PPARAM, PPARAMOUT: case PPARAM, PPARAMOUT:
ll.N.SetOpt(int32(len(result))) ln.SetOpt(int32(len(result)))
result = append(result, ll.N) result = append(result, ln)
} }
} }
} }
...@@ -795,8 +795,8 @@ func livenessprintcfg(lv *Liveness) { ...@@ -795,8 +795,8 @@ func livenessprintcfg(lv *Liveness) {
} }
func checkauto(fn *Node, p *obj.Prog, n *Node) { func checkauto(fn *Node, p *obj.Prog, n *Node) {
for l := fn.Func.Dcl; l != nil; l = l.Next { for _, ln := range fn.Func.Dcl {
if l.N.Op == ONAME && l.N.Class == PAUTO && l.N == n { if ln.Op == ONAME && ln.Class == PAUTO && ln == n {
return return
} }
} }
...@@ -807,8 +807,8 @@ func checkauto(fn *Node, p *obj.Prog, n *Node) { ...@@ -807,8 +807,8 @@ func checkauto(fn *Node, p *obj.Prog, n *Node) {
} }
fmt.Printf("checkauto %v: %v (%p; class=%d) not found in %p %v\n", funcSym(Curfn), n, n, n.Class, p, p) fmt.Printf("checkauto %v: %v (%p; class=%d) not found in %p %v\n", funcSym(Curfn), n, n, n.Class, p, p)
for l := fn.Func.Dcl; l != nil; l = l.Next { for _, ln := range fn.Func.Dcl {
fmt.Printf("\t%v (%p; class=%d)\n", l.N, l.N, l.N.Class) fmt.Printf("\t%v (%p; class=%d)\n", ln, ln, ln.Class)
} }
Yyerror("checkauto: invariant lost") Yyerror("checkauto: invariant lost")
} }
...@@ -817,10 +817,8 @@ func checkparam(fn *Node, p *obj.Prog, n *Node) { ...@@ -817,10 +817,8 @@ func checkparam(fn *Node, p *obj.Prog, n *Node) {
if isfunny(n) { if isfunny(n) {
return return
} }
var a *Node
var class Class var class Class
for l := fn.Func.Dcl; l != nil; l = l.Next { for _, a := range fn.Func.Dcl {
a = l.N
class = a.Class &^ PHEAP class = a.Class &^ PHEAP
if a.Op == ONAME && (class == PPARAM || class == PPARAMOUT) && a == n { if a.Op == ONAME && (class == PPARAM || class == PPARAMOUT) && a == n {
return return
...@@ -828,8 +826,8 @@ func checkparam(fn *Node, p *obj.Prog, n *Node) { ...@@ -828,8 +826,8 @@ func checkparam(fn *Node, p *obj.Prog, n *Node) {
} }
fmt.Printf("checkparam %v: %v (%p; class=%d) not found in %v\n", Curfn, n, n, n.Class, p) fmt.Printf("checkparam %v: %v (%p; class=%d) not found in %v\n", Curfn, n, n, n.Class, p)
for l := fn.Func.Dcl; l != nil; l = l.Next { for _, ln := range fn.Func.Dcl {
fmt.Printf("\t%v (%p; class=%d)\n", l.N, l.N, l.N.Class) fmt.Printf("\t%v (%p; class=%d)\n", ln, ln, ln.Class)
} }
Yyerror("checkparam: invariant lost") Yyerror("checkparam: invariant lost")
} }
...@@ -1807,9 +1805,9 @@ func liveness(fn *Node, firstp *obj.Prog, argssym *Sym, livesym *Sym) { ...@@ -1807,9 +1805,9 @@ func liveness(fn *Node, firstp *obj.Prog, argssym *Sym, livesym *Sym) {
onebitwritesymbol(lv.argslivepointers, argssym) onebitwritesymbol(lv.argslivepointers, argssym)
// Free everything. // Free everything.
for l := fn.Func.Dcl; l != nil; l = l.Next { for _, ln := range fn.Func.Dcl {
if l.N != nil { if ln != nil {
l.N.SetOpt(nil) ln.SetOpt(nil)
} }
} }
freeliveness(lv) freeliveness(lv)
......
...@@ -589,8 +589,8 @@ func mergetemp(firstp *obj.Prog) { ...@@ -589,8 +589,8 @@ func mergetemp(firstp *obj.Prog) {
// Build list of all mergeable variables. // Build list of all mergeable variables.
var vars []*TempVar var vars []*TempVar
for l := Curfn.Func.Dcl; l != nil; l = l.Next { for _, n := range Curfn.Func.Dcl {
if n := l.N; canmerge(n) { if canmerge(n) {
v := &TempVar{} v := &TempVar{}
vars = append(vars, v) vars = append(vars, v)
n.SetOpt(v) n.SetOpt(v)
...@@ -819,22 +819,15 @@ func mergetemp(firstp *obj.Prog) { ...@@ -819,22 +819,15 @@ func mergetemp(firstp *obj.Prog) {
} }
// Delete merged nodes from declaration list. // Delete merged nodes from declaration list.
for lp := &Curfn.Func.Dcl; ; { dcl := make([]*Node, 0, len(Curfn.Func.Dcl)-nkill)
l := *lp for _, n := range Curfn.Func.Dcl {
if l == nil {
break
}
Curfn.Func.Dcl.End = l
n := l.N
v, _ := n.Opt().(*TempVar) v, _ := n.Opt().(*TempVar)
if v != nil && (v.merge != nil || v.removed) { if v != nil && (v.merge != nil || v.removed) {
*lp = l.Next
continue continue
} }
dcl = append(dcl, n)
lp = &l.Next
} }
Curfn.Func.Dcl = dcl
// Clear aux structures. // Clear aux structures.
for _, v := range vars { for _, v := range vars {
......
...@@ -1543,8 +1543,8 @@ func frame(context int) { ...@@ -1543,8 +1543,8 @@ func frame(context int) {
if Curfn != nil { if Curfn != nil {
fmt.Printf("--- %v frame ---\n", Curfn.Func.Nname.Sym) fmt.Printf("--- %v frame ---\n", Curfn.Func.Nname.Sym)
for l := Curfn.Func.Dcl; l != nil; l = l.Next { for _, ln := range Curfn.Func.Dcl {
printframenode(l.N) printframenode(ln)
} }
} }
} }
......
...@@ -152,8 +152,8 @@ type Func struct { ...@@ -152,8 +152,8 @@ type Func struct {
Enter *NodeList Enter *NodeList
Exit *NodeList Exit *NodeList
Cvars *NodeList // closure params Cvars *NodeList // closure params
Dcl *NodeList // autodcl for this func/closure Dcl []*Node // autodcl for this func/closure
Inldcl *NodeList // copy of dcl for use in inlining Inldcl []*Node // copy of dcl for use in inlining
Closgen int Closgen int
Outerfunc *Node Outerfunc *Node
Fieldtrack []*Type Fieldtrack []*Type
......
...@@ -3433,9 +3433,9 @@ func typecheckfunc(n *Node) { ...@@ -3433,9 +3433,9 @@ func typecheckfunc(n *Node) {
addmethod(n.Func.Shortname.Sym, t, true, n.Func.Nname.Nointerface) addmethod(n.Func.Shortname.Sym, t, true, n.Func.Nname.Nointerface)
} }
for l := n.Func.Dcl; l != nil; l = l.Next { for _, ln := range n.Func.Dcl {
if l.N.Op == ONAME && (l.N.Class == PPARAM || l.N.Class == PPARAMOUT) { if ln.Op == ONAME && (ln.Class == PPARAM || ln.Class == PPARAMOUT) {
l.N.Name.Decldepth = 1 ln.Name.Decldepth = 1
} }
} }
} }
......
...@@ -29,33 +29,34 @@ func walk(fn *Node) { ...@@ -29,33 +29,34 @@ func walk(fn *Node) {
// Final typecheck for any unused variables. // Final typecheck for any unused variables.
// It's hard to be on the heap when not-used, but best to be consistent about &~PHEAP here and below. // It's hard to be on the heap when not-used, but best to be consistent about &~PHEAP here and below.
for l := fn.Func.Dcl; l != nil; l = l.Next { for i, ln := range fn.Func.Dcl {
if l.N.Op == ONAME && l.N.Class&^PHEAP == PAUTO { if ln.Op == ONAME && ln.Class&^PHEAP == PAUTO {
typecheck(&l.N, Erv|Easgn) typecheck(&ln, Erv|Easgn)
fn.Func.Dcl[i] = ln
} }
} }
// Propagate the used flag for typeswitch variables up to the NONAME in it's definition. // Propagate the used flag for typeswitch variables up to the NONAME in it's definition.
for l := fn.Func.Dcl; l != nil; l = l.Next { for _, ln := range fn.Func.Dcl {
if l.N.Op == ONAME && l.N.Class&^PHEAP == PAUTO && l.N.Name.Defn != nil && l.N.Name.Defn.Op == OTYPESW && l.N.Used { if ln.Op == ONAME && ln.Class&^PHEAP == PAUTO && ln.Name.Defn != nil && ln.Name.Defn.Op == OTYPESW && ln.Used {
l.N.Name.Defn.Left.Used = true ln.Name.Defn.Left.Used = true
} }
} }
for l := fn.Func.Dcl; l != nil; l = l.Next { for _, ln := range fn.Func.Dcl {
if l.N.Op != ONAME || l.N.Class&^PHEAP != PAUTO || l.N.Sym.Name[0] == '&' || l.N.Used { if ln.Op != ONAME || ln.Class&^PHEAP != PAUTO || ln.Sym.Name[0] == '&' || ln.Used {
continue continue
} }
if defn := l.N.Name.Defn; defn != nil && defn.Op == OTYPESW { if defn := ln.Name.Defn; defn != nil && defn.Op == OTYPESW {
if defn.Left.Used { if defn.Left.Used {
continue continue
} }
lineno = defn.Left.Lineno lineno = defn.Left.Lineno
Yyerror("%v declared and not used", l.N.Sym) Yyerror("%v declared and not used", ln.Sym)
defn.Left.Used = true // suppress repeats defn.Left.Used = true // suppress repeats
} else { } else {
lineno = l.N.Lineno lineno = ln.Lineno
Yyerror("%v declared and not used", l.N.Sym) Yyerror("%v declared and not used", ln.Sym)
} }
} }
...@@ -92,11 +93,11 @@ func samelist(a *NodeList, b *NodeList) bool { ...@@ -92,11 +93,11 @@ func samelist(a *NodeList, b *NodeList) bool {
} }
func paramoutheap(fn *Node) bool { func paramoutheap(fn *Node) bool {
for l := fn.Func.Dcl; l != nil; l = l.Next { for _, ln := range fn.Func.Dcl {
switch l.N.Class { switch ln.Class {
case PPARAMOUT, case PPARAMOUT,
PPARAMOUT | PHEAP: PPARAMOUT | PHEAP:
return l.N.Addrtaken return ln.Addrtaken
// stop early - parameters are over // stop early - parameters are over
case PAUTO, case PAUTO,
...@@ -290,13 +291,13 @@ func walkstmt(np **Node) { ...@@ -290,13 +291,13 @@ func walkstmt(np **Node) {
var rl *NodeList var rl *NodeList
var cl Class var cl Class
for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next { for _, ln := range Curfn.Func.Dcl {
cl = ll.N.Class &^ PHEAP cl = ln.Class &^ PHEAP
if cl == PAUTO { if cl == PAUTO {
break break
} }
if cl == PPARAMOUT { if cl == PPARAMOUT {
rl = list(rl, ll.N) rl = list(rl, ln)
} }
} }
......
...@@ -12,8 +12,6 @@ import ( ...@@ -12,8 +12,6 @@ import (
) )
func defframe(ptxt *obj.Prog) { func defframe(ptxt *obj.Prog) {
var n *gc.Node
// fill in argument size, stack size // fill in argument size, stack size
ptxt.To.Type = obj.TYPE_TEXTSIZE ptxt.To.Type = obj.TYPE_TEXTSIZE
...@@ -30,8 +28,7 @@ func defframe(ptxt *obj.Prog) { ...@@ -30,8 +28,7 @@ func defframe(ptxt *obj.Prog) {
lo := hi lo := hi
// iterate through declarations - they are sorted in decreasing xoffset order. // iterate through declarations - they are sorted in decreasing xoffset order.
for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next { for _, n := range gc.Curfn.Func.Dcl {
n = l.N
if !n.Name.Needzero { if !n.Name.Needzero {
continue continue
} }
......
...@@ -12,8 +12,6 @@ import ( ...@@ -12,8 +12,6 @@ import (
) )
func defframe(ptxt *obj.Prog) { func defframe(ptxt *obj.Prog) {
var n *gc.Node
// fill in argument size, stack size // fill in argument size, stack size
ptxt.To.Type = obj.TYPE_TEXTSIZE ptxt.To.Type = obj.TYPE_TEXTSIZE
...@@ -30,8 +28,7 @@ func defframe(ptxt *obj.Prog) { ...@@ -30,8 +28,7 @@ func defframe(ptxt *obj.Prog) {
lo := hi lo := hi
// iterate through declarations - they are sorted in decreasing xoffset order. // iterate through declarations - they are sorted in decreasing xoffset order.
for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next { for _, n := range gc.Curfn.Func.Dcl {
n = l.N
if !n.Name.Needzero { if !n.Name.Needzero {
continue continue
} }
......
...@@ -11,8 +11,6 @@ import ( ...@@ -11,8 +11,6 @@ import (
) )
func defframe(ptxt *obj.Prog) { func defframe(ptxt *obj.Prog) {
var n *gc.Node
// fill in argument size, stack size // fill in argument size, stack size
ptxt.To.Type = obj.TYPE_TEXTSIZE ptxt.To.Type = obj.TYPE_TEXTSIZE
...@@ -28,8 +26,7 @@ func defframe(ptxt *obj.Prog) { ...@@ -28,8 +26,7 @@ func defframe(ptxt *obj.Prog) {
hi := int64(0) hi := int64(0)
lo := hi lo := hi
ax := uint32(0) ax := uint32(0)
for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next { for _, n := range gc.Curfn.Func.Dcl {
n = l.N
if !n.Name.Needzero { if !n.Name.Needzero {
continue continue
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment