summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2017-01-11 15:48:30 -0800
committerMatthew Dempsky <mdempsky@google.com>2017-01-13 23:07:14 +0000
commitec63158d7104ab6eb3765f7d4ea48744f97d9ff9 (patch)
tree4148adfb7821e413a15518b2d3a7a35e3c821d7a
parentb90aed020dc9bd430c9a451386550d26c2355ea5 (diff)
downloadgo-git-dev.inline.tar.gz
[dev.inline] cmd/compile: parse source files concurrentlydev.inline
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>
-rw-r--r--src/cmd/compile/internal/gc/lex.go30
-rw-r--r--src/cmd/compile/internal/gc/noder.go107
-rw-r--r--src/cmd/compile/internal/gc/syntax.go17
3 files changed, 85 insertions, 69 deletions
diff --git a/src/cmd/compile/internal/gc/lex.go b/src/cmd/compile/internal/gc/lex.go
index 5ff55d7c83..c0039fd880 100644
--- a/src/cmd/compile/internal/gc/lex.go
+++ b/src/cmd/compile/internal/gc/lex.go
@@ -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
diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go
index 3744da6165..1207c3f614 100644
--- a/src/cmd/compile/internal/gc/noder.go
+++ b/src/cmd/compile/internal/gc/noder.go
@@ -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
diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go
index 8be9f21df2..3039aeb402 100644
--- a/src/cmd/compile/internal/gc/syntax.go
+++ b/src/cmd/compile/internal/gc/syntax.go
@@ -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
}