mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile/internal/syntax: remove dependency on cmd/internal/src
For dependency reasons, the data structure implementing source positions in the compiler is in cmd/internal/src. It contains highly compiler specific details (e.g. inlining index). This change introduces a parallel but simpler position representation, defined in the syntax package, which removes that package's dependency on cmd/internal/src, and also removes the need to deal with certain filename-specific operations (defined by the needs of the compiler) in the syntax package. As a result, the syntax package becomes again a compiler- independent, stand-alone package that at some point might replace (or augment) the existing top-level go/* syntax-related packages. Additionally, line directives that update column numbers are now correctly tracked through the syntax package, with additional tests added. (The respective changes also need to be made in cmd/internal/src; i.e., the compiler accepts but still ignores column numbers in line directives.) This change comes at the cost of a new position translation step, but that step is cheap because it only needs to do real work if the position base changed (i.e., if there is a new file, or new line directive). There is no noticeable impact on overall compiler performance measured with `compilebench -count 5 -alloc`: name old time/op new time/op delta Template 220ms ± 8% 228ms ±18% ~ (p=0.548 n=5+5) Unicode 119ms ±11% 113ms ± 5% ~ (p=0.056 n=5+5) GoTypes 684ms ± 6% 677ms ± 3% ~ (p=0.841 n=5+5) Compiler 3.19s ± 7% 3.01s ± 1% ~ (p=0.095 n=5+5) SSA 7.92s ± 8% 7.79s ± 1% ~ (p=0.690 n=5+5) Flate 141ms ± 7% 139ms ± 4% ~ (p=0.548 n=5+5) GoParser 173ms ±12% 171ms ± 4% ~ (p=1.000 n=5+5) Reflect 417ms ± 5% 411ms ± 3% ~ (p=0.548 n=5+5) Tar 205ms ± 5% 198ms ± 2% ~ (p=0.690 n=5+5) XML 232ms ± 4% 229ms ± 4% ~ (p=0.690 n=5+5) StdCmd 28.7s ± 5% 28.2s ± 2% ~ (p=0.421 n=5+5) name old user-time/op new user-time/op delta Template 269ms ± 4% 265ms ± 5% ~ (p=0.421 n=5+5) Unicode 153ms ± 7% 149ms ± 3% ~ (p=0.841 n=5+5) GoTypes 850ms ± 7% 862ms ± 4% ~ (p=0.841 n=5+5) Compiler 4.01s ± 5% 3.86s ± 0% ~ (p=0.190 n=5+4) SSA 10.9s ± 4% 10.8s ± 2% ~ (p=0.548 n=5+5) Flate 166ms ± 7% 167ms ± 6% ~ (p=1.000 n=5+5) GoParser 204ms ± 8% 206ms ± 7% ~ (p=0.841 n=5+5) Reflect 514ms ± 5% 508ms ± 4% ~ (p=0.548 n=5+5) Tar 245ms ± 6% 244ms ± 3% ~ (p=0.690 n=5+5) XML 280ms ± 4% 278ms ± 4% ~ (p=0.841 n=5+5) name old alloc/op new alloc/op delta Template 37.9MB ± 0% 37.9MB ± 0% ~ (p=0.841 n=5+5) Unicode 28.8MB ± 0% 28.8MB ± 0% ~ (p=0.841 n=5+5) GoTypes 113MB ± 0% 113MB ± 0% ~ (p=0.151 n=5+5) Compiler 468MB ± 0% 468MB ± 0% -0.01% (p=0.032 n=5+5) SSA 1.50GB ± 0% 1.50GB ± 0% ~ (p=0.548 n=5+5) Flate 24.4MB ± 0% 24.4MB ± 0% ~ (p=1.000 n=5+5) GoParser 30.7MB ± 0% 30.7MB ± 0% ~ (p=1.000 n=5+5) Reflect 76.5MB ± 0% 76.5MB ± 0% ~ (p=0.548 n=5+5) Tar 38.9MB ± 0% 38.9MB ± 0% ~ (p=0.222 n=5+5) XML 41.6MB ± 0% 41.6MB ± 0% ~ (p=0.548 n=5+5) name old allocs/op new allocs/op delta Template 382k ± 0% 382k ± 0% +0.01% (p=0.008 n=5+5) Unicode 343k ± 0% 343k ± 0% ~ (p=0.841 n=5+5) GoTypes 1.19M ± 0% 1.19M ± 0% +0.01% (p=0.008 n=5+5) Compiler 4.53M ± 0% 4.53M ± 0% +0.03% (p=0.008 n=5+5) SSA 12.4M ± 0% 12.4M ± 0% +0.00% (p=0.008 n=5+5) Flate 235k ± 0% 235k ± 0% ~ (p=0.079 n=5+5) GoParser 318k ± 0% 318k ± 0% ~ (p=0.730 n=5+5) Reflect 978k ± 0% 978k ± 0% ~ (p=1.000 n=5+5) Tar 393k ± 0% 393k ± 0% ~ (p=0.056 n=5+5) XML 405k ± 0% 405k ± 0% ~ (p=0.548 n=5+5) name old text-bytes new text-bytes delta HelloSize 672kB ± 0% 672kB ± 0% ~ (all equal) CmdGoSize 7.12MB ± 0% 7.12MB ± 0% ~ (all equal) name old data-bytes new data-bytes delta HelloSize 133kB ± 0% 133kB ± 0% ~ (all equal) CmdGoSize 390kB ± 0% 390kB ± 0% ~ (all equal) name old exe-bytes new exe-bytes delta HelloSize 1.07MB ± 0% 1.07MB ± 0% ~ (all equal) CmdGoSize 11.2MB ± 0% 11.2MB ± 0% ~ (all equal) Passes toolstash compare. For #22662. Change-Id: I19edb53dd9675af57f7122cb7dba2a6d8bdcc3da Reviewed-on: https://go-review.googlesource.com/94515 Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
b1accced20
commit
5c08b9e8bd
14 changed files with 309 additions and 151 deletions
|
|
@ -5,7 +5,6 @@
|
|||
package syntax
|
||||
|
||||
import (
|
||||
"cmd/internal/src"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
|
|
@ -16,26 +15,24 @@ const debug = false
|
|||
const trace = false
|
||||
|
||||
type parser struct {
|
||||
file *src.PosBase
|
||||
errh ErrorHandler
|
||||
fileh FilenameHandler
|
||||
mode Mode
|
||||
file *PosBase
|
||||
errh ErrorHandler
|
||||
mode Mode
|
||||
scanner
|
||||
|
||||
base *src.PosBase // current position base
|
||||
first error // first error encountered
|
||||
errcnt int // number of errors encountered
|
||||
pragma Pragma // pragma flags
|
||||
base *PosBase // current position base
|
||||
first error // first error encountered
|
||||
errcnt int // number of errors encountered
|
||||
pragma Pragma // pragma flags
|
||||
|
||||
fnest int // function nesting level (for error handling)
|
||||
xnest int // expression nesting level (for complit ambiguity resolution)
|
||||
indent []byte // tracing support
|
||||
}
|
||||
|
||||
func (p *parser) init(file *src.PosBase, r io.Reader, errh ErrorHandler, pragh PragmaHandler, fileh FilenameHandler, mode Mode) {
|
||||
func (p *parser) init(file *PosBase, r io.Reader, errh ErrorHandler, pragh PragmaHandler, mode Mode) {
|
||||
p.file = file
|
||||
p.errh = errh
|
||||
p.fileh = fileh
|
||||
p.mode = mode
|
||||
p.scanner.init(
|
||||
r,
|
||||
|
|
@ -52,15 +49,25 @@ func (p *parser) init(file *src.PosBase, r io.Reader, errh ErrorHandler, pragh P
|
|||
|
||||
// otherwise it must be a comment containing a line or go: directive
|
||||
text := commentText(msg)
|
||||
col += 2 // text starts after // or /*
|
||||
if strings.HasPrefix(text, "line ") {
|
||||
p.updateBase(line, col+5, text[5:])
|
||||
var pos Pos // position immediately following the comment
|
||||
if msg[1] == '/' {
|
||||
// line comment
|
||||
pos = MakePos(p.file, line+1, colbase)
|
||||
} else {
|
||||
// regular comment
|
||||
// (if the comment spans multiple lines it's not
|
||||
// a valid line directive and will be discarded
|
||||
// by updateBase)
|
||||
pos = MakePos(p.file, line, col+uint(len(msg)))
|
||||
}
|
||||
p.updateBase(pos, line, col+2+5, text[5:]) // +2 to skip over // or /*
|
||||
return
|
||||
}
|
||||
|
||||
// go: directive (but be conservative and test)
|
||||
if pragh != nil && strings.HasPrefix(text, "go:") {
|
||||
p.pragma |= pragh(p.posAt(line, col), text)
|
||||
p.pragma |= pragh(p.posAt(line, col+2), text) // +2 to skip over // or /*
|
||||
}
|
||||
},
|
||||
directives,
|
||||
|
|
@ -76,9 +83,7 @@ func (p *parser) init(file *src.PosBase, r io.Reader, errh ErrorHandler, pragh P
|
|||
p.indent = nil
|
||||
}
|
||||
|
||||
const lineMax = 1<<24 - 1 // TODO(gri) this limit is defined for src.Pos - fix
|
||||
|
||||
func (p *parser) updateBase(line, col uint, text string) {
|
||||
func (p *parser) updateBase(pos Pos, line, col uint, text string) {
|
||||
i, n, ok := trailingDigits(text)
|
||||
if i == 0 {
|
||||
return // ignore (not a line directive)
|
||||
|
|
@ -96,26 +101,25 @@ func (p *parser) updateBase(line, col uint, text string) {
|
|||
//line filename:line:col
|
||||
i, i2 = i2, i
|
||||
n, n2 = n2, n
|
||||
if n2 == 0 {
|
||||
if n2 == 0 || n2 > PosMax {
|
||||
p.errorAt(p.posAt(line, col+i2), "invalid column number: "+text[i2:])
|
||||
return
|
||||
}
|
||||
text = text[:i2-1] // lop off :col
|
||||
} else {
|
||||
//line filename:line
|
||||
n2 = colbase // use start of line for column
|
||||
}
|
||||
|
||||
if n == 0 || n > lineMax {
|
||||
if n == 0 || n > PosMax {
|
||||
p.errorAt(p.posAt(line, col+i), "invalid line number: "+text[i:])
|
||||
return
|
||||
}
|
||||
|
||||
filename := text[:i-1] // lop off :line
|
||||
absFilename := filename
|
||||
if p.fileh != nil {
|
||||
absFilename = p.fileh(filename)
|
||||
}
|
||||
// TODO(gri) handle case where filename doesn't change (see #22662)
|
||||
|
||||
// TODO(gri) pass column n2 to NewLinePragmaBase
|
||||
p.base = src.NewLinePragmaBase(src.MakePos(p.file, line, col), filename, absFilename, uint(n) /*uint(n2)*/)
|
||||
p.base = NewLineBase(pos, filename, n, n2)
|
||||
}
|
||||
|
||||
func commentText(s string) string {
|
||||
|
|
@ -162,12 +166,12 @@ func (p *parser) want(tok token) {
|
|||
// Error handling
|
||||
|
||||
// posAt returns the Pos value for (line, col) and the current position base.
|
||||
func (p *parser) posAt(line, col uint) src.Pos {
|
||||
return src.MakePos(p.base, line, col)
|
||||
func (p *parser) posAt(line, col uint) Pos {
|
||||
return MakePos(p.base, line, col)
|
||||
}
|
||||
|
||||
// error reports an error at the given position.
|
||||
func (p *parser) errorAt(pos src.Pos, msg string) {
|
||||
func (p *parser) errorAt(pos Pos, msg string) {
|
||||
err := Error{pos, msg}
|
||||
if p.first == nil {
|
||||
p.first = err
|
||||
|
|
@ -180,7 +184,7 @@ func (p *parser) errorAt(pos src.Pos, msg string) {
|
|||
}
|
||||
|
||||
// syntaxErrorAt reports a syntax error at the given position.
|
||||
func (p *parser) syntaxErrorAt(pos src.Pos, msg string) {
|
||||
func (p *parser) syntaxErrorAt(pos Pos, msg string) {
|
||||
if trace {
|
||||
p.print("syntax error: " + msg)
|
||||
}
|
||||
|
|
@ -237,7 +241,7 @@ func tokstring(tok token) string {
|
|||
}
|
||||
|
||||
// Convenience methods using the current token position.
|
||||
func (p *parser) pos() src.Pos { return p.posAt(p.line, p.col) }
|
||||
func (p *parser) pos() Pos { return p.posAt(p.line, p.col) }
|
||||
func (p *parser) syntaxError(msg string) { p.syntaxErrorAt(p.pos(), msg) }
|
||||
|
||||
// The stopset contains keywords that start a statement.
|
||||
|
|
@ -417,7 +421,7 @@ func isEmptyFuncDecl(dcl Decl) bool {
|
|||
// list = "(" { f sep } ")" |
|
||||
// "{" { f sep } "}" . // sep is optional before ")" or "}"
|
||||
//
|
||||
func (p *parser) list(open, sep, close token, f func() bool) src.Pos {
|
||||
func (p *parser) list(open, sep, close token, f func() bool) Pos {
|
||||
p.want(open)
|
||||
|
||||
var done bool
|
||||
|
|
@ -1064,7 +1068,7 @@ func (p *parser) type_() Expr {
|
|||
return typ
|
||||
}
|
||||
|
||||
func newIndirect(pos src.Pos, typ Expr) Expr {
|
||||
func newIndirect(pos Pos, typ Expr) Expr {
|
||||
o := new(Operation)
|
||||
o.pos = pos
|
||||
o.Op = Mul
|
||||
|
|
@ -1276,7 +1280,7 @@ func (p *parser) funcResult() []*Field {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *parser) addField(styp *StructType, pos src.Pos, name *Name, typ Expr, tag *BasicLit) {
|
||||
func (p *parser) addField(styp *StructType, pos Pos, name *Name, typ Expr, tag *BasicLit) {
|
||||
if tag != nil {
|
||||
for i := len(styp.FieldList) - len(styp.TagList); i > 0; i-- {
|
||||
styp.TagList = append(styp.TagList, nil)
|
||||
|
|
@ -1694,7 +1698,7 @@ func (p *parser) newRangeClause(lhs Expr, def bool) *RangeClause {
|
|||
return r
|
||||
}
|
||||
|
||||
func (p *parser) newAssignStmt(pos src.Pos, op Operator, lhs, rhs Expr) *AssignStmt {
|
||||
func (p *parser) newAssignStmt(pos Pos, op Operator, lhs, rhs Expr) *AssignStmt {
|
||||
a := new(AssignStmt)
|
||||
a.pos = pos
|
||||
a.Op = op
|
||||
|
|
@ -1818,7 +1822,7 @@ func (p *parser) header(keyword token) (init SimpleStmt, cond Expr, post SimpleS
|
|||
|
||||
var condStmt SimpleStmt
|
||||
var semi struct {
|
||||
pos src.Pos
|
||||
pos Pos
|
||||
lit string // valid if pos.IsKnown()
|
||||
}
|
||||
if p.tok != _Lbrace {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue