diff --git a/go/gcimporter15/bimport.go b/go/gcimporter15/bimport.go index 369dfb65..1936a7f6 100644 --- a/go/gcimporter15/bimport.go +++ b/go/gcimporter15/bimport.go @@ -21,14 +21,15 @@ import ( ) type importer struct { - imports map[string]*types.Package - data []byte - path string - buf []byte // for reading strings - version int // export format version + imports map[string]*types.Package + data []byte + importpath string + buf []byte // for reading strings + version int // export format version // object lists strList []string // in order of appearance + pathList []string // in order of appearance pkgList []*types.Package // in order of appearance typList []types.Type // in order of appearance interfaceList []*types.Interface // for delayed completion only @@ -62,13 +63,14 @@ func BImportData(fset *token.FileSet, imports map[string]*types.Package, data [] }() p := importer{ - imports: imports, - data: data, - path: path, - version: -1, // unknown version - strList: []string{""}, // empty string is mapped to 0 - fset: fset, - files: make(map[string]*token.File), + imports: imports, + data: data, + importpath: path, + version: -1, // unknown version + strList: []string{""}, // empty string is mapped to 0 + pathList: []string{""}, // empty string is mapped to 0 + fset: fset, + files: make(map[string]*token.File), } // read version info @@ -102,10 +104,10 @@ func BImportData(fset *token.FileSet, imports map[string]*types.Package, data [] // read version specific flags - extend as necessary switch p.version { - // case 5: + // case 6: // ... // fallthrough - case 4, 3, 2, 1: + case 5, 4, 3, 2, 1: p.debugFormat = p.rawStringln(p.rawByte()) == "debug" p.trackAllTypes = p.int() != 0 p.posInfoFormat = p.int() != 0 @@ -171,12 +173,17 @@ func (p *importer) pkg() *types.Package { // otherwise, i is the package tag (< 0) if i != packageTag { - errorf("unexpected package tag %d", i) + errorf("unexpected package tag %d version %d", i, p.version) } // read package data name := p.string() - path := p.string() + var path string + if p.version >= 5 { + path = p.path() + } else { + path = p.string() + } // we should never see an empty package name if name == "" { @@ -191,7 +198,7 @@ func (p *importer) pkg() *types.Package { // if the package was imported before, use that one; otherwise create a new one if path == "" { - path = p.path + path = p.importpath } pkg := p.imports[path] if pkg == nil { @@ -285,6 +292,8 @@ func (p *importer) obj(tag int) { } } +const deltaNewFile = -64 // see cmd/compile/internal/gc/bexport.go + func (p *importer) pos() token.Pos { if !p.posInfoFormat { return token.NoPos @@ -292,15 +301,26 @@ func (p *importer) pos() token.Pos { file := p.prevFile line := p.prevLine - if delta := p.int(); delta != 0 { - // line changed - line += delta - } else if n := p.int(); n >= 0 { - // file changed - file = p.prevFile[:n] + p.string() - p.prevFile = file - line = p.int() + delta := p.int() + line += delta + if p.version >= 5 { + if delta == deltaNewFile { + if n := p.int(); n >= 0 { + // file changed + file = p.path() + line = n + } + } + } else { + if delta == 0 { + if n := p.int(); n >= 0 { + // file changed + file = p.prevFile[:n] + p.string() + line = p.int() + } + } } + p.prevFile = file p.prevLine = line // Synthesize a token.Pos @@ -778,6 +798,26 @@ func (p *importer) int64() int64 { return p.rawInt64() } +func (p *importer) path() string { + if p.debugFormat { + p.marker('p') + } + // if the path was seen before, i is its index (>= 0) + // (the empty string is at index 0) + i := p.rawInt64() + if i >= 0 { + return p.pathList[i] + } + // otherwise, i is the negative path length (< 0) + a := make([]string, -i) + for n := range a { + a[n] = p.string() + } + s := strings.Join(a, "/") + p.pathList = append(p.pathList, s) + return s +} + func (p *importer) string() string { if p.debugFormat { p.marker('s')