fn.Nname.Ntype = xtype
fn.Nname.Defn = fn
- clo := p.nod(expr, ir.OCLOSURE, nil, nil)
- clo.SetFunc(fn)
+ clo := ir.NewClosureExpr(p.pos(expr), fn)
fn.ClosureType = ntype
fn.OClosure = clo
offset := int64(Widthptr)
for _, v := range fn.ClosureVars {
// cv refers to the field inside of closure OSTRUCTLIT.
- cv := ir.Nod(ir.OCLOSUREVAR, nil, nil)
-
- cv.SetType(v.Type())
+ typ := v.Type()
if !v.Byval() {
- cv.SetType(types.NewPtr(v.Type()))
+ typ = types.NewPtr(typ)
}
- offset = Rnd(offset, int64(cv.Type().Align))
- cv.SetOffset(offset)
- offset += cv.Type().Width
+ offset = Rnd(offset, int64(typ.Align))
+ cr := ir.NewClosureRead(typ, offset)
+ offset += typ.Width
if v.Byval() && v.Type().Width <= int64(2*Widthptr) {
// If it is a small variable captured by value, downgrade it to PAUTO.
v.SetClass(ir.PAUTO)
fn.Dcl = append(fn.Dcl, v)
- body = append(body, ir.Nod(ir.OAS, v, cv))
+ body = append(body, ir.Nod(ir.OAS, v, cr))
} else {
// Declare variable holding addresses taken from closure
// and initialize in entry prologue.
addr.Curfn = fn
fn.Dcl = append(fn.Dcl, addr)
v.Heapaddr = addr
+ var src ir.Node = cr
if v.Byval() {
- cv = ir.Nod(ir.OADDR, cv, nil)
+ src = ir.Nod(ir.OADDR, cr, nil)
}
- body = append(body, ir.Nod(ir.OAS, addr, cv))
+ body = append(body, ir.Nod(ir.OAS, addr, src))
}
}
tfn.Type().SetPkg(t0.Pkg())
// Declare and initialize variable holding receiver.
-
- cv := ir.Nod(ir.OCLOSUREVAR, nil, nil)
- cv.SetType(rcvrtype)
- cv.SetOffset(Rnd(int64(Widthptr), int64(cv.Type().Align)))
-
+ cr := ir.NewClosureRead(rcvrtype, Rnd(int64(Widthptr), int64(rcvrtype.Align)))
ptr := NewName(lookup(".this"))
declare(ptr, ir.PAUTO)
ptr.SetUsed(true)
var body []ir.Node
if rcvrtype.IsPtr() || rcvrtype.IsInterface() {
ptr.SetType(rcvrtype)
- body = append(body, ir.Nod(ir.OAS, ptr, cv))
+ body = append(body, ir.Nod(ir.OAS, ptr, cr))
} else {
ptr.SetType(types.NewPtr(rcvrtype))
- body = append(body, ir.Nod(ir.OAS, ptr, ir.Nod(ir.OADDR, cv, nil)))
+ body = append(body, ir.Nod(ir.OAS, ptr, ir.Nod(ir.OADDR, cr, nil)))
}
call := ir.Nod(ir.OCALL, nodSym(ir.OXDOT, ptr, meth), nil)
default:
base.Fatalf("unexpected expr: %v", n)
- case ir.OLITERAL, ir.ONIL, ir.OGETG, ir.OCLOSUREVAR, ir.OTYPE, ir.OMETHEXPR:
+ case ir.OLITERAL, ir.ONIL, ir.OGETG, ir.OCLOSUREREAD, ir.OTYPE, ir.OMETHEXPR:
// nop
case ir.ONAME:
// We're ignoring things like division by zero, index out of range,
// and nil pointer dereference here.
switch n.Op() {
- case ir.ONAME, ir.OCLOSUREVAR, ir.OLITERAL, ir.ONIL:
+ case ir.ONAME, ir.OCLOSUREREAD, ir.OLITERAL, ir.ONIL:
return false
// Left+Right group.
// Handle captured variables when inlining closures.
if c := fn.OClosure; c != nil {
- for _, v := range c.Func().ClosureVars {
+ for _, v := range fn.ClosureVars {
if v.Op() == ir.OXXX {
continue
}
// NB: if we enabled inlining of functions containing OCLOSURE or refined
// the reassigned check via some sort of copy propagation this would most
// likely need to be changed to a loop to walk up to the correct Param
- if o == nil || (o.Curfn != Curfn && o.Curfn.OClosure != Curfn) {
+ if o == nil || o.Curfn != Curfn {
base.Fatalf("%v: unresolvable capture %v %v\n", ir.Line(n), fn, v)
}
}
addr := s.addr(n)
return s.load(n.Type(), addr)
- case ir.OCLOSUREVAR:
+ case ir.OCLOSUREREAD:
addr := s.addr(n)
return s.load(n.Type(), addr)
case ir.ONIL:
case ir.ODOTPTR:
p := s.exprPtr(n.Left(), n.Bounded(), n.Pos())
return s.newValue1I(ssa.OpOffPtr, t, n.Offset(), p)
- case ir.OCLOSUREVAR:
+ case ir.OCLOSUREREAD:
return s.newValue1I(ssa.OpOffPtr, t, n.Offset(),
s.entryNewValue0(ssa.OpGetClosurePtr, s.f.Config.Types.BytePtr))
case ir.OCONVNOP:
n.SetType(types.NewPtr(t.Elem()))
}
- case ir.OCLOSUREVAR:
+ case ir.OCLOSUREREAD:
ok |= ctxExpr
case ir.OCFUNC:
return false
}
fallthrough
- case ir.ODEREF, ir.ODOTPTR, ir.OCLOSUREVAR:
+ case ir.ODEREF, ir.ODOTPTR, ir.OCLOSUREREAD:
return true
case ir.ODOT:
}
switch l.Op() {
- case ir.ONAME, ir.OCLOSUREVAR:
+ case ir.ONAME, ir.OCLOSUREREAD:
return l == r
case ir.ODOT, ir.ODOTPTR:
case ir.ORECOVER:
n = mkcall("gorecover", n.Type(), init, ir.Nod(ir.OADDR, nodfp, nil))
- case ir.OCLOSUREVAR, ir.OCFUNC:
+ case ir.OCLOSUREREAD, ir.OCFUNC:
case ir.OCALLINTER, ir.OCALLFUNC, ir.OCALLMETH:
if n.Op() == ir.OCALLINTER {
import (
"cmd/compile/internal/types"
+ "cmd/internal/src"
+ "fmt"
)
// A miniStmt is a miniNode with extra fields common to expressions.
func (n *miniExpr) Init() Nodes { return n.init }
func (n *miniExpr) PtrInit() *Nodes { return &n.init }
func (n *miniExpr) SetInit(x Nodes) { n.init = x }
+
+// A ClosureExpr is a function literal expression.
+type ClosureExpr struct {
+ miniExpr
+ fn *Func
+}
+
+func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr {
+ n := &ClosureExpr{fn: fn}
+ n.op = OCLOSURE
+ n.pos = pos
+ return n
+}
+
+func (n *ClosureExpr) String() string { return fmt.Sprint(n) }
+func (n *ClosureExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *ClosureExpr) RawCopy() Node { c := *n; return &c }
+func (n *ClosureExpr) Func() *Func { return n.fn }
+
+// A ClosureRead denotes reading a variable stored within a closure struct.
+type ClosureRead struct {
+ miniExpr
+ offset int64
+}
+
+func NewClosureRead(typ *types.Type, offset int64) *ClosureRead {
+ n := &ClosureRead{offset: offset}
+ n.typ = typ
+ n.op = OCLOSUREREAD
+ return n
+}
+
+func (n *ClosureRead) String() string { return fmt.Sprint(n) }
+func (n *ClosureRead) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *ClosureRead) RawCopy() Node { c := *n; return &c }
+func (n *ClosureRead) Type() *types.Type { return n.typ }
+func (n *ClosureRead) Offset() int64 { return n.offset }
body Nodes
iota int64
- Nname *Name // ONAME node
- OClosure Node // OCLOSURE node
+ Nname *Name // ONAME node
+ OClosure *ClosureExpr // OCLOSURE node
Shortname *types.Sym
OTARRAY // []int, [8]int, [N]int or [...]int
// misc
- ODDD // func f(args ...int) or f(l...) or var a = [...]int{0, 1, 2}.
- OINLCALL // intermediary representation of an inlined call.
- OEFACE // itable and data words of an empty-interface value.
- OITAB // itable word of an interface value.
- OIDATA // data word of an interface value in Left
- OSPTR // base pointer of a slice or string.
- OCLOSUREVAR // variable reference at beginning of closure function
- OCFUNC // reference to c function pointer (not go func value)
- OCHECKNIL // emit code to ensure pointer/interface not nil
- OVARDEF // variable is about to be fully initialized
- OVARKILL // variable is dead
- OVARLIVE // variable is alive
- ORESULT // result of a function call; Xoffset is stack offset
- OINLMARK // start of an inlined body, with file/line of caller. Xoffset is an index into the inline tree.
+ ODDD // func f(args ...int) or f(l...) or var a = [...]int{0, 1, 2}.
+ OINLCALL // intermediary representation of an inlined call.
+ OEFACE // itable and data words of an empty-interface value.
+ OITAB // itable word of an interface value.
+ OIDATA // data word of an interface value in Left
+ OSPTR // base pointer of a slice or string.
+ OCLOSUREREAD // read from inside closure struct at beginning of closure function
+ OCFUNC // reference to c function pointer (not go func value)
+ OCHECKNIL // emit code to ensure pointer/interface not nil
+ OVARDEF // variable is about to be fully initialized
+ OVARKILL // variable is dead
+ OVARLIVE // variable is alive
+ ORESULT // result of a function call; Xoffset is stack offset
+ OINLMARK // start of an inlined body, with file/line of caller. Xoffset is an index into the inline tree.
// arch-specific opcodes
ORETJMP // return to other function
OCFUNC: true,
OCHECKNIL: true,
OCLOSE: true,
- OCLOSURE: true,
- OCLOSUREVAR: true,
OCOMPLEX: true,
OCOMPLIT: true,
OCONV: true,
_ = x[OITAB-141]
_ = x[OIDATA-142]
_ = x[OSPTR-143]
- _ = x[OCLOSUREVAR-144]
+ _ = x[OCLOSUREREAD-144]
_ = x[OCFUNC-145]
_ = x[OCHECKNIL-146]
_ = x[OVARDEF-147]
_ = x[OEND-154]
}
-const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNEWOBJNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFMETHEXPRBLOCKBREAKCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKRETJMPGETGEND"
+const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNEWOBJNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFMETHEXPRBLOCKBREAKCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDINLCALLEFACEITABIDATASPTRCLOSUREREADCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKRETJMPGETGEND"
-var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 126, 129, 139, 146, 153, 160, 164, 168, 176, 184, 193, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 280, 284, 287, 294, 302, 310, 317, 323, 326, 332, 339, 347, 351, 358, 366, 368, 370, 372, 374, 376, 378, 383, 388, 396, 399, 408, 411, 415, 423, 430, 439, 452, 455, 458, 461, 464, 467, 470, 476, 479, 485, 488, 494, 498, 501, 505, 510, 515, 521, 526, 530, 535, 543, 551, 557, 566, 577, 584, 588, 595, 602, 610, 614, 618, 622, 629, 636, 644, 650, 658, 663, 668, 672, 680, 685, 690, 694, 697, 705, 709, 711, 716, 718, 723, 729, 735, 741, 747, 752, 756, 763, 769, 774, 780, 783, 790, 795, 799, 804, 808, 818, 823, 831, 837, 844, 851, 857, 864, 870, 874, 877}
+var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 126, 129, 139, 146, 153, 160, 164, 168, 176, 184, 193, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 280, 284, 287, 294, 302, 310, 317, 323, 326, 332, 339, 347, 351, 358, 366, 368, 370, 372, 374, 376, 378, 383, 388, 396, 399, 408, 411, 415, 423, 430, 439, 452, 455, 458, 461, 464, 467, 470, 476, 479, 485, 488, 494, 498, 501, 505, 510, 515, 521, 526, 530, 535, 543, 551, 557, 566, 577, 584, 588, 595, 602, 610, 614, 618, 622, 629, 636, 644, 650, 658, 663, 668, 672, 680, 685, 690, 694, 697, 705, 709, 711, 716, 718, 723, 729, 735, 741, 747, 752, 756, 763, 769, 774, 780, 783, 790, 795, 799, 804, 808, 819, 824, 832, 838, 845, 852, 858, 865, 871, 875, 878}
func (i Op) String() string {
if i >= Op(len(_Op_index)-1) {
_32bit uintptr // size on 32bit platforms
_64bit uintptr // size on 64bit platforms
}{
- {Func{}, 172, 296},
+ {Func{}, 168, 288},
{Name{}, 128, 224},
{node{}, 84, 144},
}