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

1079 lines
24 KiB
Go
Raw Normal View History

// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gc
import (
"fmt"
"os"
"strconv"
"strings"
"unicode/utf8"
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
"cmd/compile/internal/syntax"
"cmd/internal/obj"
"cmd/internal/src"
)
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
func parseFile(filename string) uint {
f, err := os.Open(filename)
if err != nil {
fmt.Println(err)
errorexit()
}
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
defer f.Close()
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
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 !imported_unsafe {
for _, pos := range p.linknames {
p.error(syntax.Error{Pos: pos, Msg: "//go:linkname only allowed in Go files that import \"unsafe\""})
}
}
if nsyntaxerrors == 0 {
testdclstack()
}
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
return file.Lines
}
var pathPrefix string
func absFilename(name string) string {
return obj.AbsFile(Ctxt.Pathname, name, pathPrefix)
}
// noder transforms package syntax's AST into a Nod tree.
type noder struct {
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
linknames []src.Pos // tracks //go:linkname positions
}
func (p *noder) file(file *syntax.File) {
p.lineno(file.PkgName)
mkpackage(file.PkgName.Value)
xtop = append(xtop, p.decls(file.DeclList)...)
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
// 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.
// After processing the last function, the lineno was used for the
// line number information of the initialization code (fninit).
// It would be better to use an explicit "<autogenerated>" filename
// for fninit and set lineno to NoPos here.
// TODO(gri) fix this once we switched permanently to the new
// position information.
lineno = src.MakePos(file.Pos().Base(), uint(file.Lines), 0)
}
func (p *noder) decls(decls []syntax.Decl) (l []*Node) {
var lastConstGroup *syntax.Group
var lastConstRHS []*Node
var iotaVal int64
for _, decl := range decls {
p.lineno(decl)
switch decl := decl.(type) {
case *syntax.ImportDecl:
p.importDecl(decl)
case *syntax.VarDecl:
l = append(l, p.varDecl(decl)...)
case *syntax.ConstDecl:
// Tricky to handle golang.org/issue/15550 correctly.
prevIota := iota_
if decl.Group == nil || decl.Group != lastConstGroup {
iotaVal = 0
lastConstRHS = nil
}
iota_ = iotaVal
lastconst = lastConstRHS
l = append(l, p.constDecl(decl)...)
lastConstRHS = lastconst
lastconst = nil
iota_ = prevIota
iotaVal++
lastConstGroup = decl.Group
case *syntax.TypeDecl:
l = append(l, p.typeDecl(decl))
case *syntax.FuncDecl:
l = append(l, p.funcDecl(decl))
default:
panic("unhandled Decl")
}
}
return
}
func (p *noder) importDecl(imp *syntax.ImportDecl) {
val := p.basicLit(imp.Path)
importfile(&val, nil)
ipkg := importpkg
importpkg = nil
if ipkg == nil {
if nerrors == 0 {
Fatalf("phase error in import")
}
return
}
ipkg.Direct = true
var my *Sym
if imp.LocalPkgName != nil {
my = p.name(imp.LocalPkgName)
} else {
my = lookup(ipkg.Name)
}
pack := p.nod(imp, OPACK, nil, nil)
pack.Sym = my
pack.Name.Pkg = ipkg
if my.Name == "." {
importdot(ipkg, pack)
return
}
if my.Name == "init" {
yyerrorl(pack.Pos, "cannot import package as init - init must be a func")
return
}
if my.Name == "_" {
return
}
if my.Def != nil {
lineno = pack.Pos
redeclare(my, "as imported package name")
}
my.Def = pack
my.Lastlineno = pack.Pos
my.Block = 1 // at top level
}
func (p *noder) varDecl(decl *syntax.VarDecl) []*Node {
names := p.declNames(decl.NameList)
var typ *Node
if decl.Type != nil {
typ = p.typeExpr(decl.Type)
}
var exprs []*Node
if decl.Values != nil {
exprs = p.exprList(decl.Values)
}
p.lineno(decl)
return variter(names, typ, exprs)
}
func (p *noder) constDecl(decl *syntax.ConstDecl) []*Node {
names := p.declNames(decl.NameList)
var typ *Node
if decl.Type != nil {
typ = p.typeExpr(decl.Type)
}
var exprs []*Node
if decl.Values != nil {
exprs = p.exprList(decl.Values)
}
return constiter(names, typ, exprs)
}
func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node {
name := typedcl0(p.name(decl.Name))
cmd/compile: add go:notinheap type pragma This adds a //go:notinheap pragma for declarations of types that must not be heap allocated. We ensure these rules by disallowing new(T), make([]T), append([]T), or implicit allocation of T, by disallowing conversions to notinheap types, and by propagating notinheap to any struct or array that contains notinheap elements. The utility of this pragma is that we can eliminate write barriers for writes to pointers to go:notinheap types, since the write barrier is guaranteed to be a no-op. This will let us mark several scheduler and memory allocator structures as go:notinheap, which will let us disallow write barriers in the scheduler and memory allocator much more thoroughly and also eliminate some problematic hybrid write barriers. This also makes go:nowritebarrierrec and go:yeswritebarrierrec much more powerful. Currently we use go:nowritebarrier all over the place, but it's almost never what you actually want: when write barriers are illegal, they're typically illegal for a whole dynamic scope. Partly this is because go:nowritebarrier has been around longer, but it's also because go:nowritebarrierrec couldn't be used in situations that had no-op write barriers or where some nested scope did allow write barriers. go:notinheap eliminates many no-op write barriers and go:yeswritebarrierrec makes it possible to opt back in to write barriers, so these two changes will let us use go:nowritebarrierrec far more liberally. This updates #13386, which is about controlling pointers from non-GC'd memory to GC'd memory. That would require some additional pragma (or pragmas), but could build on this pragma. Change-Id: I6314f8f4181535dd166887c9ec239977b54940bd Reviewed-on: https://go-review.googlesource.com/30939 Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-10-11 22:53:27 -04:00
name.Name.Param.Pragma = Pragma(decl.Pragma)
var typ *Node
if decl.Type != nil {
typ = p.typeExpr(decl.Type)
}
return typedcl1(name, typ, true)
}
func (p *noder) declNames(names []*syntax.Name) []*Node {
var nodes []*Node
for _, name := range names {
nodes = append(nodes, p.declName(name))
}
return nodes
}
func (p *noder) declName(name *syntax.Name) *Node {
// TODO(mdempsky): Set lineno?
return dclname(p.name(name))
}
func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node {
f := p.funcHeader(fun)
if f == nil {
return nil
}
var body []*Node
if fun.Body != nil {
body = p.stmts(fun.Body)
if body == nil {
body = []*Node{p.nod(fun, OEMPTY, nil, nil)}
}
}
pragma := Pragma(fun.Pragma)
f.Nbody.Set(body)
f.Noescape = pragma&Noescape != 0
if f.Noescape && len(body) != 0 {
yyerror("can only use //go:noescape with external func implementations")
}
f.Func.Pragma = pragma
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
lineno = src.MakePos(fun.Pos().Base(), fun.EndLine, 0)
f.Func.Endlineno = lineno
funcbody(f)
return f
}
func (p *noder) funcHeader(fun *syntax.FuncDecl) *Node {
name := p.name(fun.Name)
t := p.signature(fun.Recv, fun.Type)
f := p.nod(fun, ODCLFUNC, nil, nil)
if fun.Recv == nil {
// FunctionName Signature
if name.Name == "init" {
name = renameinit()
if t.List.Len() > 0 || t.Rlist.Len() > 0 {
yyerror("func init must have no arguments and no return values")
}
}
if localpkg.Name == "main" && name.Name == "main" {
if t.List.Len() > 0 || t.Rlist.Len() > 0 {
yyerror("func main must have no arguments and no return values")
}
}
f.Func.Nname = newfuncname(name)
} else {
// Receiver MethodName Signature
f.Func.Shortname = newfuncname(name)
f.Func.Nname = methodname(f.Func.Shortname, t.Left.Right)
}
f.Func.Nname.Name.Defn = f
f.Func.Nname.Name.Param.Ntype = t // TODO: check if nname already has an ntype
declare(f.Func.Nname, PFUNC)
funchdr(f)
return f
}
func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) *Node {
n := p.nod(typ, OTFUNC, nil, nil)
if recv != nil {
n.Left = p.param(recv, false, false)
}
n.List.Set(p.params(typ.ParamList, true))
n.Rlist.Set(p.params(typ.ResultList, false))
return n
}
func (p *noder) params(params []*syntax.Field, dddOk bool) []*Node {
var nodes []*Node
for i, param := range params {
p.lineno(param)
nodes = append(nodes, p.param(param, dddOk, i+1 == len(params)))
}
return nodes
}
func (p *noder) param(param *syntax.Field, dddOk, final bool) *Node {
var name *Node
if param.Name != nil {
name = p.newname(param.Name)
}
typ := p.typeExpr(param.Type)
n := p.nod(param, ODCLFIELD, name, typ)
// rewrite ...T parameter
if typ.Op == ODDD {
if !dddOk {
yyerror("cannot use ... in receiver or result parameter list")
} else if !final {
yyerror("can only use ... with final parameter in list")
}
typ.Op = OTARRAY
typ.Right = typ.Left
typ.Left = nil
n.Isddd = true
if n.Left != nil {
n.Left.Isddd = true
}
}
return n
}
func (p *noder) exprList(expr syntax.Expr) []*Node {
if list, ok := expr.(*syntax.ListExpr); ok {
return p.exprs(list.ElemList)
}
return []*Node{p.expr(expr)}
}
func (p *noder) exprs(exprs []syntax.Expr) []*Node {
var nodes []*Node
for _, expr := range exprs {
nodes = append(nodes, p.expr(expr))
}
return nodes
}
func (p *noder) expr(expr syntax.Expr) *Node {
p.lineno(expr)
switch expr := expr.(type) {
case nil:
return nil
case *syntax.Name:
return p.mkname(expr)
case *syntax.BasicLit:
return p.setlineno(expr, nodlit(p.basicLit(expr)))
case *syntax.CompositeLit:
n := p.nod(expr, OCOMPLIT, nil, nil)
if expr.Type != nil {
n.Right = p.expr(expr.Type)
}
l := p.exprs(expr.ElemList)
for i, e := range l {
l[i] = p.wrapname(expr.ElemList[i], e)
}
n.List.Set(l)
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
lineno = src.MakePos(expr.Pos().Base(), expr.EndLine, 0)
return n
case *syntax.KeyValueExpr:
return p.nod(expr, OKEY, p.expr(expr.Key), p.wrapname(expr.Value, p.expr(expr.Value)))
case *syntax.FuncLit:
closurehdr(p.typeExpr(expr.Type))
body := p.stmts(expr.Body)
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
lineno = src.MakePos(expr.Pos().Base(), expr.EndLine, 0)
return p.setlineno(expr, closurebody(body))
case *syntax.ParenExpr:
return p.nod(expr, OPAREN, p.expr(expr.X), nil)
case *syntax.SelectorExpr:
// parser.new_dotname
obj := p.expr(expr.X)
if obj.Op == OPACK {
obj.Used = true
return oldname(restrictlookup(expr.Sel.Value, obj.Name.Pkg))
}
return p.setlineno(expr, nodSym(OXDOT, obj, p.name(expr.Sel)))
case *syntax.IndexExpr:
return p.nod(expr, OINDEX, p.expr(expr.X), p.expr(expr.Index))
case *syntax.SliceExpr:
op := OSLICE
if expr.Full {
op = OSLICE3
}
n := p.nod(expr, op, p.expr(expr.X), nil)
var index [3]*Node
for i, x := range expr.Index {
if x != nil {
index[i] = p.expr(x)
}
}
n.SetSliceBounds(index[0], index[1], index[2])
return n
case *syntax.AssertExpr:
if expr.Type == nil {
panic("unexpected AssertExpr")
}
// TODO(mdempsky): parser.pexpr uses p.expr(), but
// seems like the type field should be parsed with
// ntype? Shrug, doesn't matter here.
return p.nod(expr, ODOTTYPE, p.expr(expr.X), p.expr(expr.Type))
case *syntax.Operation:
x := p.expr(expr.X)
if expr.Y == nil {
if expr.Op == syntax.And {
x = unparen(x) // TODO(mdempsky): Needed?
if x.Op == OCOMPLIT {
// Special case for &T{...}: turn into (*T){...}.
// TODO(mdempsky): Switch back to p.nod after we
// get rid of gcCompat.
x.Right = nod(OIND, x.Right, nil)
x.Right.Implicit = true
return x
}
}
return p.nod(expr, p.unOp(expr.Op), x, nil)
}
return p.nod(expr, p.binOp(expr.Op), x, p.expr(expr.Y))
case *syntax.CallExpr:
n := p.nod(expr, OCALL, p.expr(expr.Fun), nil)
n.List.Set(p.exprs(expr.ArgList))
n.Isddd = expr.HasDots
return n
case *syntax.ArrayType:
var len *Node
if expr.Len != nil {
len = p.expr(expr.Len)
} else {
len = p.nod(expr, ODDD, nil, nil)
}
return p.nod(expr, OTARRAY, len, p.typeExpr(expr.Elem))
case *syntax.SliceType:
return p.nod(expr, OTARRAY, nil, p.typeExpr(expr.Elem))
case *syntax.DotsType:
return p.nod(expr, ODDD, p.typeExpr(expr.Elem), nil)
case *syntax.StructType:
return p.structType(expr)
case *syntax.InterfaceType:
return p.interfaceType(expr)
case *syntax.FuncType:
return p.signature(nil, expr)
case *syntax.MapType:
return p.nod(expr, OTMAP, p.typeExpr(expr.Key), p.typeExpr(expr.Value))
case *syntax.ChanType:
n := p.nod(expr, OTCHAN, p.typeExpr(expr.Elem), nil)
n.Etype = EType(p.chanDir(expr.Dir))
return n
case *syntax.TypeSwitchGuard:
n := p.nod(expr, OTYPESW, nil, p.expr(expr.X))
if expr.Lhs != nil {
n.Left = p.declName(expr.Lhs)
if isblank(n.Left) {
yyerror("invalid variable name %v in type switch", n.Left)
}
}
return n
}
panic("unhandled Expr")
}
func (p *noder) typeExpr(typ syntax.Expr) *Node {
// TODO(mdempsky): Be stricter? typecheck should handle errors anyway.
return p.expr(typ)
}
func (p *noder) chanDir(dir syntax.ChanDir) ChanDir {
switch dir {
case 0:
return Cboth
case syntax.SendOnly:
return Csend
case syntax.RecvOnly:
return Crecv
}
panic("unhandled ChanDir")
}
func (p *noder) structType(expr *syntax.StructType) *Node {
var l []*Node
for i, field := range expr.FieldList {
p.lineno(field)
var n *Node
if field.Name == nil {
n = p.embedded(field.Type)
} else {
n = p.nod(field, ODCLFIELD, p.newname(field.Name), p.typeExpr(field.Type))
}
if i < len(expr.TagList) && expr.TagList[i] != nil {
n.SetVal(p.basicLit(expr.TagList[i]))
}
l = append(l, n)
}
p.lineno(expr)
n := p.nod(expr, OTSTRUCT, nil, nil)
n.List.Set(l)
return n
}
func (p *noder) interfaceType(expr *syntax.InterfaceType) *Node {
var l []*Node
for _, method := range expr.MethodList {
p.lineno(method)
var n *Node
if method.Name == nil {
n = p.nod(method, ODCLFIELD, nil, oldname(p.packname(method.Type)))
} else {
mname := p.newname(method.Name)
sig := p.typeExpr(method.Type)
sig.Left = fakethis()
n = p.nod(method, ODCLFIELD, mname, sig)
ifacedcl(n)
}
l = append(l, n)
}
n := p.nod(expr, OTINTER, nil, nil)
n.List.Set(l)
return n
}
func (p *noder) packname(expr syntax.Expr) *Sym {
switch expr := expr.(type) {
case *syntax.Name:
name := p.name(expr)
if n := oldname(name); n.Name != nil && n.Name.Pack != nil {
n.Name.Pack.Used = true
}
return name
case *syntax.SelectorExpr:
name := p.name(expr.X.(*syntax.Name))
var pkg *Pkg
if name.Def == nil || name.Def.Op != OPACK {
yyerror("%v is not a package", name)
pkg = localpkg
} else {
name.Def.Used = true
pkg = name.Def.Name.Pkg
}
return restrictlookup(expr.Sel.Value, pkg)
}
panic(fmt.Sprintf("unexpected packname: %#v", expr))
}
func (p *noder) embedded(typ syntax.Expr) *Node {
op, isStar := typ.(*syntax.Operation)
if isStar {
if op.Op != syntax.Mul || op.Y != nil {
panic("unexpected Operation")
}
typ = op.X
}
n := embedded(p.packname(typ), localpkg)
if isStar {
n.Right = p.nod(op, OIND, n.Right, nil)
}
return n
}
func (p *noder) stmts(stmts []syntax.Stmt) []*Node {
var nodes []*Node
for _, stmt := range stmts {
s := p.stmt(stmt)
if s == nil {
} else if s.Op == OBLOCK && s.Ninit.Len() == 0 {
nodes = append(nodes, s.List.Slice()...)
} else {
nodes = append(nodes, s)
}
}
return nodes
}
func (p *noder) stmt(stmt syntax.Stmt) *Node {
p.lineno(stmt)
switch stmt := stmt.(type) {
case *syntax.EmptyStmt:
return nil
case *syntax.LabeledStmt:
return p.labeledStmt(stmt)
case *syntax.BlockStmt:
return p.body(stmt.Body)
case *syntax.ExprStmt:
return p.wrapname(stmt, p.expr(stmt.X))
case *syntax.SendStmt:
return p.nod(stmt, OSEND, p.expr(stmt.Chan), p.expr(stmt.Value))
case *syntax.DeclStmt:
return liststmt(p.decls(stmt.DeclList))
case *syntax.AssignStmt:
if stmt.Op != 0 && stmt.Op != syntax.Def {
n := p.nod(stmt, OASOP, p.expr(stmt.Lhs), p.expr(stmt.Rhs))
n.Implicit = stmt.Rhs == syntax.ImplicitOne
n.Etype = EType(p.binOp(stmt.Op))
return n
}
lhs := p.exprList(stmt.Lhs)
rhs := p.exprList(stmt.Rhs)
n := p.nod(stmt, OAS, nil, nil) // assume common case
if stmt.Op == syntax.Def {
n.Colas = true
colasdefn(lhs, n) // modifies lhs, call before using lhs[0] in common case
}
if len(lhs) == 1 && len(rhs) == 1 {
// common case
n.Left = lhs[0]
n.Right = rhs[0]
} else {
n.Op = OAS2
n.List.Set(lhs)
n.Rlist.Set(rhs)
}
return n
case *syntax.BranchStmt:
var op Op
switch stmt.Tok {
case syntax.Break:
op = OBREAK
case syntax.Continue:
op = OCONTINUE
case syntax.Fallthrough:
op = OXFALL
case syntax.Goto:
op = OGOTO
default:
panic("unhandled BranchStmt")
}
n := p.nod(stmt, op, nil, nil)
if stmt.Label != nil {
n.Left = p.newname(stmt.Label)
}
if op == OGOTO {
n.Sym = dclstack // context, for goto restriction
}
if op == OXFALL {
n.Xoffset = int64(block)
}
return n
case *syntax.CallStmt:
var op Op
switch stmt.Tok {
case syntax.Defer:
op = ODEFER
case syntax.Go:
op = OPROC
default:
panic("unhandled CallStmt")
}
return p.nod(stmt, op, p.expr(stmt.Call), nil)
case *syntax.ReturnStmt:
var results []*Node
if stmt.Results != nil {
results = p.exprList(stmt.Results)
}
n := p.nod(stmt, ORETURN, nil, nil)
n.List.Set(results)
if n.List.Len() == 0 && Curfn != nil {
for _, ln := range Curfn.Func.Dcl {
if ln.Class == PPARAM {
continue
}
if ln.Class != PPARAMOUT {
break
}
if ln.Sym.Def != ln {
yyerror("%s is shadowed during return", ln.Sym.Name)
}
}
}
return n
case *syntax.IfStmt:
return p.ifStmt(stmt)
case *syntax.ForStmt:
return p.forStmt(stmt)
case *syntax.SwitchStmt:
return p.switchStmt(stmt)
case *syntax.SelectStmt:
return p.selectStmt(stmt)
}
panic("unhandled Stmt")
}
func (p *noder) body(body []syntax.Stmt) *Node {
l := p.bodyList(body)
if len(l) == 0 {
// TODO(mdempsky): Line number?
return nod(OEMPTY, nil, nil)
}
return liststmt(l)
}
func (p *noder) bodyList(body []syntax.Stmt) []*Node {
markdcl()
nodes := p.stmts(body)
popdcl()
return nodes
}
func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node {
markdcl()
n := p.nod(stmt, OIF, nil, nil)
if stmt.Init != nil {
n.Ninit.Set1(p.stmt(stmt.Init))
}
if stmt.Cond != nil {
n.Left = p.expr(stmt.Cond)
}
n.Nbody.Set(p.bodyList(stmt.Then))
if stmt.Else != nil {
e := p.stmt(stmt.Else)
if e.Op == OBLOCK && e.Ninit.Len() == 0 {
n.Rlist.Set(e.List.Slice())
} else {
n.Rlist.Set1(e)
}
}
popdcl()
return n
}
func (p *noder) forStmt(stmt *syntax.ForStmt) *Node {
markdcl()
var n *Node
if r, ok := stmt.Init.(*syntax.RangeClause); ok {
if stmt.Cond != nil || stmt.Post != nil {
panic("unexpected RangeClause")
}
n = p.nod(r, ORANGE, nil, p.expr(r.X))
if r.Lhs != nil {
lhs := p.exprList(r.Lhs)
n.List.Set(lhs)
if r.Def {
n.Colas = true
colasdefn(lhs, n)
}
}
} else {
n = p.nod(stmt, OFOR, nil, nil)
if stmt.Init != nil {
n.Ninit.Set1(p.stmt(stmt.Init))
}
if stmt.Cond != nil {
n.Left = p.expr(stmt.Cond)
}
if stmt.Post != nil {
n.Right = p.stmt(stmt.Post)
}
}
n.Nbody.Set(p.bodyList(stmt.Body))
popdcl()
return n
}
func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node {
markdcl()
n := p.nod(stmt, OSWITCH, nil, nil)
if stmt.Init != nil {
n.Ninit.Set1(p.stmt(stmt.Init))
}
if stmt.Tag != nil {
n.Left = p.expr(stmt.Tag)
}
tswitch := n.Left
if tswitch != nil && (tswitch.Op != OTYPESW || tswitch.Left == nil) {
tswitch = nil
}
n.List.Set(p.caseClauses(stmt.Body, tswitch))
popdcl()
return n
}
func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node) []*Node {
var nodes []*Node
for _, clause := range clauses {
p.lineno(clause)
markdcl()
n := p.nod(clause, OXCASE, nil, nil)
if clause.Cases != nil {
n.List.Set(p.exprList(clause.Cases))
}
if tswitch != nil {
nn := newname(tswitch.Left.Sym)
declare(nn, dclcontext)
n.Rlist.Set1(nn)
// keep track of the instances for reporting unused
nn.Name.Defn = tswitch
}
n.Xoffset = int64(block)
n.Nbody.Set(p.stmts(clause.Body))
popdcl()
nodes = append(nodes, n)
}
return nodes
}
func (p *noder) selectStmt(stmt *syntax.SelectStmt) *Node {
n := p.nod(stmt, OSELECT, nil, nil)
n.List.Set(p.commClauses(stmt.Body))
return n
}
func (p *noder) commClauses(clauses []*syntax.CommClause) []*Node {
var nodes []*Node
for _, clause := range clauses {
p.lineno(clause)
markdcl()
n := p.nod(clause, OXCASE, nil, nil)
if clause.Comm != nil {
n.List.Set1(p.stmt(clause.Comm))
}
n.Xoffset = int64(block)
n.Nbody.Set(p.stmts(clause.Body))
popdcl()
nodes = append(nodes, n)
}
return nodes
}
func (p *noder) labeledStmt(label *syntax.LabeledStmt) *Node {
lhs := p.nod(label, OLABEL, p.newname(label.Label), nil)
lhs.Sym = dclstack
var ls *Node
if label.Stmt != nil { // TODO(mdempsky): Should always be present.
ls = p.stmt(label.Stmt)
}
lhs.Name.Defn = ls
l := []*Node{lhs}
if ls != nil {
if ls.Op == OBLOCK && ls.Ninit.Len() == 0 {
l = append(l, ls.List.Slice()...)
} else {
l = append(l, ls)
}
}
return liststmt(l)
}
var unOps = [...]Op{
syntax.Recv: ORECV,
syntax.Mul: OIND,
syntax.And: OADDR,
syntax.Not: ONOT,
syntax.Xor: OCOM,
syntax.Add: OPLUS,
syntax.Sub: OMINUS,
}
func (p *noder) unOp(op syntax.Operator) Op {
if uint64(op) >= uint64(len(unOps)) || unOps[op] == 0 {
panic("invalid Operator")
}
return unOps[op]
}
var binOps = [...]Op{
syntax.OrOr: OOROR,
syntax.AndAnd: OANDAND,
syntax.Eql: OEQ,
syntax.Neq: ONE,
syntax.Lss: OLT,
syntax.Leq: OLE,
syntax.Gtr: OGT,
syntax.Geq: OGE,
syntax.Add: OADD,
syntax.Sub: OSUB,
syntax.Or: OOR,
syntax.Xor: OXOR,
syntax.Mul: OMUL,
syntax.Div: ODIV,
syntax.Rem: OMOD,
syntax.And: OAND,
syntax.AndNot: OANDNOT,
syntax.Shl: OLSH,
syntax.Shr: ORSH,
}
func (p *noder) binOp(op syntax.Operator) Op {
if uint64(op) >= uint64(len(binOps)) || binOps[op] == 0 {
panic("invalid Operator")
}
return binOps[op]
}
func (p *noder) basicLit(lit *syntax.BasicLit) Val {
// TODO: Don't try to convert if we had syntax errors (conversions may fail).
// Use dummy values so we can continue to compile. Eventually, use a
// form of "unknown" literals that are ignored during type-checking so
// we can continue type-checking w/o spurious follow-up errors.
switch s := lit.Value; lit.Kind {
case syntax.IntLit:
x := new(Mpint)
x.SetString(s)
return Val{U: x}
case syntax.FloatLit:
x := newMpflt()
x.SetString(s)
return Val{U: x}
case syntax.ImagLit:
x := new(Mpcplx)
x.Imag.SetString(strings.TrimSuffix(s, "i"))
return Val{U: x}
case syntax.RuneLit:
var r rune
if u, err := strconv.Unquote(s); err == nil && len(u) > 0 {
// Package syntax already reported any errors.
// Check for them again though because 0 is a
// better fallback value for invalid rune
// literals than 0xFFFD.
if len(u) == 1 {
r = rune(u[0])
} else {
r, _ = utf8.DecodeRuneInString(u)
}
}
x := new(Mpint)
x.SetInt64(int64(r))
x.Rune = true
return Val{U: x}
case syntax.StringLit:
if len(s) > 0 && s[0] == '`' {
// strip carriage returns from raw string
s = strings.Replace(s, "\r", "", -1)
}
// Ignore errors because package syntax already reported them.
u, _ := strconv.Unquote(s)
return Val{U: u}
default:
panic("unhandled BasicLit kind")
}
}
func (p *noder) name(name *syntax.Name) *Sym {
return lookup(name.Value)
}
func (p *noder) mkname(name *syntax.Name) *Node {
// TODO(mdempsky): Set line number?
return mkname(p.name(name))
}
func (p *noder) newname(name *syntax.Name) *Node {
// TODO(mdempsky): Set line number?
return newname(p.name(name))
}
func (p *noder) wrapname(n syntax.Node, x *Node) *Node {
// These nodes do not carry line numbers.
// Introduce a wrapper node to give them the correct line.
switch x.Op {
case OTYPE, OLITERAL:
if x.Sym == nil {
break
}
fallthrough
case ONAME, ONONAME, OPACK:
x = p.nod(n, OPAREN, x, nil)
x.Implicit = true
}
return x
}
func (p *noder) nod(orig syntax.Node, op Op, left, right *Node) *Node {
return p.setlineno(orig, nod(op, left, right))
}
func (p *noder) setlineno(src_ syntax.Node, dst *Node) *Node {
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
pos := src_.Pos()
if !pos.IsKnown() {
// TODO(mdempsky): Shouldn't happen. Fix package syntax.
return dst
}
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
dst.Pos = pos
return dst
}
func (p *noder) lineno(n syntax.Node) {
if n == nil {
return
}
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
pos := n.Pos()
if !pos.IsKnown() {
// TODO(mdempsky): Shouldn't happen. Fix package syntax.
return
}
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
lineno = pos
}
func (p *noder) error(err error) {
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
e := err.(syntax.Error)
yyerrorl(e.Pos, "%s", e.Msg)
}
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
func (p *noder) pragma(pos src.Pos, text string) syntax.Pragma {
switch {
case strings.HasPrefix(text, "line "):
[dev.inline] cmd/internal/src: replace src.Pos with syntax.Pos This replaces the src.Pos LineHist-based position tracking with the syntax.Pos implementation and updates all uses. The LineHist table is not used anymore - the respective code is still there but should be removed eventually. CL forthcoming. Passes toolstash -cmp when comparing to the master repo (with the exception of a couple of swapped assembly instructions, likely due to different instruction scheduling because the line-based sorting has changed; though this is won't affect correctness). The sizes of various important compiler data structures have increased significantly (see the various sizes_test.go files); this is probably the reason for an increase of compilation times (to be addressed). Here are the results of compilebench -count 5, run on a "quiet" machine (no apps running besides a terminal): name old time/op new time/op delta Template 256ms ± 1% 280ms ±15% +9.54% (p=0.008 n=5+5) Unicode 132ms ± 1% 132ms ± 1% ~ (p=0.690 n=5+5) GoTypes 891ms ± 1% 917ms ± 2% +2.88% (p=0.008 n=5+5) Compiler 3.84s ± 2% 3.99s ± 2% +3.95% (p=0.016 n=5+5) MakeBash 47.1s ± 1% 47.2s ± 2% ~ (p=0.841 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 326M ± 2% +5.18% (p=0.008 n=5+5) Unicode 165M ± 1% 168M ± 4% ~ (p=0.421 n=5+5) GoTypes 1.14G ± 2% 1.18G ± 1% +3.47% (p=0.008 n=5+5) Compiler 5.00G ± 1% 5.16G ± 1% +3.12% (p=0.008 n=5+5) Change-Id: I241c4246cdff627d7ecb95cac23060b38f9775ec Reviewed-on: https://go-review.googlesource.com/34273 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-12-09 17:15:05 -08:00
// line directives are handled by syntax package
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]
case strings.HasPrefix(text, "go:cgo_"):
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))
}
return 0
}
func mkname(sym *Sym) *Node {
n := oldname(sym)
if n.Name != nil && n.Name.Pack != nil {
n.Name.Pack.Used = true
}
return n
}
func unparen(x *Node) *Node {
for x.Op == OPAREN {
x = x.Left
}
return x
}