Skip to content

Commit 70a684c

Browse files
committed
go/internal/gccgoimporter: additional V3 export data changes
This patch merges in support for reading the most recent incarnation of V3 export data (initial inline function bodies), from the importer portions of https://golang.org/cl/150061 and https://golang.org/cl/150067. Updates #28961. Change-Id: I34e837acbf48b8fd1a4896a1a977d2241adfb28d Reviewed-on: https://go-review.googlesource.com/c/151557 Run-TryBot: Than McIntosh <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Cherry Zhang <[email protected]>
1 parent 2b58ca6 commit 70a684c

File tree

1 file changed

+66
-6
lines changed

1 file changed

+66
-6
lines changed

Diff for: src/go/internal/gccgoimporter/parser.go

+66-6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"strconv"
1616
"strings"
1717
"text/scanner"
18+
"unicode/utf8"
1819
)
1920

2021
type parser struct {
@@ -41,7 +42,7 @@ func (p *parser) init(filename string, src io.Reader, imports map[string]*types.
4142
func (p *parser) initScanner(filename string, src io.Reader) {
4243
p.scanner.Init(src)
4344
p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
44-
p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
45+
p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats | scanner.ScanStrings
4546
p.scanner.Whitespace = 1<<'\t' | 1<<' '
4647
p.scanner.Filename = filename // for good error messages
4748
p.next()
@@ -281,6 +282,15 @@ func (p *parser) parseConversion(pkg *types.Package) (val constant.Value, typ ty
281282
// ConstValue = string | "false" | "true" | ["-"] (int ["'"] | FloatOrComplex) | Conversion .
282283
// FloatOrComplex = float ["i" | ("+"|"-") float "i"] .
283284
func (p *parser) parseConstValue(pkg *types.Package) (val constant.Value, typ types.Type) {
285+
// v3 changed to $false, $true, $convert, to avoid confusion
286+
// with variable names in inline function bodies.
287+
if p.tok == '$' {
288+
p.next()
289+
if p.tok != scanner.Ident {
290+
p.errorf("expected identifer after '$', got %s (%q)", scanner.TokenString(p.tok), p.lit)
291+
}
292+
}
293+
284294
switch p.tok {
285295
case scanner.String:
286296
str := p.parseString()
@@ -443,7 +453,7 @@ func (p *parser) update(t types.Type, nlist []int) {
443453

444454
// NamedType = TypeName [ "=" ] Type { Method } .
445455
// TypeName = ExportedName .
446-
// Method = "func" "(" Param ")" Name ParamList ResultList ";" .
456+
// Method = "func" "(" Param ")" Name ParamList ResultList [InlineBody] ";" .
447457
func (p *parser) parseNamedType(nlist []int) types.Type {
448458
pkg, name := p.parseExportedName()
449459
scope := pkg.Scope()
@@ -508,6 +518,7 @@ func (p *parser) parseNamedType(nlist []int) types.Type {
508518
name := p.parseName()
509519
params, isVariadic := p.parseParamList(pkg)
510520
results := p.parseResultList(pkg)
521+
p.skipInlineBody()
511522
p.expectEOL()
512523

513524
sig := types.NewSignature(receiver, params, results, isVariadic)
@@ -653,7 +664,11 @@ func (p *parser) parseParamList(pkg *types.Package) (*types.Tuple, bool) {
653664
func (p *parser) parseResultList(pkg *types.Package) *types.Tuple {
654665
switch p.tok {
655666
case '<':
656-
return types.NewTuple(types.NewParam(token.NoPos, pkg, "", p.parseType(pkg)))
667+
p.next()
668+
if p.tok == scanner.Ident && p.lit == "inl" {
669+
return nil
670+
}
671+
return types.NewTuple(types.NewParam(token.NoPos, pkg, "", p.parseTypeAfterAngle(pkg)))
657672

658673
case '(':
659674
params, _ := p.parseParamList(pkg)
@@ -676,7 +691,7 @@ func (p *parser) parseFunctionType(pkg *types.Package, nlist []int) *types.Signa
676691
return t
677692
}
678693

679-
// Func = Name FunctionType .
694+
// Func = Name FunctionType [InlineBody] .
680695
func (p *parser) parseFunc(pkg *types.Package) *types.Func {
681696
name := p.parseName()
682697
if strings.ContainsRune(name, '$') {
@@ -685,7 +700,9 @@ func (p *parser) parseFunc(pkg *types.Package) *types.Func {
685700
p.discardDirectiveWhileParsingTypes(pkg)
686701
return nil
687702
}
688-
return types.NewFunc(token.NoPos, pkg, name, p.parseFunctionType(pkg, nil))
703+
f := types.NewFunc(token.NoPos, pkg, name, p.parseFunctionType(pkg, nil))
704+
p.skipInlineBody()
705+
return f
689706
}
690707

691708
// InterfaceType = "interface" "{" { ("?" Type | Func) ";" } "}" .
@@ -823,8 +840,13 @@ func lookupBuiltinType(typ int) types.Type {
823840
//
824841
// parseType updates the type map to t for all type numbers n.
825842
//
826-
func (p *parser) parseType(pkg *types.Package, n ...int) (t types.Type) {
843+
func (p *parser) parseType(pkg *types.Package, n ...int) types.Type {
827844
p.expect('<')
845+
return p.parseTypeAfterAngle(pkg, n...)
846+
}
847+
848+
// (*parser).Type after reading the "<".
849+
func (p *parser) parseTypeAfterAngle(pkg *types.Package, n ...int) (t types.Type) {
828850
p.expectKeyword("type")
829851

830852
switch p.tok {
@@ -863,6 +885,39 @@ func (p *parser) parseType(pkg *types.Package, n ...int) (t types.Type) {
863885
return
864886
}
865887

888+
// InlineBody = "<inl:NN>" .{NN}
889+
// Reports whether a body was skipped.
890+
func (p *parser) skipInlineBody() {
891+
// We may or may not have seen the '<' already, depending on
892+
// whether the function had a result type or not.
893+
if p.tok == '<' {
894+
p.next()
895+
p.expectKeyword("inl")
896+
} else if p.tok != scanner.Ident || p.lit != "inl" {
897+
return
898+
} else {
899+
p.next()
900+
}
901+
902+
p.expect(':')
903+
want := p.parseInt()
904+
p.expect('>')
905+
906+
defer func(w uint64) {
907+
p.scanner.Whitespace = w
908+
}(p.scanner.Whitespace)
909+
p.scanner.Whitespace = 0
910+
911+
got := 0
912+
for got < want {
913+
r := p.scanner.Next()
914+
if r == scanner.EOF {
915+
p.error("unexpected EOF")
916+
}
917+
got += utf8.RuneLen(r)
918+
}
919+
}
920+
866921
// Types = "types" maxp1 exportedp1 (offset length)* .
867922
func (p *parser) parseTypes(pkg *types.Package) {
868923
maxp1 := p.parseInt()
@@ -882,6 +937,11 @@ func (p *parser) parseTypes(pkg *types.Package) {
882937
total += len
883938
}
884939

940+
defer func(w uint64) {
941+
p.scanner.Whitespace = w
942+
}(p.scanner.Whitespace)
943+
p.scanner.Whitespace = 0
944+
885945
// We should now have p.tok pointing to the final newline.
886946
// The next runes from the scanner should be the type data.
887947

0 commit comments

Comments
 (0)