aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/noder/noder.go
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2021-01-09 00:57:55 -0800
committerMatthew Dempsky <mdempsky@google.com>2021-01-14 02:07:48 +0000
commitef5285fbd0636965d916c81dbf87834731f337b2 (patch)
tree005d62b2e4f8bb7373b93d467fb749696d23ef66 /src/cmd/compile/internal/noder/noder.go
parentf065ff221b546c9ac550d947f89eb3b44b11fc2f (diff)
downloadgo-ef5285fbd0636965d916c81dbf87834731f337b2.tar.gz
go-ef5285fbd0636965d916c81dbf87834731f337b2.zip
[dev.typeparams] cmd/compile: add types2-based noder
This CL adds "irgen", a new noding implementation that utilizes types2 to guide IR construction. Notably, it completely skips dealing with constant and type expressions (aside from using ir.TypeNode to interoperate with the types1 typechecker), because types2 already handled those. It also omits any syntax checking, trusting that types2 already rejected any errors. It currently still utilizes the types1 typechecker for the desugaring operations it handles (e.g., turning OAS2 into OAS2FUNC/etc, inserting implicit conversions, rewriting f(g()) functions, and so on). However, the IR is constructed in a fully incremental fashion, so it should be easy to now piecemeal replace those dependencies as needed. Nearly all of "go test std cmd" passes with -G=3 enabled by default. The main remaining blocker is the number of test/run.go failures. There also appear to be cases where types2 does not provide us with position information. These will be iterated upon. Portions and ideas from Dan Scales's CL 276653. Change-Id: Ic99e8f2d0267b0312d30c10d5d043f5817a59c9d Reviewed-on: https://go-review.googlesource.com/c/go/+/281932 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Dan Scales <danscales@google.com> Reviewed-by: Robert Griesemer <gri@golang.org> Trust: Matthew Dempsky <mdempsky@google.com> Trust: Robert Griesemer <gri@golang.org>
Diffstat (limited to 'src/cmd/compile/internal/noder/noder.go')
-rw-r--r--src/cmd/compile/internal/noder/noder.go178
1 files changed, 29 insertions, 149 deletions
diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go
index 6a0ee831d7..0c7d015977 100644
--- a/src/cmd/compile/internal/noder/noder.go
+++ b/src/cmd/compile/internal/noder/noder.go
@@ -23,48 +23,31 @@ import (
"cmd/compile/internal/syntax"
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
- "cmd/compile/internal/types2"
"cmd/internal/objabi"
"cmd/internal/src"
)
func LoadPackage(filenames []string) {
base.Timer.Start("fe", "parse")
- lines := ParseFiles(filenames)
- base.Timer.Stop()
- base.Timer.AddEvent(int64(lines), "lines")
- if base.Flag.G != 0 && base.Flag.G < 3 {
- // can only parse generic code for now
- base.ExitIfErrors()
- return
+ mode := syntax.CheckBranches
+ if base.Flag.G != 0 {
+ mode |= syntax.AllowGenerics
}
- // Typecheck.
- Package()
-
- // With all user code typechecked, it's now safe to verify unused dot imports.
- CheckDotImports()
- base.ExitIfErrors()
-}
-
-// ParseFiles concurrently parses files into *syntax.File structures.
-// Each declaration in every *syntax.File is converted to a syntax tree
-// and its root represented by *Node is appended to Target.Decls.
-// Returns the total count of parsed lines.
-func ParseFiles(filenames []string) (lines uint) {
- noders := make([]*noder, 0, len(filenames))
// Limit the number of simultaneously open files.
sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)
- for _, filename := range filenames {
- p := &noder{
+ noders := make([]*noder, len(filenames))
+ for i, filename := range filenames {
+ p := noder{
err: make(chan syntax.Error),
trackScopes: base.Flag.Dwarf,
}
- noders = append(noders, p)
+ noders[i] = &p
- go func(filename string) {
+ filename := filename
+ go func() {
sem <- struct{}{}
defer func() { <-sem }()
defer close(p.err)
@@ -77,115 +60,42 @@ func ParseFiles(filenames []string) (lines uint) {
}
defer f.Close()
- mode := syntax.CheckBranches
- if base.Flag.G != 0 {
- mode |= syntax.AllowGenerics
- }
p.file, _ = syntax.Parse(fbase, f, p.error, p.pragma, mode) // errors are tracked via p.error
- }(filename)
- }
-
- // generic noding phase (using new typechecker)
- if base.Flag.G != 0 {
- // setup and syntax error reporting
- nodersmap := make(map[string]*noder)
- var files []*syntax.File
- for _, p := range noders {
- for e := range p.err {
- p.errorAt(e.Pos, "%s", e.Msg)
- }
-
- nodersmap[p.file.Pos().RelFilename()] = p
- files = append(files, p.file)
- lines += p.file.EOF.Line()
-
- }
- if base.SyntaxErrors() != 0 {
- base.ErrorExit()
- }
-
- // typechecking
- conf := types2.Config{
- InferFromConstraints: true,
- IgnoreBranches: true, // parser already checked via syntax.CheckBranches mode
- CompilerErrorMessages: true, // use error strings matching existing compiler errors
- Error: func(err error) {
- terr := err.(types2.Error)
- if len(terr.Msg) > 0 && terr.Msg[0] == '\t' {
- // types2 reports error clarifications via separate
- // error messages which are indented with a tab.
- // Ignore them to satisfy tools and tests that expect
- // only one error in such cases.
- // TODO(gri) Need to adjust error reporting in types2.
- return
- }
- p := nodersmap[terr.Pos.RelFilename()]
- base.ErrorfAt(p.makeXPos(terr.Pos), "%s", terr.Msg)
- },
- Importer: &gcimports{
- packages: make(map[string]*types2.Package),
- },
- Sizes: &gcSizes{},
- }
- info := types2.Info{
- Types: make(map[syntax.Expr]types2.TypeAndValue),
- Defs: make(map[*syntax.Name]types2.Object),
- Uses: make(map[*syntax.Name]types2.Object),
- Selections: make(map[*syntax.SelectorExpr]*types2.Selection),
- // expand as needed
- }
- conf.Check(base.Ctxt.Pkgpath, files, &info)
- base.ExitIfErrors()
- if base.Flag.G < 2 {
- return
- }
-
- // noding
- for _, p := range noders {
- // errors have already been reported
-
- p.typeInfo = &info
- p.node()
- lines += p.file.EOF.Line()
- p.file = nil // release memory
- base.ExitIfErrors()
-
- // Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
- types.CheckDclstack()
- }
-
- types.LocalPkg.Height = myheight
- return
+ }()
}
- // traditional (non-generic) noding phase
+ var lines uint
for _, p := range noders {
for e := range p.err {
p.errorAt(e.Pos, "%s", e.Msg)
}
+ lines += p.file.EOF.Line()
+ }
+ base.Timer.AddEvent(int64(lines), "lines")
+
+ if base.Flag.G != 0 {
+ // Use types2 to type-check and possibly generate IR.
+ check2(noders)
+ return
+ }
+ for _, p := range noders {
p.node()
- lines += p.file.EOF.Line()
p.file = nil // release memory
- if base.SyntaxErrors() != 0 {
- base.ErrorExit()
- }
+ }
- // Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
- types.CheckDclstack()
+ if base.SyntaxErrors() != 0 {
+ base.ErrorExit()
}
+ types.CheckDclstack()
for _, p := range noders {
p.processPragmas()
}
+ // Typecheck.
types.LocalPkg.Height = myheight
- return
-}
-
-func Package() {
typecheck.DeclareUniverse()
-
typecheck.TypecheckAllowed = true
// Process top-level declarations in phases.
@@ -242,8 +152,10 @@ func Package() {
}
// Phase 5: With all user code type-checked, it's now safe to verify map keys.
+ // With all user code typechecked, it's now safe to verify unused dot imports.
typecheck.CheckMapKeys()
-
+ CheckDotImports()
+ base.ExitIfErrors()
}
func (p *noder) errorAt(pos syntax.Pos, format string, args ...interface{}) {
@@ -272,37 +184,6 @@ type noder struct {
trackScopes bool
funcState *funcState
-
- // typeInfo provides access to the type information computed by the new
- // typechecker. It is only present if -G is set, and all noders point to
- // the same types.Info. For now this is a local field, if need be we can
- // make it global.
- typeInfo *types2.Info
-}
-
-// For now we provide these basic accessors to get to type and object
-// information of expression nodes during noding. Eventually we will
-// attach this information directly to the syntax tree which should
-// simplify access and make it more efficient as well.
-
-// typ returns the type and value information for the given expression.
-func (p *noder) typ(x syntax.Expr) types2.TypeAndValue {
- return p.typeInfo.Types[x]
-}
-
-// def returns the object for the given name in its declaration.
-func (p *noder) def(x *syntax.Name) types2.Object {
- return p.typeInfo.Defs[x]
-}
-
-// use returns the object for the given name outside its declaration.
-func (p *noder) use(x *syntax.Name) types2.Object {
- return p.typeInfo.Uses[x]
-}
-
-// sel returns the selection information for the given selector expression.
-func (p *noder) sel(x *syntax.SelectorExpr) *types2.Selection {
- return p.typeInfo.Selections[x]
}
// funcState tracks all per-function state to make handling nested
@@ -380,7 +261,6 @@ type linkname struct {
}
func (p *noder) node() {
- types.Block = 1
p.importedUnsafe = false
p.importedEmbed = false