mirror of
https://github.com/golang/go
synced 2024-11-19 13:14:42 -07:00
[dev.inline] cmd/compile: parse source files concurrently
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>
This commit is contained in:
parent
b90aed020d
commit
ec63158d71
@ -40,17 +40,15 @@ func plan9quote(s string) string {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
type Pragma syntax.Pragma
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Func pragmas.
|
// Func pragmas.
|
||||||
Nointerface Pragma = 1 << iota
|
Nointerface syntax.Pragma = 1 << iota
|
||||||
Noescape // func parameters don't escape
|
Noescape // func parameters don't escape
|
||||||
Norace // func must not have race detector annotations
|
Norace // func must not have race detector annotations
|
||||||
Nosplit // func should not execute on separate stack
|
Nosplit // func should not execute on separate stack
|
||||||
Noinline // func should not be inlined
|
Noinline // func should not be inlined
|
||||||
CgoUnsafeArgs // treat a pointer to one arg as a pointer to them all
|
CgoUnsafeArgs // treat a pointer to one arg as a pointer to them all
|
||||||
UintptrEscapes // pointers converted to uintptr escape
|
UintptrEscapes // pointers converted to uintptr escape
|
||||||
|
|
||||||
// Runtime-only func pragmas.
|
// Runtime-only func pragmas.
|
||||||
// See ../../../../runtime/README.md for detailed descriptions.
|
// See ../../../../runtime/README.md for detailed descriptions.
|
||||||
@ -63,7 +61,7 @@ const (
|
|||||||
NotInHeap // values of this type must not be heap allocated
|
NotInHeap // values of this type must not be heap allocated
|
||||||
)
|
)
|
||||||
|
|
||||||
func pragmaValue(verb string) Pragma {
|
func pragmaValue(verb string) syntax.Pragma {
|
||||||
switch verb {
|
switch verb {
|
||||||
case "go:nointerface":
|
case "go:nointerface":
|
||||||
if obj.Fieldtrack_enabled != 0 {
|
if obj.Fieldtrack_enabled != 0 {
|
||||||
@ -78,24 +76,12 @@ func pragmaValue(verb string) Pragma {
|
|||||||
case "go:noinline":
|
case "go:noinline":
|
||||||
return Noinline
|
return Noinline
|
||||||
case "go:systemstack":
|
case "go:systemstack":
|
||||||
if !compiling_runtime {
|
|
||||||
yyerror("//go:systemstack only allowed in runtime")
|
|
||||||
}
|
|
||||||
return Systemstack
|
return Systemstack
|
||||||
case "go:nowritebarrier":
|
case "go:nowritebarrier":
|
||||||
if !compiling_runtime {
|
|
||||||
yyerror("//go:nowritebarrier only allowed in runtime")
|
|
||||||
}
|
|
||||||
return Nowritebarrier
|
return Nowritebarrier
|
||||||
case "go:nowritebarrierrec":
|
case "go:nowritebarrierrec":
|
||||||
if !compiling_runtime {
|
|
||||||
yyerror("//go:nowritebarrierrec only allowed in runtime")
|
|
||||||
}
|
|
||||||
return Nowritebarrierrec | Nowritebarrier // implies Nowritebarrier
|
return Nowritebarrierrec | Nowritebarrier // implies Nowritebarrier
|
||||||
case "go:yeswritebarrierrec":
|
case "go:yeswritebarrierrec":
|
||||||
if !compiling_runtime {
|
|
||||||
yyerror("//go:yeswritebarrierrec only allowed in runtime")
|
|
||||||
}
|
|
||||||
return Yeswritebarrierrec
|
return Yeswritebarrierrec
|
||||||
case "go:cgo_unsafe_args":
|
case "go:cgo_unsafe_args":
|
||||||
return CgoUnsafeArgs
|
return CgoUnsafeArgs
|
||||||
|
@ -18,34 +18,47 @@ import (
|
|||||||
|
|
||||||
func parseFiles(filenames []string) uint {
|
func parseFiles(filenames []string) uint {
|
||||||
var lines uint
|
var lines uint
|
||||||
|
var noders []*noder
|
||||||
|
|
||||||
for _, filename := range filenames {
|
for _, filename := range filenames {
|
||||||
lines += parseFile(filename)
|
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()
|
||||||
|
|
||||||
|
p.file, _ = syntax.Parse(base, f, p.error, p.pragma, 0) // errors are tracked via p.error
|
||||||
|
}(filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range noders {
|
||||||
|
for e := range p.err {
|
||||||
|
yyerrorpos(e.Pos, "%s", e.Msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.node()
|
||||||
|
lines += p.file.Lines
|
||||||
|
p.file = nil // release memory
|
||||||
|
|
||||||
if nsyntaxerrors != 0 {
|
if nsyntaxerrors != 0 {
|
||||||
errorexit()
|
errorexit()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return lines
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseFile(filename string) uint {
|
|
||||||
f, err := os.Open(filename)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
errorexit()
|
|
||||||
}
|
|
||||||
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
|
|
||||||
|
|
||||||
p.file(file)
|
|
||||||
|
|
||||||
if nsyntaxerrors == 0 {
|
|
||||||
testdclstack()
|
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
|
var pathPrefix string
|
||||||
@ -54,27 +67,41 @@ func absFilename(name string) string {
|
|||||||
return obj.AbsFile(Ctxt.Pathname, name, pathPrefix)
|
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 {
|
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
|
block = 1
|
||||||
iota_ = -1000000
|
iota_ = -1000000
|
||||||
imported_unsafe = false
|
imported_unsafe = false
|
||||||
|
|
||||||
p.lineno(file.PkgName)
|
p.lineno(p.file.PkgName)
|
||||||
mkpackage(file.PkgName.Value)
|
mkpackage(p.file.PkgName.Value)
|
||||||
|
|
||||||
xtop = append(xtop, p.decls(file.DeclList)...)
|
xtop = append(xtop, p.decls(p.file.DeclList)...)
|
||||||
|
|
||||||
if !imported_unsafe {
|
for _, n := range p.linknames {
|
||||||
for _, pos := range p.linknames {
|
if imported_unsafe {
|
||||||
p.error(syntax.Error{Pos: pos, Msg: "//go:linkname only allowed in Go files that import \"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):
|
// For compatibility with old code only (comparisons w/ toolstash):
|
||||||
// The old line number tracking simply continued incrementing the
|
// The old line number tracking simply continued incrementing the
|
||||||
// virtual line number (lexlineno) and using it also for lineno.
|
// 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.
|
// for fninit and set lineno to NoPos here.
|
||||||
// TODO(gri) fix this once we switched permanently to the new
|
// TODO(gri) fix this once we switched permanently to the new
|
||||||
// position information.
|
// position information.
|
||||||
lineno = MakePos(file.Pos().Base(), uint(file.Lines), 0)
|
lineno = MakePos(p.file.Pos().Base(), uint(p.file.Lines), 0)
|
||||||
|
|
||||||
clearImports()
|
clearImports()
|
||||||
}
|
}
|
||||||
@ -221,7 +248,7 @@ func (p *noder) constDecl(decl *syntax.ConstDecl) []*Node {
|
|||||||
|
|
||||||
func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node {
|
func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node {
|
||||||
name := typedcl0(p.name(decl.Name))
|
name := typedcl0(p.name(decl.Name))
|
||||||
name.Name.Param.Pragma = Pragma(decl.Pragma)
|
name.Name.Param.Pragma = decl.Pragma
|
||||||
|
|
||||||
var typ *Node
|
var typ *Node
|
||||||
if decl.Type != nil {
|
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.Nbody.Set(body)
|
||||||
f.Noescape = pragma&Noescape != 0
|
f.Noescape = pragma&Noescape != 0
|
||||||
@ -1043,8 +1070,7 @@ func (p *noder) lineno(n syntax.Node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *noder) error(err error) {
|
func (p *noder) error(err error) {
|
||||||
e := err.(syntax.Error)
|
p.err <- err.(syntax.Error)
|
||||||
yyerrorl(Ctxt.PosTable.XPos(e.Pos), "%s", e.Msg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *noder) pragma(pos src.Pos, text string) syntax.Pragma {
|
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")
|
panic("unreachable")
|
||||||
|
|
||||||
case strings.HasPrefix(text, "go:linkname "):
|
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)
|
f := strings.Fields(text)
|
||||||
if len(f) != 3 {
|
if len(f) != 3 {
|
||||||
p.error(syntax.Error{Pos: pos, Msg: "usage: //go:linkname localname linkname"})
|
p.error(syntax.Error{Pos: pos, Msg: "usage: //go:linkname localname linkname"})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
lookup(f[1]).Linkname = f[2]
|
p.linknames = append(p.linknames, linkname{pos, f[1], f[2]})
|
||||||
|
|
||||||
case strings.HasPrefix(text, "go:cgo_"):
|
case strings.HasPrefix(text, "go:cgo_"):
|
||||||
pragcgobuf += pragcgo(text)
|
p.pragcgobuf += pragcgo(text)
|
||||||
fallthrough // because of //go:cgo_unsafe_args
|
fallthrough // because of //go:cgo_unsafe_args
|
||||||
default:
|
default:
|
||||||
verb := text
|
verb := text
|
||||||
if i := strings.Index(text, " "); i >= 0 {
|
if i := strings.Index(text, " "); i >= 0 {
|
||||||
verb = verb[:i]
|
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
|
return 0
|
||||||
|
@ -6,7 +6,10 @@
|
|||||||
|
|
||||||
package gc
|
package gc
|
||||||
|
|
||||||
import "cmd/internal/src"
|
import (
|
||||||
|
"cmd/compile/internal/syntax"
|
||||||
|
"cmd/internal/src"
|
||||||
|
)
|
||||||
|
|
||||||
// A Node is a single node in the syntax tree.
|
// A Node is a single node in the syntax tree.
|
||||||
// Actually the syntax tree is a syntax DAG, because there is only one
|
// Actually the syntax tree is a syntax DAG, because there is only one
|
||||||
@ -285,7 +288,7 @@ type Param struct {
|
|||||||
// OTYPE pragmas
|
// OTYPE pragmas
|
||||||
//
|
//
|
||||||
// TODO: Should Func pragmas also be stored on the Name?
|
// 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.
|
// Func holds Node fields used only with function-like nodes.
|
||||||
@ -313,11 +316,11 @@ type Func struct {
|
|||||||
Endlineno src.XPos
|
Endlineno src.XPos
|
||||||
WBPos src.XPos // position of first write barrier
|
WBPos src.XPos // position of first write barrier
|
||||||
|
|
||||||
Pragma Pragma // go:xxx function annotations
|
Pragma syntax.Pragma // go:xxx function annotations
|
||||||
Dupok bool // duplicate definitions ok
|
Dupok bool // duplicate definitions ok
|
||||||
Wrapper bool // is method wrapper
|
Wrapper bool // is method wrapper
|
||||||
Needctxt bool // function uses context register (has closure variables)
|
Needctxt bool // function uses context register (has closure variables)
|
||||||
ReflectMethod bool // function calls reflect.Type.Method or MethodByName
|
ReflectMethod bool // function calls reflect.Type.Method or MethodByName
|
||||||
IsHiddenClosure bool
|
IsHiddenClosure bool
|
||||||
NoFramePointer bool // Must not use a frame pointer for this function
|
NoFramePointer bool // Must not use a frame pointer for this function
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user