Commit 7d0d1222 authored by Robert Griesemer's avatar Robert Griesemer

cmd/compile: move more compiler specifics into compiler specific export section

Instead of indicating with each function signature if it has an inlineable
body, collect all functions in order and export function bodies with function
index in platform-specific section.

Moves this compiler specific information out of the platform-independent
export data section, and removes an int value for all functions w/o body.
Also simplifies the code a bit.

Change-Id: I8b2d7299dbe81f2706be49ecfb9d9f7da85fd854
Reviewed-on: https://go-review.googlesource.com/21939Reviewed-by: 's avatarMatthew Dempsky <mdempsky@google.com>
parent d8e8fc29
......@@ -124,10 +124,11 @@ const exportVersion = "v0"
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
......@@ -322,27 +323,39 @@ func export(out *bufio.Writer, trace bool) int {
// --- 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")
}
......@@ -443,10 +456,9 @@ func (p *exporter) obj(sym *Sym) {
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
......@@ -454,9 +466,9 @@ func (p *exporter) obj(sym *Sym) {
// 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)
......@@ -563,13 +575,12 @@ func (p *exporter) typ(t *Type) {
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 {
......
......@@ -23,9 +23,10 @@ type importer struct {
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
......@@ -107,21 +108,35 @@ func Import(in *bufio.Reader) {
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)
......@@ -131,6 +146,13 @@ func Import(in *bufio.Reader) {
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 {
......@@ -214,47 +236,23 @@ func (p *importer) obj(tag int) {
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)
......@@ -316,23 +314,13 @@ func (p *importer) typ() *Type {
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
......@@ -341,12 +329,6 @@ func (p *importer) typ() *Type {
// 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 {
......
......@@ -186,7 +186,6 @@ func (p *importer) obj(tag int) {
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:
......@@ -269,7 +268,6 @@ func (p *importer) typ(parent *types.Package) types.Type {
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))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment