const exportInlined = true // default: true
type exporter struct {
- out *bufio.Writer
- pkgIndex map[*Pkg]int
- typIndex map[*Type]int
- inlined []*Func
+ out *bufio.Writer
+
+ pkgIndex map[*Pkg]int // pkg -> pkg index in order of appearance
+ typIndex map[*Type]int // type -> type index in order of appearance
+ funcList []*Func // in order of appearance
// debugging support
written int // bytes written
// --- inlined function bodies ---
if p.trace {
- p.tracef("\n--- inlined function bodies ---\n[ ")
+ p.tracef("\n--- inlined function bodies ---\n")
if p.indent != 0 {
Fatalf("exporter: incorrect indentation")
}
}
- // write inlined function bodies
- p.int(len(p.inlined))
- if p.trace {
- p.tracef("]\n")
- }
- for _, f := range p.inlined {
- if p.trace {
- p.tracef("\n----\nfunc { %s }\n", Hconv(f.Inl, FmtSharp))
- }
- p.stmtList(f.Inl)
- if p.trace {
- p.tracef("\n")
+ // write inlineable function bodies
+ objcount = 0
+ for i, f := range p.funcList {
+ if f != nil {
+ // function has inlineable body:
+ // write index and body
+ if p.trace {
+ p.tracef("\n----\nfunc { %s }\n", Hconv(f.Inl, FmtSharp))
+ }
+ p.int(i)
+ p.stmtList(f.Inl)
+ if p.trace {
+ p.tracef("\n")
+ }
+ objcount++
}
}
+ // indicate end of list
+ if p.trace {
+ p.tracef("\n")
+ }
+ p.tag(-1) // invalid index terminates list
+
+ // for self-verification only (redundant)
+ p.int(objcount)
+
if p.trace {
p.tracef("\n--- end ---\n")
}
p.paramList(sig.Params(), inlineable)
p.paramList(sig.Results(), inlineable)
- index := -1
+ var f *Func
if inlineable {
- index = len(p.inlined)
- p.inlined = append(p.inlined, sym.Def.Func)
+ f = sym.Def.Func
// TODO(gri) re-examine reexportdeplist:
// Because we can trivially export types
// in-place, we don't need to collect types
// With an adjusted reexportdeplist used only
// by the binary exporter, we can also avoid
// the global exportlist.
- reexportdeplist(sym.Def.Func.Inl)
+ reexportdeplist(f.Inl)
}
- p.int(index)
+ p.funcList = append(p.funcList, f)
} else {
// variable
p.tag(varTag)
p.paramList(sig.Params(), inlineable)
p.paramList(sig.Results(), inlineable)
- index := -1
+ var f *Func
if inlineable {
- index = len(p.inlined)
- p.inlined = append(p.inlined, mfn.Func)
+ f = mfn.Func
reexportdeplist(mfn.Func.Inl)
}
- p.int(index)
+ p.funcList = append(p.funcList, f)
}
if p.trace && len(methods) > 0 {
in *bufio.Reader
buf []byte // for reading strings
bufarray [64]byte // initial underlying array for buf, large enough to avoid allocation when compiling std lib
- pkgList []*Pkg
- typList []*Type
- inlined []*Node // functions with pending inlined function bodies
+
+ pkgList []*Pkg // in order of appearance
+ typList []*Type // in order of appearance
+ funcList []*Node // in order of appearance; nil entry means already declared
// debugging support
debugFormat bool
Fatalf("importer: got %d objects; want %d", objcount, count)
}
- // read inlined functions bodies
+ // read inlineable functions bodies
if dclcontext != PEXTERN {
Fatalf("importer: unexpected context %d", dclcontext)
}
- bcount := p.int() // consistency check only
- if bcount != len(p.inlined) {
- Fatalf("importer: expected %d inlined function bodies; got %d", bcount, len(p.inlined))
- }
- for _, f := range p.inlined {
+ objcount = 0
+ for i0 := -1; ; {
+ i := p.int() // index of function with inlineable body
+ if i < 0 {
+ break
+ }
+
+ // don't process the same function twice
+ if i <= i0 {
+ Fatalf("importer: index not increasing: %d <= %d", i, i0)
+ }
+ i0 = i
+
if Funcdepth != 0 {
Fatalf("importer: unexpected Funcdepth %d", Funcdepth)
}
- if f != nil {
- // function body not yet imported - read body and set it
+
+ // Note: In the original code, funchdr and funcbody are called for
+ // all functions (that were not yet imported). Now, we are calling
+ // them only for functions with inlineable bodies. funchdr does
+ // parameter renaming which doesn't matter if we don't have a body.
+
+ if f := p.funcList[i]; f != nil {
+ // function not yet imported - read body and set it
funchdr(f)
f.Func.Inl.Set(p.stmtList())
funcbody(f)
p.stmtList()
dclcontext = PEXTERN
}
+
+ objcount++
+ }
+
+ // self-verification
+ if count := p.int(); count != objcount {
+ Fatalf("importer: got %d functions; want %d", objcount, count)
}
if dclcontext != PEXTERN {
sym := p.qualifiedName()
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 {
- if Eqtype(sig, sym.Def.Type) {
- // function was imported before (via another import)
- dclcontext = PDISCARD // since we skip funchdr below
- } else {
+ // function was imported before (via another import)
+ if !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)
}
- }
-
- var n *Node
- if dclcontext != PDISCARD {
- n = newfuncname(sym)
- n.Type = sig
- declare(n, PFUNC)
- if inl < 0 {
- funchdr(n)
- }
- }
-
- if inl >= 0 {
- // function has inlined body - collect for later
- if inl != len(p.inlined) {
- Fatalf("importer: inlined index = %d; want %d", inl, len(p.inlined))
- }
- p.inlined = append(p.inlined, n)
- }
-
- // parser.go:hidden_import
- if dclcontext == PDISCARD {
- dclcontext = PEXTERN // since we skip the funcbody below
+ p.funcList = append(p.funcList, nil)
break
}
- if inl < 0 {
- funcbody(n)
- }
- importlist = append(importlist, n) // TODO(gri) may only be needed for inlineable functions
+ n := newfuncname(sym)
+ n.Type = sig
+ declare(n, PFUNC)
+ p.funcList = append(p.funcList, n)
+ importlist = append(importlist, n)
if Debug['E'] > 0 {
fmt.Printf("import [%q] func %v \n", importpkg.Path, n)
recv := p.paramList() // TODO(gri) do we need a full param list for the receiver?
params := p.paramList()
result := p.paramList()
- inl := p.int()
n := methodname1(newname(sym), recv[0].Right)
n.Type = functype(recv[0], params, result)
checkwidth(n.Type)
addmethod(sym, n.Type, tsym.Pkg, false, false)
- if inl < 0 {
- funchdr(n)
- }
-
- if inl >= 0 {
- // method has inlined body - collect for later
- if inl != len(p.inlined) {
- Fatalf("importer: inlined index = %d; want %d", inl, len(p.inlined))
- }
- p.inlined = append(p.inlined, n)
- }
+ p.funcList = append(p.funcList, n)
+ importlist = append(importlist, n)
// (comment from parser.go)
// inl.C's inlnode in on a dotmeth node expects to find the inlineable body as
// this back link here we avoid special casing there.
n.Type.SetNname(n)
- // parser.go:hidden_import
- if inl < 0 {
- funcbody(n)
- }
- importlist = append(importlist, n) // TODO(gri) may only be needed for inlineable functions
-
if Debug['E'] > 0 {
fmt.Printf("import [%q] meth %v \n", importpkg.Path, n)
if Debug['m'] > 2 && len(n.Func.Inl.Slice()) != 0 {
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))
default:
recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver?
params, isddd := p.paramList()
result, _ := p.paramList()
- p.int() // read and discard index of inlined function body
sig := types.NewSignature(recv.At(0), params, result, isddd)
t0.AddMethod(types.NewFunc(token.NoPos, parent, name, sig))