mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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/19919 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
67dbde0d71
commit
b66a892358
21 changed files with 161 additions and 163 deletions
|
|
@ -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) {
|
||||||
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 (
|
||||||
)
|
)
|
||||||
|
|
||||||
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) {
|
||||||
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 (
|
||||||
)
|
)
|
||||||
|
|
||||||
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) {
|
||||||
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) {
|
||||||
// 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) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
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) {
|
||||||
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) {
|
||||||
// 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) {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
|
||||||
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 {
|
||||||
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) {
|
||||||
|
|
||||||
//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) {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 (
|
||||||
"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 {
|
||||||
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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
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 {
|
||||||
// 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 {
|
||||||
// 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) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
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) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
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) {
|
||||||
|
|
||||||
// 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) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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) {
|
||||||
|
|
||||||
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 {
|
||||||
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) {
|
||||||
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) {
|
||||||
|
|
||||||
// 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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
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 (
|
||||||
)
|
)
|
||||||
|
|
||||||
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) {
|
||||||
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 (
|
||||||
)
|
)
|
||||||
|
|
||||||
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) {
|
||||||
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 (
|
||||||
)
|
)
|
||||||
|
|
||||||
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) {
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue