}
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")
}
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 {
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)
// 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
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")
}
// (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
}
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?
p.note(q.Note)
}
-func parName(q *Field) string {
+func parName(q *Field, numbered bool) string {
if q.Sym == nil {
return ""
}
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
}
// ----------------------------------------------------------------------------
// 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) {
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)
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)
}
// 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)
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)
}
// ----------------------------------------------------------------------------
// 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()