aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/typecheck/iimport.go
diff options
context:
space:
mode:
authorDan Scales <danscales@google.com>2020-12-01 14:48:03 -0800
committerDan Scales <danscales@google.com>2021-01-20 22:53:32 +0000
commit1760d736f61265b3c78a6a48f2e1904341806643 (patch)
treefbf7575c435f30ae41e97589adeca569cbe0225e /src/cmd/compile/internal/typecheck/iimport.go
parent92cb157cf3aa51d28e441dbb2b671795f22140f8 (diff)
downloadgo-1760d736f61265b3c78a6a48f2e1904341806643.tar.gz
go-1760d736f61265b3c78a6a48f2e1904341806643.zip
[dev.regabi] cmd/compile: exporting, importing, and inlining functions with OCLOSURE
I have exporting, importing, and inlining of functions with closures working in all cases (issue #28727). all.bash runs successfully without errors. Approach: - Write out the Func type, Dcls, ClosureVars, and Body when exporting an OCLOSURE. - When importing an OCLOSURE, read in the type, dcls, closure vars, and body, and then do roughly equivalent code to (*noder).funcLit - During inlining of a closure within inlined function, create new nodes for all params and local variables (including closure variables), so they can have a new Curfn and some other field values. Must substitute not only on the Nbody of the closure, but also the Type, Cvars, and Dcl fields. Fixes #28727 Change-Id: I4da1e2567c3fa31a5121afbe82dc4e5ee32b3170 Reviewed-on: https://go-review.googlesource.com/c/go/+/283112 Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com> Trust: Dan Scales <danscales@google.com>
Diffstat (limited to 'src/cmd/compile/internal/typecheck/iimport.go')
-rw-r--r--src/cmd/compile/internal/typecheck/iimport.go85
1 files changed, 66 insertions, 19 deletions
diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go
index c2610229ec..f2682257f3 100644
--- a/src/cmd/compile/internal/typecheck/iimport.go
+++ b/src/cmd/compile/internal/typecheck/iimport.go
@@ -265,6 +265,9 @@ type importReader struct {
// curfn is the current function we're importing into.
curfn *ir.Func
+ // Slice of all dcls for function, including any interior closures
+ allDcls []*ir.Name
+ allClosureVars []*ir.Name
}
func (p *iimporter) newReader(off uint64, pkg *types.Pkg) *importReader {
@@ -721,6 +724,7 @@ func (r *importReader) doInline(fn *ir.Func) {
base.Fatalf("%v already has inline body", fn)
}
+ //fmt.Printf("Importing %v\n", n)
r.funcBody(fn)
importlist = append(importlist, fn)
@@ -754,6 +758,24 @@ func (r *importReader) funcBody(fn *ir.Func) {
r.curfn = fn
// Import local declarations.
+ fn.Inl.Dcl = r.readFuncDcls(fn)
+
+ // Import function body.
+ body := r.stmtList()
+ if body == nil {
+ // Make sure empty body is not interpreted as
+ // no inlineable body (see also parser.fnbody)
+ // (not doing so can cause significant performance
+ // degradation due to unnecessary calls to empty
+ // functions).
+ body = []ir.Node{}
+ }
+ fn.Inl.Body = body
+
+ r.curfn = outerfn
+}
+
+func (r *importReader) readNames(fn *ir.Func) []*ir.Name {
dcls := make([]*ir.Name, r.int64())
for i := range dcls {
n := ir.NewDeclNameAt(r.pos(), ir.ONAME, r.localIdent())
@@ -762,7 +784,12 @@ func (r *importReader) funcBody(fn *ir.Func) {
n.SetType(r.typ())
dcls[i] = n
}
- fn.Inl.Dcl = dcls
+ r.allDcls = append(r.allDcls, dcls...)
+ return dcls
+}
+
+func (r *importReader) readFuncDcls(fn *ir.Func) []*ir.Name {
+ dcls := r.readNames(fn)
// Fixup parameter classes and associate with their
// signature's type fields.
@@ -787,28 +814,18 @@ func (r *importReader) funcBody(fn *ir.Func) {
for _, f := range typ.Results().FieldSlice() {
fix(f, ir.PPARAMOUT)
}
-
- // Import function body.
- body := r.stmtList()
- if body == nil {
- // Make sure empty body is not interpreted as
- // no inlineable body (see also parser.fnbody)
- // (not doing so can cause significant performance
- // degradation due to unnecessary calls to empty
- // functions).
- body = []ir.Node{}
- }
- fn.Inl.Body = body
-
- r.curfn = outerfn
+ return dcls
}
func (r *importReader) localName() *ir.Name {
i := r.int64()
- if i < 0 {
+ if i == -1 {
return ir.BlankNode.(*ir.Name)
}
- return r.curfn.Inl.Dcl[i]
+ if i < 0 {
+ return r.allClosureVars[-i-2]
+ }
+ return r.allDcls[i]
}
func (r *importReader) stmtList() []ir.Node {
@@ -924,8 +941,38 @@ func (r *importReader) node() ir.Node {
// case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
// unreachable - should have been resolved by typechecking
- // case OCLOSURE:
- // unimplemented
+ case ir.OCLOSURE:
+ //println("Importing CLOSURE")
+ pos := r.pos()
+ typ := r.signature(nil)
+
+ // All the remaining code below is similar to (*noder).funcLit(), but
+ // with Dcls and ClosureVars lists already set up
+ fn := ir.NewFunc(pos)
+ fn.SetIsHiddenClosure(true)
+ fn.Nname = ir.NewNameAt(pos, ir.BlankNode.Sym())
+ fn.Nname.Func = fn
+ fn.Nname.Ntype = ir.TypeNode(typ)
+ fn.Nname.Defn = fn
+ fn.Nname.SetType(typ)
+
+ cvars := make([]*ir.Name, r.int64())
+ for i := range cvars {
+ cvars[i] = ir.CaptureName(r.pos(), fn, r.localName().Canonical())
+ }
+ fn.ClosureVars = cvars
+ r.allClosureVars = append(r.allClosureVars, cvars...)
+
+ fn.Dcl = r.readFuncDcls(fn)
+ body := r.stmtList()
+ ir.FinishCaptureNames(pos, r.curfn, fn)
+
+ clo := ir.NewClosureExpr(pos, fn)
+ fn.OClosure = clo
+
+ fn.Body = body
+
+ return clo
// case OPTRLIT:
// unreachable - mapped to case OADDR below by exporter