aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2018-11-26 21:44:20 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-11-26 21:44:20 +0000
commit1e4cc1d4b097f346b4cda611782fe83eda0df18f (patch)
tree2d4e3368b005eaf1e957c8b3437f6e03d7026f42 /libgo
parent50e99db39196a0567e844f35ce1cd0f36d066b8f (diff)
downloadgcc-1e4cc1d4b097f346b4cda611782fe83eda0df18f.zip
gcc-1e4cc1d4b097f346b4cda611782fe83eda0df18f.tar.gz
gcc-1e4cc1d4b097f346b4cda611782fe83eda0df18f.tar.bz2
compiler: initial support for exporting function bodies
Create a framework for putting function bodies in export data. At present only empty functions will be put there, and they will be ignored on import. Later patches will get this to the point of supporting inlining of (some) functions defined in other packages. Reviewed-on: https://go-review.googlesource.com/c/150061 From-SVN: r266490
Diffstat (limited to 'libgo')
-rw-r--r--libgo/go/go/internal/gccgoimporter/parser.go63
1 files changed, 57 insertions, 6 deletions
diff --git a/libgo/go/go/internal/gccgoimporter/parser.go b/libgo/go/go/internal/gccgoimporter/parser.go
index dc61e4c..c23002f 100644
--- a/libgo/go/go/internal/gccgoimporter/parser.go
+++ b/libgo/go/go/internal/gccgoimporter/parser.go
@@ -15,6 +15,7 @@ import (
"strconv"
"strings"
"text/scanner"
+ "unicode/utf8"
)
type parser struct {
@@ -41,7 +42,7 @@ func (p *parser) init(filename string, src io.Reader, imports map[string]*types.
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.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats | scanner.ScanStrings
p.scanner.Whitespace = 1<<'\t' | 1<<' '
p.scanner.Filename = filename // for good error messages
p.next()
@@ -393,7 +394,7 @@ func (p *parser) parseConst(pkg *types.Package) *types.Const {
// NamedType = TypeName [ "=" ] Type { Method } .
// TypeName = ExportedName .
-// Method = "func" "(" Param ")" Name ParamList ResultList ";" .
+// Method = "func" "(" Param ")" Name ParamList ResultList [InlineBody] ";" .
func (p *parser) parseNamedType(n int) types.Type {
pkg, name := p.parseExportedName()
scope := pkg.Scope()
@@ -455,6 +456,7 @@ func (p *parser) parseNamedType(n int) types.Type {
name := p.parseName()
params, isVariadic := p.parseParamList(pkg)
results := p.parseResultList(pkg)
+ p.skipInlineBody()
p.expectEOL()
sig := types.NewSignature(receiver, params, results, isVariadic)
@@ -566,7 +568,11 @@ func (p *parser) parseParamList(pkg *types.Package) (*types.Tuple, bool) {
func (p *parser) parseResultList(pkg *types.Package) *types.Tuple {
switch p.tok {
case '<':
- return types.NewTuple(types.NewParam(token.NoPos, pkg, "", p.parseType(pkg)))
+ p.next()
+ if p.tok == scanner.Ident && p.lit == "inl" {
+ return nil
+ }
+ return types.NewTuple(types.NewParam(token.NoPos, pkg, "", p.parseTypeAfterAngle(pkg)))
case '(':
params, _ := p.parseParamList(pkg)
@@ -584,7 +590,7 @@ func (p *parser) parseFunctionType(pkg *types.Package) *types.Signature {
return types.NewSignature(nil, params, results, isVariadic)
}
-// Func = Name FunctionType .
+// Func = Name FunctionType [InlineBody] .
func (p *parser) parseFunc(pkg *types.Package) *types.Func {
name := p.parseName()
if strings.ContainsRune(name, '$') {
@@ -593,7 +599,9 @@ func (p *parser) parseFunc(pkg *types.Package) *types.Func {
p.discardDirectiveWhileParsingTypes(pkg)
return nil
}
- return types.NewFunc(token.NoPos, pkg, name, p.parseFunctionType(pkg))
+ f := types.NewFunc(token.NoPos, pkg, name, p.parseFunctionType(pkg))
+ p.skipInlineBody()
+ return f
}
// InterfaceType = "interface" "{" { ("?" Type | Func) ";" } "}" .
@@ -717,8 +725,13 @@ func lookupBuiltinType(typ int) types.Type {
}
// Type = "<" "type" ( "-" int | int [ TypeDefinition ] ) ">" .
-func (p *parser) parseType(pkg *types.Package) (t types.Type) {
+func (p *parser) parseType(pkg *types.Package) types.Type {
p.expect('<')
+ return p.parseTypeAfterAngle(pkg)
+}
+
+// (*parser).Type after reading the "<".
+func (p *parser) parseTypeAfterAngle(pkg *types.Package) (t types.Type) {
p.expectKeyword("type")
switch p.tok {
@@ -748,6 +761,39 @@ func (p *parser) parseType(pkg *types.Package) (t types.Type) {
return
}
+// InlineBody = "<inl:NN>" .{NN}
+// Reports whether a body was skipped.
+func (p *parser) skipInlineBody() {
+ // We may or may not have seen the '<' already, depending on
+ // whether the function had a result type or not.
+ if p.tok == '<' {
+ p.next()
+ p.expectKeyword("inl")
+ } else if p.tok != scanner.Ident || p.lit != "inl" {
+ return
+ } else {
+ p.next()
+ }
+
+ p.expect(':')
+ want := p.parseInt()
+ p.expect('>')
+
+ defer func(w uint64) {
+ p.scanner.Whitespace = w
+ }(p.scanner.Whitespace)
+ p.scanner.Whitespace = 0
+
+ got := int64(0)
+ for got < want {
+ r := p.scanner.Next()
+ if r == scanner.EOF {
+ p.error("unexpected EOF")
+ }
+ got += int64(utf8.RuneLen(r))
+ }
+}
+
// Types = "types" maxp1 exportedp1 (offset length)* .
func (p *parser) parseTypes(pkg *types.Package) {
maxp1 := p.parseInt()
@@ -766,6 +812,11 @@ func (p *parser) parseTypes(pkg *types.Package) {
total += len
}
+ defer func(w uint64) {
+ p.scanner.Whitespace = w
+ }(p.scanner.Whitespace)
+ p.scanner.Whitespace = 0
+
// We should now have p.tok pointing to the final newline.
// The next runes from the scanner should be the type data.