diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-10-23 02:46:41 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-10-23 02:46:41 +0000 |
commit | a847d2b7b142a86b02296a7766a1bc29f36cf7a8 (patch) | |
tree | 3a518e1527a037ab081f889246b330e2eb42669a /libgo | |
parent | 91f4d9e994869ad099bf02012e4d1371f00ade4d (diff) | |
download | gcc-a847d2b7b142a86b02296a7766a1bc29f36cf7a8.zip gcc-a847d2b7b142a86b02296a7766a1bc29f36cf7a8.tar.gz gcc-a847d2b7b142a86b02296a7766a1bc29f36cf7a8.tar.bz2 |
compiler: export indexed type data, read unexported types lazily
Introduce a new "types" command to the export data to record the
number of types and the size of their export data. It is immediately
followed by new "type" commands that can be indexed. Parse all the
exported types immediately so that we register them, but parse other
type data only as needed.
Reviewed-on: https://go-review.googlesource.com/c/143022
From-SVN: r265409
Diffstat (limited to 'libgo')
-rw-r--r-- | libgo/go/go/internal/gccgoimporter/parser.go | 81 |
1 files changed, 78 insertions, 3 deletions
diff --git a/libgo/go/go/internal/gccgoimporter/parser.go b/libgo/go/go/internal/gccgoimporter/parser.go index cd4e1d9..dc61e4c 100644 --- a/libgo/go/go/internal/gccgoimporter/parser.go +++ b/libgo/go/go/internal/gccgoimporter/parser.go @@ -18,7 +18,7 @@ import ( ) type parser struct { - scanner scanner.Scanner + scanner *scanner.Scanner version string // format version tok rune // current token lit string // literal string; only valid for Ident, Int, String tokens @@ -27,18 +27,24 @@ type parser struct { pkg *types.Package // reference to imported package imports map[string]*types.Package // package path -> package object typeMap map[int]types.Type // type number -> type + typeData []string // unparsed type data initdata InitData // package init priority data } func (p *parser) init(filename string, src io.Reader, imports map[string]*types.Package) { + p.scanner = new(scanner.Scanner) + p.initScanner(filename, src) + p.imports = imports + p.typeMap = make(map[int]types.Type) +} + +func (p *parser) initScanner(filename string, src io.Reader) { p.scanner.Init(src) p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) } p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments p.scanner.Whitespace = 1<<'\t' | 1<<' ' p.scanner.Filename = filename // for good error messages p.next() - p.imports = imports - p.typeMap = make(map[int]types.Type) } type importError struct { @@ -720,6 +726,9 @@ func (p *parser) parseType(pkg *types.Package) (t types.Type) { n := p.parseInt() if p.tok == '>' { + if len(p.typeData) > 0 && p.typeMap[int(n)] == nil { + p.parseSavedType(pkg, int(n)) + } t = p.typeMap[int(n)] } else { t = p.parseTypeDefinition(pkg, int(n)) @@ -739,6 +748,67 @@ func (p *parser) parseType(pkg *types.Package) (t types.Type) { return } +// Types = "types" maxp1 exportedp1 (offset length)* . +func (p *parser) parseTypes(pkg *types.Package) { + maxp1 := p.parseInt() + exportedp1 := p.parseInt() + + type typeOffset struct { + offset int + length int + } + var typeOffsets []typeOffset + + total := 0 + for i := 1; i < int(maxp1); i++ { + len := int(p.parseInt()) + typeOffsets = append(typeOffsets, typeOffset{total, len}) + total += len + } + + // We should now have p.tok pointing to the final newline. + // The next runes from the scanner should be the type data. + + var sb strings.Builder + for sb.Len() < total { + r := p.scanner.Next() + if r == scanner.EOF { + p.error("unexpected EOF") + } + sb.WriteRune(r) + } + allTypeData := sb.String() + + p.typeData = []string{""} // type 0, unused + for _, to := range typeOffsets { + p.typeData = append(p.typeData, allTypeData[to.offset:to.offset+to.length]) + } + + for i := 1; i < int(exportedp1); i++ { + p.parseSavedType(pkg, i) + } +} + +// parseSavedType parses one saved type definition. +func (p *parser) parseSavedType(pkg *types.Package, i int) { + defer func(s *scanner.Scanner, tok rune, lit string) { + p.scanner = s + p.tok = tok + p.lit = lit + }(p.scanner, p.tok, p.lit) + + p.scanner = new(scanner.Scanner) + p.initScanner(p.scanner.Filename, strings.NewReader(p.typeData[i])) + p.expectKeyword("type") + id := int(p.parseInt()) + if id != i { + p.errorf("type ID mismatch: got %d, want %d", id, i) + } + if p.typeMap[i] == nil { + p.typeMap[i] = p.parseTypeDefinition(pkg, i) + } +} + // PackageInit = unquotedString unquotedString int . func (p *parser) parsePackageInit() PackageInit { name := p.parseUnquotedString() @@ -883,6 +953,11 @@ func (p *parser) parseDirective() { p.getPkg(pkgpath, pkgname) p.expectEOL() + case "types": + p.next() + p.parseTypes(p.pkg) + p.expectEOL() + case "func": p.next() fun := p.parseFunc(p.pkg) |