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) {
n = &n1
case gc.ONAME:
if n.Class == gc.PPARAMREF {
var n1 gc.Node
gc.Cgen(n.Name.Heapaddr, &n1)
sclean[nsclean-1] = n1
n = &n1
}
case gc.ONAME, gc.OINDREG:
// nothing
case gc.OINDREG:
break
}
*lo = *n
......
......@@ -518,8 +518,7 @@ func cgen_wb(n, res *Node, wb bool) {
case ODOT,
ODOTPTR,
OINDEX,
OIND,
ONAME: // PPARAMREF var
OIND:
var n1 Node
Igen(n, &n1, res)
......@@ -1545,6 +1544,7 @@ func Agen(n *Node, res *Node) {
switch n.Op {
default:
Dump("bad agen", n)
Fatalf("agen: unknown op %v", Nconv(n, FmtShort|FmtSign))
case OCALLMETH:
......@@ -1571,24 +1571,6 @@ func Agen(n *Node, res *Node) {
Thearch.Gmove(&n1, res)
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:
Cgen(nl, res)
if !nl.NonNil {
......@@ -1646,8 +1628,9 @@ func Igen(n *Node, a *Node, res *Node) {
switch n.Op {
case ONAME:
if n.Class == PPARAMREF {
break
if n.Class == PAUTOHEAP {
Dump("igen", n)
Fatalf("bad name")
}
*a = *n
return
......@@ -1702,11 +1685,11 @@ func Igen(n *Node, a *Node, res *Node) {
a.Type = n.Type
return
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.
case OINDEX:
if n.Left.Type.IsArray() || (n.Left.Type.IsPtr() && n.Left.Left.Type.IsArray()) {
if Isconst(n.Right, CTINT) {
// Compute &a.
......
......@@ -313,7 +313,7 @@ func transformclosure(xfunc *Node) {
} else {
// If v of type T is captured by reference,
// 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).
addr := newname(Lookupf("&%s", v.Sym.Name))
addr.Type = Ptrto(v.Type)
......
......@@ -405,7 +405,6 @@ func Complexgen(n *Node, res *Node) {
ODOTPTR,
OINDEX,
OIND,
ONAME, // PPARAMREF var
OCALLFUNC,
OCALLMETH,
OCALLINTER:
......
......@@ -396,7 +396,8 @@ func oldname(s *Sym) *Node {
c := Nod(ONAME, nil, nil)
c.Sym = s
c.Class = PPARAMREF
c.Class = PAUTOHEAP
c.setIsClosureParam(true)
c.Isddd = n.Isddd
c.Name.Defn = n
c.Addable = false
......
......@@ -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.
if src.Class == PPARAMREF {
if src.isClosureParam() {
if leaks && Debug['m'] != 0 {
Warnl(src.Lineno, "leaking closure reference %v", Nconv(src, FmtShort))
step.describe(src)
......
......@@ -221,7 +221,6 @@ var classnames = []string{
"PAUTOHEAP",
"PPARAM",
"PPARAMOUT",
"PPARAMREF",
"PFUNC",
}
......
......@@ -43,9 +43,8 @@ func addrescapes(n *Node) {
break
}
// A PPARAMREF is a closure reference.
// Mark the thing it refers to as escaping.
if n.Class == PPARAMREF {
// If a closure reference escapes, mark the outer variable as escaping.
if n.isClosureParam() {
addrescapes(n.Name.Defn)
break
}
......@@ -347,7 +346,7 @@ func cgen_discard(nr *Node) {
switch nr.Op {
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)
}
......
......@@ -94,7 +94,6 @@ const (
PAUTOHEAP // local variable or parameter moved to heap
PPARAM // input arguments
PPARAMOUT // output results
PPARAMREF // closure variable reference
PFUNC // global function
PDISCARD // discard during parse of duplicate import
......
......@@ -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
// that has got a pointer inside. Whether it points to
// 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
foreach(n, hascallspred, &hascalls)
if hascalls != 0 {
......
......@@ -516,7 +516,7 @@ func isliteral(n *Node) 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) {
......
......@@ -2723,8 +2723,6 @@ func (s *state) addr(n *Node, bounded bool) *ssa.Value {
// that cse works on their addresses
aux := s.lookupSymbol(n, &ssa.ArgSymbol{Typ: n.Type, Node: n})
return s.newValue1A(ssa.OpAddr, t, aux, s.sp)
case PPARAMREF:
return s.expr(n.Name.Heapaddr)
default:
s.Unimplementedf("variable address class %v not implemented", classnames[n.Class])
return nil
......@@ -2803,8 +2801,7 @@ func (s *state) canSSA(n *Node) bool {
Fatalf("canSSA of PAUTOHEAP %v", n)
}
switch n.Class {
case PEXTERN, PPARAMREF:
// TODO: maybe treat PPARAMREF with an Arg-like op to read from closure?
case PEXTERN:
return false
case PPARAMOUT:
if hasdefer {
......
......@@ -1231,7 +1231,7 @@ func ullmancalc(n *Node) {
switch n.Op {
case OREGISTER, OLITERAL, ONAME:
ul = 1
if n.Class == PPARAMREF || n.Class == PAUTOHEAP {
if n.Class == PAUTOHEAP {
ul++
}
goto out
......
......@@ -78,6 +78,7 @@ type Node struct {
const (
hasBreak = 1 << iota
notLiveAtEnd
isClosureParam
)
func (n *Node) HasBreak() bool {
......@@ -100,6 +101,16 @@ func (n *Node) SetNotLiveAtEnd(b bool) {
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.
func (n *Node) Val() Val {
......@@ -174,9 +185,9 @@ type Param struct {
// ONAME PPARAM
Field *Field // TFIELD in arg struct
// ONAME closure param with PPARAMREF
Outer *Node // outer PPARAMREF in nested closure
Closure *Node // ONAME/PAUTOHEAP <-> ONAME/PPARAMREF
// ONAME closure linkage
Outer *Node
Closure *Node
}
// Func holds Node fields used only with function-like nodes.
......
......@@ -647,9 +647,7 @@ opswitch:
n.Addable = true
case ONAME:
if n.Class != PPARAMREF {
n.Addable = true
}
case OCALLINTER:
usemethod(n)
......@@ -2536,7 +2534,7 @@ func vmatch1(l *Node, r *Node) bool {
switch l.Op {
case ONAME:
switch l.Class {
case PPARAM, PPARAMREF, PAUTO:
case PPARAM, PAUTO:
break
// assignment to non-stack variable
......
......@@ -724,17 +724,8 @@ func split64(n *gc.Node, lo *gc.Node, hi *gc.Node) {
n = &n1
case gc.ONAME:
if n.Class == gc.PPARAMREF {
var n1 gc.Node
gc.Cgen(n.Name.Heapaddr, &n1)
sclean[nsclean-1] = n1
n = &n1
}
case gc.ONAME, gc.OINDREG:
// nothing
case gc.OINDREG:
break
}
*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