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
case ODOT,
ODOTPTR,
OINDEX,
- OIND,
- ONAME: // PPARAMREF var
+ OIND:
var n1 Node
Igen(n, &n1, res)
switch n.Op {
default:
+ Dump("bad agen", n)
Fatalf("agen: unknown op %v", Nconv(n, FmtShort|FmtSign))
case OCALLMETH:
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 {
switch n.Op {
case ONAME:
- if n.Class == PPARAMREF {
- break
+ if n.Class == PAUTOHEAP {
+ Dump("igen", n)
+ Fatalf("bad name")
}
*a = *n
return
a.Type = n.Type
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:
+ // 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 Isconst(n.Right, CTINT) {
// Compute &a.
} 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)
ODOTPTR,
OINDEX,
OIND,
- ONAME, // PPARAMREF var
OCALLFUNC,
OCALLMETH,
OCALLINTER:
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
}
}
- // 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)
"PAUTOHEAP",
"PPARAM",
"PPARAMOUT",
- "PPARAMREF",
"PFUNC",
}
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
}
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)
}
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
// 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 {
}
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) {
// 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
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 {
switch n.Op {
case OREGISTER, OLITERAL, ONAME:
ul = 1
- if n.Class == PPARAMREF || n.Class == PAUTOHEAP {
+ if n.Class == PAUTOHEAP {
ul++
}
goto out
const (
hasBreak = 1 << iota
notLiveAtEnd
+ isClosureParam
)
func (n *Node) HasBreak() 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 {
// 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.
n.Addable = true
case ONAME:
- if n.Class != PPARAMREF {
- n.Addable = true
- }
+ n.Addable = true
case OCALLINTER:
usemethod(n)
switch l.Op {
case ONAME:
switch l.Class {
- case PPARAM, PPARAMREF, PAUTO:
+ case PPARAM, PAUTO:
break
// assignment to non-stack variable
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