]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: keep variable numbering for inlineable exported functions
authorRobert Griesemer <gri@golang.org>
Fri, 11 Mar 2016 21:40:01 +0000 (13:40 -0800)
committerRobert Griesemer <gri@golang.org>
Mon, 14 Mar 2016 21:56:25 +0000 (21:56 +0000)
Another step towards hooking up exported inlined function bodies.

Change-Id: Ib8094b03ac7970fee0e51b5826b5f8aa232e23fb
Reviewed-on: https://go-review.googlesource.com/20605
Reviewed-by: Alan Donovan <adonovan@google.com>
Run-TryBot: Robert Griesemer <gri@golang.org>

src/cmd/compile/internal/gc/bexport.go
src/cmd/compile/internal/gc/bimport.go
src/go/internal/gcimporter/bimport.go

index 894ce492256d36517c0d424f43f5e12f49612662..3c77747026a3e9e21bfa2ef783539b2335995167 100644 (file)
@@ -276,12 +276,16 @@ func Export(out *obj.Biobuf, trace bool) int {
        }
        for _, sym := range funcs {
                p.string(sym.Name)
-               // The type can only be a signature for functions. However, by always
-               // writing the complete type specification (rather than just a signature)
-               // we keep the option open of sharing common signatures across multiple
-               // functions as a means to further compress the export data.
-               p.typ(sym.Def.Type)
-               p.inlinedBody(sym.Def)
+               sig := sym.Def.Type
+               inlineable := p.isInlineable(sym.Def)
+               p.paramList(sig.Params(), inlineable)
+               p.paramList(sig.Results(), inlineable)
+               index := -1
+               if inlineable {
+                       index = len(p.inlined)
+                       p.inlined = append(p.inlined, sym.Def.Func)
+               }
+               p.int(index)
                if p.trace {
                        p.tracef("\n")
                }
@@ -476,10 +480,17 @@ func (p *exporter) typ(t *Type) {
                                p.tracef("\n")
                        }
                        p.string(m.Sym.Name)
-                       p.paramList(m.Type.Recvs())
-                       p.paramList(m.Type.Params())
-                       p.paramList(m.Type.Results())
-                       p.inlinedBody(m.Type.Nname)
+                       sig := m.Type
+                       inlineable := p.isInlineable(sig.Nname)
+                       p.paramList(sig.Recvs(), inlineable)
+                       p.paramList(sig.Params(), inlineable)
+                       p.paramList(sig.Results(), inlineable)
+                       index := -1
+                       if inlineable {
+                               index = len(p.inlined)
+                               p.inlined = append(p.inlined, sig.Nname.Func)
+                       }
+                       p.int(index)
                }
 
                if p.trace && len(methods) > 0 {
@@ -516,8 +527,8 @@ func (p *exporter) typ(t *Type) {
 
        case TFUNC:
                p.tag(signatureTag)
-               p.paramList(t.Params())
-               p.paramList(t.Results())
+               p.paramList(t.Params(), false)
+               p.paramList(t.Results(), false)
 
        case TINTER:
                p.tag(interfaceTag)
@@ -596,8 +607,8 @@ func (p *exporter) method(m *Field) {
        // TODO(gri) For functions signatures, we use p.typ() to export
        // so we could share the same type with multiple functions. Do
        // the same here, or never try to do this for functions.
-       p.paramList(m.Type.Params())
-       p.paramList(m.Type.Results())
+       p.paramList(m.Type.Params(), false)
+       p.paramList(m.Type.Results(), false)
 }
 
 // fieldName is like qualifiedName but it doesn't record the package
@@ -631,7 +642,7 @@ func basetypeName(t *Type) string {
        return ""
 }
 
-func (p *exporter) paramList(params *Type) {
+func (p *exporter) paramList(params *Type, numbered bool) {
        if params.Etype != TSTRUCT || !params.Funarg {
                Fatalf("exporter: parameter list expected")
        }
@@ -640,16 +651,16 @@ func (p *exporter) paramList(params *Type) {
        // (look at the first parameter only since either all
        // names are present or all are absent)
        n := countfield(params)
-       if n > 0 && parName(params.Field(0)) == "" {
+       if n > 0 && parName(params.Field(0), numbered) == "" {
                n = -n
        }
        p.int(n)
        for q, it := IterFields(params); q != nil; q = it.Next() {
-               p.param(q, n)
+               p.param(q, n, numbered)
        }
 }
 
-func (p *exporter) param(q *Field, n int) {
+func (p *exporter) param(q *Field, n int, numbered bool) {
        t := q.Type
        if q.Isddd {
                // create a fake type to encode ... just for the p.typ call
@@ -659,7 +670,7 @@ func (p *exporter) param(q *Field, n int) {
        }
        p.typ(t)
        if n > 0 {
-               p.string(parName(q))
+               p.string(parName(q, numbered))
        }
        // TODO(gri) This is compiler-specific (escape info).
        // Move into compiler-specific section eventually?
@@ -670,7 +681,7 @@ func (p *exporter) param(q *Field, n int) {
        p.note(q.Note)
 }
 
-func parName(q *Field) string {
+func parName(q *Field, numbered bool) string {
        if q.Sym == nil {
                return ""
        }
@@ -687,9 +698,11 @@ func parName(q *Field) string {
                        Fatalf("exporter: unexpected parameter name: %s", name)
                }
        }
-       // undo gc-internal name specialization
-       if i := strings.Index(name, "·"); i > 0 {
-               name = name[:i] // cut off numbering
+       // undo gc-internal name specialization unless required
+       if !numbered {
+               if i := strings.Index(name, "·"); i > 0 {
+                       name = name[:i] // cut off numbering
+               }
        }
        return name
 }
@@ -775,18 +788,16 @@ func (p *exporter) float(x *Mpflt) {
 // ----------------------------------------------------------------------------
 // Inlined function bodies
 
-func (p *exporter) inlinedBody(n *Node) {
-       index := -1 // index < 0 => not inlined
+func (p *exporter) isInlineable(n *Node) bool {
        if n != nil && n.Func != nil && len(n.Func.Inl.Slice()) != 0 {
                // when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
                // currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
                if Debug['l'] < 2 {
                        typecheckinl(n)
                }
-               index = len(p.inlined) // index >= 0 => inlined
-               p.inlined = append(p.inlined, n.Func)
+               return true
        }
-       p.int(index)
+       return false
 }
 
 func (p *exporter) nodeList(list Nodes) {
index d0997416944ffe886b1999b2294b51bc6ce8fc4c..377d97293244a743f4bd3eafaaa829ff13abc2fb 100644 (file)
@@ -77,16 +77,18 @@ func Import(in *bufio.Reader) {
        for i := p.int(); i > 0; i-- {
                // parser.go:hidden_fndcl
                sym := p.localname()
-               typ := p.typ()
+               params := p.paramList()
+               result := p.paramList()
                inl := p.int()
 
+               sig := functype(nil, params, result)
                importsym(sym, ONAME)
-               if sym.Def != nil && sym.Def.Op == ONAME && !Eqtype(typ, sym.Def.Type) {
-                       Fatalf("importer: inconsistent definition for func %v during import\n\t%v\n\t%v", sym, sym.Def.Type, typ)
+               if sym.Def != nil && sym.Def.Op == ONAME && !Eqtype(sig, sym.Def.Type) {
+                       Fatalf("importer: inconsistent definition for func %v during import\n\t%v\n\t%v", sym, sym.Def.Type, sig)
                }
 
                n := newfuncname(sym)
-               n.Type = typ
+               n.Type = sig
                declare(n, PFUNC)
                funchdr(n)
 
@@ -94,7 +96,7 @@ func Import(in *bufio.Reader) {
                n.Func.Inl.Set(nil)
                if inl >= 0 {
                        if inl != len(p.inlined) {
-                               panic("inlined body list inconsistent")
+                               panic(fmt.Sprintf("inlined body list inconsistent: %d != %d", inl, len(p.inlined)))
                        }
                        p.inlined = append(p.inlined, n.Func)
                }
@@ -113,7 +115,7 @@ func Import(in *bufio.Reader) {
        // read inlined functions bodies
        n := p.int()
        for i := 0; i < n; i++ {
-               body := p.nodeList()
+               body := p.block()
                const hookup = false // TODO(gri) enable and remove this condition
                if hookup {
                        p.inlined[i].Inl.Set(body)
@@ -265,7 +267,7 @@ func (p *importer) typ() *Type {
                        n.Func.Inl.Set(nil)
                        if inl >= 0 {
                                if inl != len(p.inlined) {
-                                       panic("inlined body list inconsistent")
+                                       panic(fmt.Sprintf("inlined body list inconsistent: %d != %d", inl, len(p.inlined)))
                                }
                                p.inlined = append(p.inlined, n.Func)
                        }
@@ -542,6 +544,15 @@ func (p *importer) float(x *Mpflt) {
 // ----------------------------------------------------------------------------
 // Inlined function bodies
 
+func (p *importer) block() []*Node {
+       markdcl()
+       // TODO(gri) populate "scope" with function parameters so they can be found
+       //           inside the function body
+       list := p.nodeList()
+       popdcl()
+       return list
+}
+
 // parser.go:stmt_list
 func (p *importer) nodeList() []*Node {
        c := p.int()
index ad1c4cd02a788e50247588dc7b6250dcaa2ab399..ddace33d0ce1efac6fd3c12fb0a4decfe88ee7b4 100644 (file)
@@ -87,7 +87,9 @@ func BImportData(imports map[string]*types.Package, data []byte, path string) (i
        // read funcs
        for i := p.int(); i > 0; i-- {
                name := p.string()
-               sig := p.typ(nil).(*types.Signature)
+               params, isddd := p.paramList()
+               result, _ := p.paramList()
+               sig := types.NewSignature(nil, params, result, isddd)
                p.int() // read and discard index of inlined function body
                p.declare(types.NewFunc(token.NoPos, pkg, name, sig))
        }