Commit 20803b84 authored by Russ Cox's avatar Russ Cox

cmd/compile: eliminate PPARAMREF

As in the elimination of PHEAP|PPARAM in CL 23393,
this is something the front end can trivially take care of
and then not bother the back ends with.
It also eliminates some suspect (and only lightly exercised)
code paths in the back ends.

I don't have a smoking gun for this one but it seems
more clearly correct.

Change-Id: I3b3f5e669b3b81d091ff1e2fb13226a6f14c69d5
Reviewed-on: https://go-review.googlesource.com/23431Reviewed-by: default avatarKeith Randall <khr@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
parent b6dc3e6f
...@@ -86,17 +86,8 @@ func split64(n *gc.Node, lo *gc.Node, hi *gc.Node) { ...@@ -86,17 +86,8 @@ func split64(n *gc.Node, lo *gc.Node, hi *gc.Node) {
n = &n1 n = &n1
case gc.ONAME: case gc.ONAME, gc.OINDREG:
if n.Class == gc.PPARAMREF {
var n1 gc.Node
gc.Cgen(n.Name.Heapaddr, &n1)
sclean[nsclean-1] = n1
n = &n1
}
// nothing // nothing
case gc.OINDREG:
break
} }
*lo = *n *lo = *n
......
...@@ -518,8 +518,7 @@ func cgen_wb(n, res *Node, wb bool) { ...@@ -518,8 +518,7 @@ func cgen_wb(n, res *Node, wb bool) {
case ODOT, case ODOT,
ODOTPTR, ODOTPTR,
OINDEX, OINDEX,
OIND, OIND:
ONAME: // PPARAMREF var
var n1 Node var n1 Node
Igen(n, &n1, res) Igen(n, &n1, res)
...@@ -1545,6 +1544,7 @@ func Agen(n *Node, res *Node) { ...@@ -1545,6 +1544,7 @@ func Agen(n *Node, res *Node) {
switch n.Op { switch n.Op {
default: default:
Dump("bad agen", n)
Fatalf("agen: unknown op %v", Nconv(n, FmtShort|FmtSign)) Fatalf("agen: unknown op %v", Nconv(n, FmtShort|FmtSign))
case OCALLMETH: case OCALLMETH:
...@@ -1571,24 +1571,6 @@ func Agen(n *Node, res *Node) { ...@@ -1571,24 +1571,6 @@ func Agen(n *Node, res *Node) {
Thearch.Gmove(&n1, res) Thearch.Gmove(&n1, res)
Regfree(&n1) Regfree(&n1)
case ONAME:
// should only get here with names in this func.
if n.Name.Funcdepth > 0 && n.Name.Funcdepth != Funcdepth {
Dump("bad agen", n)
Fatalf("agen: bad ONAME funcdepth %d != %d", n.Name.Funcdepth, Funcdepth)
}
// should only get here for heap vars or paramref
if n.Class != PPARAMREF {
Dump("bad agen", n)
Fatalf("agen: bad ONAME class %#x", n.Class)
}
Cgen(n.Name.Heapaddr, res)
if n.Xoffset != 0 {
addOffset(res, n.Xoffset)
}
case OIND: case OIND:
Cgen(nl, res) Cgen(nl, res)
if !nl.NonNil { if !nl.NonNil {
...@@ -1646,8 +1628,9 @@ func Igen(n *Node, a *Node, res *Node) { ...@@ -1646,8 +1628,9 @@ func Igen(n *Node, a *Node, res *Node) {
switch n.Op { switch n.Op {
case ONAME: case ONAME:
if n.Class == PPARAMREF { if n.Class == PAUTOHEAP {
break Dump("igen", n)
Fatalf("bad name")
} }
*a = *n *a = *n
return return
...@@ -1702,11 +1685,11 @@ func Igen(n *Node, a *Node, res *Node) { ...@@ -1702,11 +1685,11 @@ func Igen(n *Node, a *Node, res *Node) {
a.Type = n.Type a.Type = n.Type
return return
// Index of fixed-size array by constant can
// put the offset in the addressing.
// Could do the same for slice except that we need
// to use the real index for the bounds checking.
case OINDEX: case OINDEX:
// Index of fixed-size array by constant can
// put the offset in the addressing.
// Could do the same for slice except that we need
// to use the real index for the bounds checking.
if n.Left.Type.IsArray() || (n.Left.Type.IsPtr() && n.Left.Left.Type.IsArray()) { if n.Left.Type.IsArray() || (n.Left.Type.IsPtr() && n.Left.Left.Type.IsArray()) {
if Isconst(n.Right, CTINT) { if Isconst(n.Right, CTINT) {
// Compute &a. // Compute &a.
......
...@@ -313,7 +313,7 @@ func transformclosure(xfunc *Node) { ...@@ -313,7 +313,7 @@ func transformclosure(xfunc *Node) {
} else { } else {
// If v of type T is captured by reference, // If v of type T is captured by reference,
// we introduce function param &v *T // we introduce function param &v *T
// and v remains PPARAMREF with &v heapaddr // and v remains PAUTOHEAP with &v heapaddr
// (accesses will implicitly deref &v). // (accesses will implicitly deref &v).
addr := newname(Lookupf("&%s", v.Sym.Name)) addr := newname(Lookupf("&%s", v.Sym.Name))
addr.Type = Ptrto(v.Type) addr.Type = Ptrto(v.Type)
......
...@@ -405,7 +405,6 @@ func Complexgen(n *Node, res *Node) { ...@@ -405,7 +405,6 @@ func Complexgen(n *Node, res *Node) {
ODOTPTR, ODOTPTR,
OINDEX, OINDEX,
OIND, OIND,
ONAME, // PPARAMREF var
OCALLFUNC, OCALLFUNC,
OCALLMETH, OCALLMETH,
OCALLINTER: OCALLINTER:
......
...@@ -396,7 +396,8 @@ func oldname(s *Sym) *Node { ...@@ -396,7 +396,8 @@ func oldname(s *Sym) *Node {
c := Nod(ONAME, nil, nil) c := Nod(ONAME, nil, nil)
c.Sym = s c.Sym = s
c.Class = PPARAMREF c.Class = PAUTOHEAP
c.setIsClosureParam(true)
c.Isddd = n.Isddd c.Isddd = n.Isddd
c.Name.Defn = n c.Name.Defn = n
c.Addable = false c.Addable = false
......
...@@ -1817,9 +1817,9 @@ func escwalkBody(e *EscState, level Level, dst *Node, src *Node, step *EscStep, ...@@ -1817,9 +1817,9 @@ func escwalkBody(e *EscState, level Level, dst *Node, src *Node, step *EscStep,
} }
} }
// Treat a PPARAMREF closure variable as equivalent to the // Treat a captured closure variable as equivalent to the
// original variable. // original variable.
if src.Class == PPARAMREF { if src.isClosureParam() {
if leaks && Debug['m'] != 0 { if leaks && Debug['m'] != 0 {
Warnl(src.Lineno, "leaking closure reference %v", Nconv(src, FmtShort)) Warnl(src.Lineno, "leaking closure reference %v", Nconv(src, FmtShort))
step.describe(src) step.describe(src)
......
...@@ -221,7 +221,6 @@ var classnames = []string{ ...@@ -221,7 +221,6 @@ var classnames = []string{
"PAUTOHEAP", "PAUTOHEAP",
"PPARAM", "PPARAM",
"PPARAMOUT", "PPARAMOUT",
"PPARAMREF",
"PFUNC", "PFUNC",
} }
......
...@@ -43,9 +43,8 @@ func addrescapes(n *Node) { ...@@ -43,9 +43,8 @@ func addrescapes(n *Node) {
break break
} }
// A PPARAMREF is a closure reference. // If a closure reference escapes, mark the outer variable as escaping.
// Mark the thing it refers to as escaping. if n.isClosureParam() {
if n.Class == PPARAMREF {
addrescapes(n.Name.Defn) addrescapes(n.Name.Defn)
break break
} }
...@@ -347,7 +346,7 @@ func cgen_discard(nr *Node) { ...@@ -347,7 +346,7 @@ func cgen_discard(nr *Node) {
switch nr.Op { switch nr.Op {
case ONAME: case ONAME:
if nr.Class != PAUTOHEAP && nr.Class != PEXTERN && nr.Class != PFUNC && nr.Class != PPARAMREF { if nr.Class != PAUTOHEAP && nr.Class != PEXTERN && nr.Class != PFUNC {
gused(nr) gused(nr)
} }
......
...@@ -94,7 +94,6 @@ const ( ...@@ -94,7 +94,6 @@ const (
PAUTOHEAP // local variable or parameter moved to heap PAUTOHEAP // local variable or parameter moved to heap
PPARAM // input arguments PPARAM // input arguments
PPARAMOUT // output results PPARAMOUT // output results
PPARAMREF // closure variable reference
PFUNC // global function PFUNC // global function
PDISCARD // discard during parse of duplicate import PDISCARD // discard during parse of duplicate import
......
...@@ -495,7 +495,7 @@ func callinstr(np **Node, init *Nodes, wr int, skip int) bool { ...@@ -495,7 +495,7 @@ func callinstr(np **Node, init *Nodes, wr int, skip int) bool {
// e.g. if we've got a local variable/method receiver // e.g. if we've got a local variable/method receiver
// that has got a pointer inside. Whether it points to // that has got a pointer inside. Whether it points to
// the heap or not is impossible to know at compile time // the heap or not is impossible to know at compile time
if class == PAUTOHEAP || class == PPARAMREF || class == PEXTERN || b.Op == OINDEX || b.Op == ODOTPTR || b.Op == OIND { if class == PAUTOHEAP || class == PEXTERN || b.Op == OINDEX || b.Op == ODOTPTR || b.Op == OIND {
hascalls := 0 hascalls := 0
foreach(n, hascallspred, &hascalls) foreach(n, hascallspred, &hascalls)
if hascalls != 0 { if hascalls != 0 {
......
...@@ -516,7 +516,7 @@ func isliteral(n *Node) bool { ...@@ -516,7 +516,7 @@ func isliteral(n *Node) bool {
} }
func (n *Node) isSimpleName() bool { func (n *Node) isSimpleName() bool {
return n.Op == ONAME && n.Addable && n.Class != PAUTOHEAP && n.Class != PPARAMREF return n.Op == ONAME && n.Addable && n.Class != PAUTOHEAP
} }
func litas(l *Node, r *Node, init *Nodes) { func litas(l *Node, r *Node, init *Nodes) {
......
...@@ -2723,8 +2723,6 @@ func (s *state) addr(n *Node, bounded bool) *ssa.Value { ...@@ -2723,8 +2723,6 @@ func (s *state) addr(n *Node, bounded bool) *ssa.Value {
// that cse works on their addresses // that cse works on their addresses
aux := s.lookupSymbol(n, &ssa.ArgSymbol{Typ: n.Type, Node: n}) aux := s.lookupSymbol(n, &ssa.ArgSymbol{Typ: n.Type, Node: n})
return s.newValue1A(ssa.OpAddr, t, aux, s.sp) return s.newValue1A(ssa.OpAddr, t, aux, s.sp)
case PPARAMREF:
return s.expr(n.Name.Heapaddr)
default: default:
s.Unimplementedf("variable address class %v not implemented", classnames[n.Class]) s.Unimplementedf("variable address class %v not implemented", classnames[n.Class])
return nil return nil
...@@ -2803,8 +2801,7 @@ func (s *state) canSSA(n *Node) bool { ...@@ -2803,8 +2801,7 @@ func (s *state) canSSA(n *Node) bool {
Fatalf("canSSA of PAUTOHEAP %v", n) Fatalf("canSSA of PAUTOHEAP %v", n)
} }
switch n.Class { switch n.Class {
case PEXTERN, PPARAMREF: case PEXTERN:
// TODO: maybe treat PPARAMREF with an Arg-like op to read from closure?
return false return false
case PPARAMOUT: case PPARAMOUT:
if hasdefer { if hasdefer {
......
...@@ -1231,7 +1231,7 @@ func ullmancalc(n *Node) { ...@@ -1231,7 +1231,7 @@ func ullmancalc(n *Node) {
switch n.Op { switch n.Op {
case OREGISTER, OLITERAL, ONAME: case OREGISTER, OLITERAL, ONAME:
ul = 1 ul = 1
if n.Class == PPARAMREF || n.Class == PAUTOHEAP { if n.Class == PAUTOHEAP {
ul++ ul++
} }
goto out goto out
......
...@@ -78,6 +78,7 @@ type Node struct { ...@@ -78,6 +78,7 @@ type Node struct {
const ( const (
hasBreak = 1 << iota hasBreak = 1 << iota
notLiveAtEnd notLiveAtEnd
isClosureParam
) )
func (n *Node) HasBreak() bool { func (n *Node) HasBreak() bool {
...@@ -100,6 +101,16 @@ func (n *Node) SetNotLiveAtEnd(b bool) { ...@@ -100,6 +101,16 @@ func (n *Node) SetNotLiveAtEnd(b bool) {
n.flags &^= notLiveAtEnd n.flags &^= notLiveAtEnd
} }
} }
func (n *Node) isClosureParam() bool {
return n.flags&isClosureParam != 0
}
func (n *Node) setIsClosureParam(b bool) {
if b {
n.flags |= isClosureParam
} else {
n.flags &^= isClosureParam
}
}
// Val returns the Val for the node. // Val returns the Val for the node.
func (n *Node) Val() Val { func (n *Node) Val() Val {
...@@ -174,9 +185,9 @@ type Param struct { ...@@ -174,9 +185,9 @@ type Param struct {
// ONAME PPARAM // ONAME PPARAM
Field *Field // TFIELD in arg struct Field *Field // TFIELD in arg struct
// ONAME closure param with PPARAMREF // ONAME closure linkage
Outer *Node // outer PPARAMREF in nested closure Outer *Node
Closure *Node // ONAME/PAUTOHEAP <-> ONAME/PPARAMREF Closure *Node
} }
// Func holds Node fields used only with function-like nodes. // Func holds Node fields used only with function-like nodes.
......
...@@ -647,9 +647,7 @@ opswitch: ...@@ -647,9 +647,7 @@ opswitch:
n.Addable = true n.Addable = true
case ONAME: case ONAME:
if n.Class != PPARAMREF { n.Addable = true
n.Addable = true
}
case OCALLINTER: case OCALLINTER:
usemethod(n) usemethod(n)
...@@ -2536,7 +2534,7 @@ func vmatch1(l *Node, r *Node) bool { ...@@ -2536,7 +2534,7 @@ func vmatch1(l *Node, r *Node) bool {
switch l.Op { switch l.Op {
case ONAME: case ONAME:
switch l.Class { switch l.Class {
case PPARAM, PPARAMREF, PAUTO: case PPARAM, PAUTO:
break break
// assignment to non-stack variable // assignment to non-stack variable
......
...@@ -724,17 +724,8 @@ func split64(n *gc.Node, lo *gc.Node, hi *gc.Node) { ...@@ -724,17 +724,8 @@ func split64(n *gc.Node, lo *gc.Node, hi *gc.Node) {
n = &n1 n = &n1
case gc.ONAME: case gc.ONAME, gc.OINDREG:
if n.Class == gc.PPARAMREF {
var n1 gc.Node
gc.Cgen(n.Name.Heapaddr, &n1)
sclean[nsclean-1] = n1
n = &n1
}
// nothing // nothing
case gc.OINDREG:
break
} }
*lo = *n *lo = *n
......
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