go/gcimporter: update importer to match latest gc export data changes

Adjustments taken from https://golang.org/cl/22580.

Change-Id: Ic88137b410767bd17e3d6142cec2b5a112df56be
Reviewed-on: https://go-review.googlesource.com/22582
Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
Robert Griesemer 2016-04-28 13:47:39 -07:00
parent 14480f21a0
commit c5c16cf68a
2 changed files with 54 additions and 32 deletions

View File

@ -37,14 +37,6 @@ import (
// (suspected) format errors, and whenever a change is made to the format. // (suspected) format errors, and whenever a change is made to the format.
const debugFormat = false // default: false const debugFormat = false // default: false
// If posInfoFormat is set, position information (file, lineno) is written
// for each exported object, including methods and struct fields. Currently
// disabled because it may lead to different object files depending on which
// directory they are built under, which causes tests checking for hermetic
// builds to fail (e.g. TestCgoConsistentResults for cmd/go).
// TODO(gri) determine what to do here.
const posInfoFormat = false
// If trace is set, debugging output is printed to std out. // If trace is set, debugging output is printed to std out.
const trace = false // default: false const trace = false // default: false
@ -60,8 +52,9 @@ type exporter struct {
typIndex map[types.Type]int typIndex map[types.Type]int
// position encoding // position encoding
prevFile string posInfoFormat bool
prevLine int prevFile string
prevLine int
// debugging support // debugging support
written int // bytes written written int // bytes written
@ -72,10 +65,11 @@ type exporter struct {
// If no file set is provided, position info will be missing. // If no file set is provided, position info will be missing.
func BExportData(fset *token.FileSet, pkg *types.Package) []byte { func BExportData(fset *token.FileSet, pkg *types.Package) []byte {
p := exporter{ p := exporter{
fset: fset, fset: fset,
strIndex: map[string]int{"": 0}, // empty string is mapped to 0 strIndex: map[string]int{"": 0}, // empty string is mapped to 0
pkgIndex: make(map[*types.Package]int), pkgIndex: make(map[*types.Package]int),
typIndex: make(map[types.Type]int), typIndex: make(map[types.Type]int),
posInfoFormat: true, // TODO(gri) might become a flag, eventually
} }
// first byte indicates low-level encoding format // first byte indicates low-level encoding format
@ -86,7 +80,7 @@ func BExportData(fset *token.FileSet, pkg *types.Package) []byte {
p.rawByte(format) p.rawByte(format)
// posInfo exported or not? // posInfo exported or not?
p.bool(posInfoFormat) p.bool(p.posInfoFormat)
// --- generic export data --- // --- generic export data ---
@ -211,29 +205,56 @@ func (p *exporter) obj(obj types.Object) {
} }
func (p *exporter) pos(obj types.Object) { func (p *exporter) pos(obj types.Object) {
if !posInfoFormat { if !p.posInfoFormat {
return return
} }
var file string file, line := p.fileLine(obj)
var line int if file == p.prevFile {
// common case: write line delta
// delta == 0 means different file or no line change
delta := line - p.prevLine
p.int(delta)
if delta == 0 {
p.int(-1) // -1 means no file change
}
} else {
// different file
p.int(0)
// Encode filename as length of common prefix with previous
// filename, followed by (possibly empty) suffix. Filenames
// frequently share path prefixes, so this can save a lot
// of space and make export data size less dependent on file
// path length. The suffix is unlikely to be empty because
// file names tend to end in ".go".
n := commonPrefixLen(p.prevFile, file)
p.int(n) // n >= 0
p.string(file[n:]) // write suffix only
p.prevFile = file
p.int(line)
}
p.prevLine = line
}
func (p *exporter) fileLine(obj types.Object) (file string, line int) {
if p.fset != nil { if p.fset != nil {
pos := p.fset.Position(obj.Pos()) pos := p.fset.Position(obj.Pos())
file = pos.Filename file = pos.Filename
line = pos.Line line = pos.Line
} }
return
}
if file == p.prevFile && line != p.prevLine { func commonPrefixLen(a, b string) int {
// common case: write delta-encoded line number if len(a) > len(b) {
p.int(line - p.prevLine) // != 0 a, b = b, a
} else {
// uncommon case: filename changed, or line didn't change
p.int(0)
p.string(file)
p.int(line)
p.prevFile = file
} }
p.prevLine = line // len(a) <= len(b)
i := 0
for i < len(a) && a[i] == b[i] {
i++
}
return i
} }
func (p *exporter) qualifiedName(obj types.Object) { func (p *exporter) qualifiedName(obj types.Object) {

View File

@ -208,13 +208,14 @@ func (p *importer) pos() {
file := p.prevFile file := p.prevFile
line := p.prevLine line := p.prevLine
if delta := p.int(); delta != 0 { if delta := p.int(); delta != 0 {
// line changed
line += delta line += delta
} else { } else if n := p.int(); n >= 0 {
file = p.string() // file changed
line = p.int() file = p.prevFile[:n] + p.string()
p.prevFile = file p.prevFile = file
line = p.int()
} }
p.prevLine = line p.prevLine = line