]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.inline] cmd/compile: parse source files concurrently
authorMatthew Dempsky <mdempsky@google.com>
Wed, 11 Jan 2017 23:48:30 +0000 (15:48 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Fri, 13 Jan 2017 23:07:14 +0000 (23:07 +0000)
Conversion to Nodes still happens sequentially at the moment.

Change-Id: I3407ba0711b8b92e22ece0a06fefaff863c3ccc9
Reviewed-on: https://go-review.googlesource.com/35126
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/gc/lex.go
src/cmd/compile/internal/gc/noder.go
src/cmd/compile/internal/gc/syntax.go

index 5ff55d7c836c9f4dde4eee3a6065b9d138c9341c..c0039fd8804a3c03a80b6b938b63dd1e79cf7db4 100644 (file)
@@ -40,17 +40,15 @@ func plan9quote(s string) string {
        return s
 }
 
-type Pragma syntax.Pragma
-
 const (
        // Func pragmas.
-       Nointerface    Pragma = 1 << iota
-       Noescape              // func parameters don't escape
-       Norace                // func must not have race detector annotations
-       Nosplit               // func should not execute on separate stack
-       Noinline              // func should not be inlined
-       CgoUnsafeArgs         // treat a pointer to one arg as a pointer to them all
-       UintptrEscapes        // pointers converted to uintptr escape
+       Nointerface    syntax.Pragma = 1 << iota
+       Noescape                     // func parameters don't escape
+       Norace                       // func must not have race detector annotations
+       Nosplit                      // func should not execute on separate stack
+       Noinline                     // func should not be inlined
+       CgoUnsafeArgs                // treat a pointer to one arg as a pointer to them all
+       UintptrEscapes               // pointers converted to uintptr escape
 
        // Runtime-only func pragmas.
        // See ../../../../runtime/README.md for detailed descriptions.
@@ -63,7 +61,7 @@ const (
        NotInHeap // values of this type must not be heap allocated
 )
 
-func pragmaValue(verb string) Pragma {
+func pragmaValue(verb string) syntax.Pragma {
        switch verb {
        case "go:nointerface":
                if obj.Fieldtrack_enabled != 0 {
@@ -78,24 +76,12 @@ func pragmaValue(verb string) Pragma {
        case "go:noinline":
                return Noinline
        case "go:systemstack":
-               if !compiling_runtime {
-                       yyerror("//go:systemstack only allowed in runtime")
-               }
                return Systemstack
        case "go:nowritebarrier":
-               if !compiling_runtime {
-                       yyerror("//go:nowritebarrier only allowed in runtime")
-               }
                return Nowritebarrier
        case "go:nowritebarrierrec":
-               if !compiling_runtime {
-                       yyerror("//go:nowritebarrierrec only allowed in runtime")
-               }
                return Nowritebarrierrec | Nowritebarrier // implies Nowritebarrier
        case "go:yeswritebarrierrec":
-               if !compiling_runtime {
-                       yyerror("//go:yeswritebarrierrec only allowed in runtime")
-               }
                return Yeswritebarrierrec
        case "go:cgo_unsafe_args":
                return CgoUnsafeArgs
index 3744da6165a407823a57413b29d64255cf1dfdfe..1207c3f6149a2e902797c501427c9c1874b0e126 100644 (file)
@@ -18,34 +18,47 @@ import (
 
 func parseFiles(filenames []string) uint {
        var lines uint
+       var noders []*noder
+
        for _, filename := range filenames {
-               lines += parseFile(filename)
-               if nsyntaxerrors != 0 {
-                       errorexit()
-               }
-       }
-       return lines
-}
+               p := &noder{err: make(chan syntax.Error)}
+               noders = append(noders, p)
+
+               go func(filename string) {
+                       defer close(p.err)
+                       base := src.NewFileBase(filename, absFilename(filename))
+
+                       f, err := os.Open(filename)
+                       if err != nil {
+                               p.error(syntax.Error{Pos: src.MakePos(base, 0, 0), Msg: err.Error()})
+                               return
+                       }
+                       defer f.Close()
 
-func parseFile(filename string) uint {
-       f, err := os.Open(filename)
-       if err != nil {
-               fmt.Println(err)
-               errorexit()
+                       p.file, _ = syntax.Parse(base, f, p.error, p.pragma, 0) // errors are tracked via p.error
+               }(filename)
        }
-       defer f.Close()
 
-       base := src.NewFileBase(filename, absFilename(filename))
-       var p noder
-       file, _ := syntax.Parse(base, f, p.error, p.pragma, 0) // errors are tracked via p.error
+       for _, p := range noders {
+               for e := range p.err {
+                       yyerrorpos(e.Pos, "%s", e.Msg)
+               }
 
-       p.file(file)
+               p.node()
+               lines += p.file.Lines
+               p.file = nil // release memory
 
-       if nsyntaxerrors == 0 {
+               if nsyntaxerrors != 0 {
+                       errorexit()
+               }
                testdclstack()
        }
 
-       return file.Lines
+       return lines
+}
+
+func yyerrorpos(pos src.Pos, format string, args ...interface{}) {
+       yyerrorl(Ctxt.PosTable.XPos(pos), format, args...)
 }
 
 var pathPrefix string
@@ -54,27 +67,41 @@ func absFilename(name string) string {
        return obj.AbsFile(Ctxt.Pathname, name, pathPrefix)
 }
 
-// noder transforms package syntax's AST into a Nod tree.
+// noder transforms package syntax's AST into a Node tree.
 type noder struct {
-       linknames []src.Pos // tracks //go:linkname positions
+       file       *syntax.File
+       linknames  []linkname
+       pragcgobuf string
+       err        chan syntax.Error
 }
 
-func (p *noder) file(file *syntax.File) {
+// linkname records a //go:linkname directive.
+type linkname struct {
+       pos    src.Pos
+       local  string
+       remote string
+}
+
+func (p *noder) node() {
        block = 1
        iota_ = -1000000
        imported_unsafe = false
 
-       p.lineno(file.PkgName)
-       mkpackage(file.PkgName.Value)
+       p.lineno(p.file.PkgName)
+       mkpackage(p.file.PkgName.Value)
 
-       xtop = append(xtop, p.decls(file.DeclList)...)
+       xtop = append(xtop, p.decls(p.file.DeclList)...)
 
-       if !imported_unsafe {
-               for _, pos := range p.linknames {
-                       p.error(syntax.Error{Pos: pos, Msg: "//go:linkname only allowed in Go files that import \"unsafe\""})
+       for _, n := range p.linknames {
+               if imported_unsafe {
+                       lookup(n.local).Linkname = n.remote
+               } else {
+                       yyerrorpos(n.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")
                }
        }
 
+       pragcgobuf += p.pragcgobuf
+
        // For compatibility with old code only (comparisons w/ toolstash):
        // The old line number tracking simply continued incrementing the
        // virtual line number (lexlineno) and using it also for lineno.
@@ -84,7 +111,7 @@ func (p *noder) file(file *syntax.File) {
        // for fninit and set lineno to NoPos here.
        // TODO(gri) fix this once we switched permanently to the new
        // position information.
-       lineno = MakePos(file.Pos().Base(), uint(file.Lines), 0)
+       lineno = MakePos(p.file.Pos().Base(), uint(p.file.Lines), 0)
 
        clearImports()
 }
@@ -221,7 +248,7 @@ func (p *noder) constDecl(decl *syntax.ConstDecl) []*Node {
 
 func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node {
        name := typedcl0(p.name(decl.Name))
-       name.Name.Param.Pragma = Pragma(decl.Pragma)
+       name.Name.Param.Pragma = decl.Pragma
 
        var typ *Node
        if decl.Type != nil {
@@ -258,7 +285,7 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node {
                }
        }
 
-       pragma := Pragma(fun.Pragma)
+       pragma := fun.Pragma
 
        f.Nbody.Set(body)
        f.Noescape = pragma&Noescape != 0
@@ -1043,8 +1070,7 @@ func (p *noder) lineno(n syntax.Node) {
 }
 
 func (p *noder) error(err error) {
-       e := err.(syntax.Error)
-       yyerrorl(Ctxt.PosTable.XPos(e.Pos), "%s", e.Msg)
+       p.err <- err.(syntax.Error)
 }
 
 func (p *noder) pragma(pos src.Pos, text string) syntax.Pragma {
@@ -1054,26 +1080,27 @@ func (p *noder) pragma(pos src.Pos, text string) syntax.Pragma {
                panic("unreachable")
 
        case strings.HasPrefix(text, "go:linkname "):
-               // Record line number so we can emit an error later if
-               // the file doesn't import package unsafe.
-               p.linknames = append(p.linknames, pos)
-
                f := strings.Fields(text)
                if len(f) != 3 {
                        p.error(syntax.Error{Pos: pos, Msg: "usage: //go:linkname localname linkname"})
                        break
                }
-               lookup(f[1]).Linkname = f[2]
+               p.linknames = append(p.linknames, linkname{pos, f[1], f[2]})
 
        case strings.HasPrefix(text, "go:cgo_"):
-               pragcgobuf += pragcgo(text)
+               p.pragcgobuf += pragcgo(text)
                fallthrough // because of //go:cgo_unsafe_args
        default:
                verb := text
                if i := strings.Index(text, " "); i >= 0 {
                        verb = verb[:i]
                }
-               return syntax.Pragma(pragmaValue(verb))
+               prag := pragmaValue(verb)
+               const runtimePragmas = Systemstack | Nowritebarrier | Nowritebarrierrec | Yeswritebarrierrec
+               if !compiling_runtime && prag&runtimePragmas != 0 {
+                       p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//go:%s only allowed in runtime", verb)})
+               }
+               return prag
        }
 
        return 0
index 8be9f21df22a6efc96990c99c1a743e984f0fc2a..3039aeb4025e803fedb4d5ef56839259b7d2cded 100644 (file)
@@ -6,7 +6,10 @@
 
 package gc
 
-import "cmd/internal/src"
+import (
+       "cmd/compile/internal/syntax"
+       "cmd/internal/src"
+)
 
 // A Node is a single node in the syntax tree.
 // Actually the syntax tree is a syntax DAG, because there is only one
@@ -285,7 +288,7 @@ type Param struct {
        // OTYPE pragmas
        //
        // TODO: Should Func pragmas also be stored on the Name?
-       Pragma Pragma
+       Pragma syntax.Pragma
 }
 
 // Func holds Node fields used only with function-like nodes.
@@ -313,11 +316,11 @@ type Func struct {
        Endlineno src.XPos
        WBPos     src.XPos // position of first write barrier
 
-       Pragma          Pragma // go:xxx function annotations
-       Dupok           bool   // duplicate definitions ok
-       Wrapper         bool   // is method wrapper
-       Needctxt        bool   // function uses context register (has closure variables)
-       ReflectMethod   bool   // function calls reflect.Type.Method or MethodByName
+       Pragma          syntax.Pragma // go:xxx function annotations
+       Dupok           bool          // duplicate definitions ok
+       Wrapper         bool          // is method wrapper
+       Needctxt        bool          // function uses context register (has closure variables)
+       ReflectMethod   bool          // function calls reflect.Type.Method or MethodByName
        IsHiddenClosure bool
        NoFramePointer  bool // Must not use a frame pointer for this function
 }