[dev.regabi] cmd/compile: introduce cmd/compile/internal/base [generated]

Move Flag, Debug, Ctxt, Exit, and error messages to
new package cmd/compile/internal/base.

These are the core functionality that everything in gc uses
and which otherwise prevent splitting any other code
out of gc into different packages.

A minor milestone: the compiler source code
no longer contains the string "yy".

[git-generate]
cd src/cmd/compile/internal/gc
rf '
        mv atExit AtExit
        mv Ctxt atExitFuncs AtExit Exit base.go

        mv lineno Pos
        mv linestr FmtPos
        mv flusherrors FlushErrors
        mv yyerror Errorf
        mv yyerrorl ErrorfAt
        mv yyerrorv ErrorfVers
        mv noder.yyerrorpos noder.errorAt
        mv Warnl WarnfAt
        mv errorexit ErrorExit

        mv base.go debug.go flag.go print.go cmd/compile/internal/base
'

: # update comments
sed -i '' 's/yyerrorl/ErrorfAt/g; s/yyerror/Errorf/g' *.go

: # bootstrap.go is not built by default so invisible to rf
sed -i '' 's/Fatalf/base.Fatalf/' bootstrap.go
goimports -w bootstrap.go

: # update cmd/dist to add internal/base
cd ../../../dist
sed -i '' '/internal.amd64/a\
	"cmd/compile/internal/base",
' buildtool.go
gofmt -w buildtool.go

Change-Id: I59903c7084222d6eaee38823fd222159ba24a31a
Reviewed-on: https://go-review.googlesource.com/c/go/+/272250
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Russ Cox 2020-11-19 20:49:23 -05:00
parent eb3086e5a8
commit 26b66fd60b
67 changed files with 1626 additions and 1542 deletions

View file

@ -16,6 +16,7 @@ import (
"unicode"
"unicode/utf8"
"cmd/compile/internal/base"
"cmd/compile/internal/syntax"
"cmd/compile/internal/types"
"cmd/internal/obj"
@ -59,15 +60,15 @@ func parseFiles(filenames []string) uint {
var lines uint
for _, p := range noders {
for e := range p.err {
p.yyerrorpos(e.Pos, "%s", e.Msg)
p.errorAt(e.Pos, "%s", e.Msg)
}
p.node()
lines += p.file.Lines
p.file = nil // release memory
if SyntaxErrors() != 0 {
errorexit()
if base.SyntaxErrors() != 0 {
base.ErrorExit()
}
// Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
testdclstack()
@ -111,20 +112,20 @@ func (p *noder) makeSrcPosBase(b0 *syntax.PosBase) *src.PosBase {
}
func (p *noder) makeXPos(pos syntax.Pos) (_ src.XPos) {
return Ctxt.PosTable.XPos(src.MakePos(p.makeSrcPosBase(pos.Base()), pos.Line(), pos.Col()))
return base.Ctxt.PosTable.XPos(src.MakePos(p.makeSrcPosBase(pos.Base()), pos.Line(), pos.Col()))
}
func (p *noder) yyerrorpos(pos syntax.Pos, format string, args ...interface{}) {
yyerrorl(p.makeXPos(pos), format, args...)
func (p *noder) errorAt(pos syntax.Pos, format string, args ...interface{}) {
base.ErrorfAt(p.makeXPos(pos), format, args...)
}
// TODO(gri) Can we eliminate fileh in favor of absFilename?
func fileh(name string) string {
return objabi.AbsFile("", name, Flag.TrimPath)
return objabi.AbsFile("", name, base.Flag.TrimPath)
}
func absFilename(name string) string {
return objabi.AbsFile(Ctxt.Pathname, name, Flag.TrimPath)
return objabi.AbsFile(base.Ctxt.Pathname, name, base.Flag.TrimPath)
}
// noder transforms package syntax's AST into a Node tree.
@ -162,8 +163,8 @@ func (p *noder) funcBody(fn *Node, block *syntax.BlockStmt) {
}
fn.Nbody.Set(body)
lineno = p.makeXPos(block.Rbrace)
fn.Func.Endlineno = lineno
base.Pos = p.makeXPos(block.Rbrace)
fn.Func.Endlineno = base.Pos
}
funcbody()
@ -193,7 +194,7 @@ func (p *noder) closeScope(pos syntax.Pos) {
// no variables were declared in this scope, so we can retract it.
if int(p.scope) != len(Curfn.Func.Parents) {
Fatalf("scope tracking inconsistency, no variables declared but scopes were not retracted")
base.Fatalf("scope tracking inconsistency, no variables declared but scopes were not retracted")
}
p.scope = Curfn.Func.Parents[p.scope-1]
@ -258,7 +259,7 @@ func (p *noder) node() {
for _, n := range p.linknames {
if !p.importedUnsafe {
p.yyerrorpos(n.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")
p.errorAt(n.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")
continue
}
s := lookup(n.local)
@ -267,10 +268,10 @@ func (p *noder) node() {
} else {
// Use the default object symbol name if the
// user didn't provide one.
if Ctxt.Pkgpath == "" {
p.yyerrorpos(n.pos, "//go:linkname requires linkname argument or -p compiler flag")
if base.Ctxt.Pkgpath == "" {
p.errorAt(n.pos, "//go:linkname requires linkname argument or -p compiler flag")
} else {
s.Linkname = objabi.PathToPrefix(Ctxt.Pkgpath) + "." + n.local
s.Linkname = objabi.PathToPrefix(base.Ctxt.Pkgpath) + "." + n.local
}
}
}
@ -288,7 +289,7 @@ func (p *noder) node() {
}
pragcgobuf = append(pragcgobuf, p.pragcgobuf...)
lineno = src.NoXPos
base.Pos = src.NoXPos
clearImports()
}
@ -332,8 +333,8 @@ func (p *noder) importDecl(imp *syntax.ImportDecl) {
ipkg := importfile(p.basicLit(imp.Path))
if ipkg == nil {
if Errors() == 0 {
Fatalf("phase error in import")
if base.Errors() == 0 {
base.Fatalf("phase error in import")
}
return
}
@ -363,7 +364,7 @@ func (p *noder) importDecl(imp *syntax.ImportDecl) {
importdot(ipkg, pack)
return
case "init":
yyerrorl(pack.Pos, "cannot import package as init - init must be a func")
base.ErrorfAt(pack.Pos, "cannot import package as init - init must be a func")
return
case "_":
return
@ -393,7 +394,7 @@ func (p *noder) varDecl(decl *syntax.VarDecl) []*Node {
// so at that point it hasn't seen the imports.
// We're left to check now, just before applying the //go:embed lines.
for _, e := range pragma.Embeds {
p.yyerrorpos(e.Pos, "//go:embed only allowed in Go files that import \"embed\"")
p.errorAt(e.Pos, "//go:embed only allowed in Go files that import \"embed\"")
}
} else {
exprs = varEmbed(p, names, typ, exprs, pragma.Embeds)
@ -437,7 +438,7 @@ func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []*Node {
cs.typ, cs.values = typ, values
} else {
if typ != nil {
yyerror("const declaration cannot have type without expression")
base.Errorf("const declaration cannot have type without expression")
}
typ, values = cs.typ, cs.values
}
@ -445,7 +446,7 @@ func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []*Node {
nn := make([]*Node, 0, len(names))
for i, n := range names {
if i >= len(values) {
yyerror("missing value in const declaration")
base.Errorf("missing value in const declaration")
break
}
v := values[i]
@ -464,7 +465,7 @@ func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []*Node {
}
if len(values) > len(names) {
yyerror("extra expression in const declaration")
base.Errorf("extra expression in const declaration")
}
cs.iota++
@ -493,7 +494,7 @@ func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node {
nod := p.nod(decl, ODCLTYPE, n, nil)
if param.Alias() && !langSupported(1, 9, localpkg) {
yyerrorl(nod.Pos, "type aliases only supported as of -lang=go1.9")
base.ErrorfAt(nod.Pos, "type aliases only supported as of -lang=go1.9")
}
return nod
}
@ -521,13 +522,13 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node {
if name.Name == "init" {
name = renameinit()
if t.List.Len() > 0 || t.Rlist.Len() > 0 {
yyerrorl(f.Pos, "func init must have no arguments and no return values")
base.ErrorfAt(f.Pos, "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 {
yyerrorl(f.Pos, "func main must have no arguments and no return values")
base.ErrorfAt(f.Pos, "func main must have no arguments and no return values")
}
}
} else {
@ -542,7 +543,7 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node {
if pragma, ok := fun.Pragma.(*Pragma); ok {
f.Func.Pragma = pragma.Flag & FuncPragmas
if pragma.Flag&Systemstack != 0 && pragma.Flag&Nosplit != 0 {
yyerrorl(f.Pos, "go:nosplit and go:systemstack cannot be combined")
base.ErrorfAt(f.Pos, "go:nosplit and go:systemstack cannot be combined")
}
pragma.Flag &^= FuncPragmas
p.checkUnused(pragma)
@ -556,10 +557,10 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node {
if fun.Body != nil {
if f.Func.Pragma&Noescape != 0 {
yyerrorl(f.Pos, "can only use //go:noescape with external func implementations")
base.ErrorfAt(f.Pos, "can only use //go:noescape with external func implementations")
}
} else {
if Flag.Complete || strings.HasPrefix(f.funcname(), "init.") {
if base.Flag.Complete || strings.HasPrefix(f.funcname(), "init.") {
// Linknamed functions are allowed to have no body. Hopefully
// the linkname target has a body. See issue 23311.
isLinknamed := false
@ -570,7 +571,7 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node {
}
}
if !isLinknamed {
yyerrorl(f.Pos, "missing function body")
base.ErrorfAt(f.Pos, "missing function body")
}
}
}
@ -610,13 +611,13 @@ func (p *noder) param(param *syntax.Field, dddOk, final bool) *Node {
if typ.Op == ODDD {
if !dddOk {
// We mark these as syntax errors to get automatic elimination
// of multiple such errors per line (see yyerrorl in subr.go).
yyerror("syntax error: cannot use ... in receiver or result parameter list")
// of multiple such errors per line (see ErrorfAt in subr.go).
base.Errorf("syntax error: cannot use ... in receiver or result parameter list")
} else if !final {
if param.Name == nil {
yyerror("syntax error: cannot use ... with non-final parameter")
base.Errorf("syntax error: cannot use ... with non-final parameter")
} else {
p.yyerrorpos(param.Name.Pos(), "syntax error: cannot use ... with non-final parameter %s", param.Name.Value)
p.errorAt(param.Name.Pos(), "syntax error: cannot use ... with non-final parameter %s", param.Name.Value)
}
}
typ.Op = OTARRAY
@ -670,7 +671,7 @@ func (p *noder) expr(expr syntax.Expr) *Node {
l[i] = p.wrapname(expr.ElemList[i], e)
}
n.List.Set(l)
lineno = p.makeXPos(expr.Rbrace)
base.Pos = p.makeXPos(expr.Rbrace)
return n
case *syntax.KeyValueExpr:
// use position of expr.Key rather than of expr (which has position of ':')
@ -752,7 +753,7 @@ func (p *noder) expr(expr syntax.Expr) *Node {
if expr.Lhs != nil {
n.Left = p.declName(expr.Lhs)
if n.Left.isBlank() {
yyerror("invalid variable name %v in type switch", n.Left)
base.Errorf("invalid variable name %v in type switch", n.Left)
}
}
return n
@ -916,12 +917,12 @@ func (p *noder) packname(expr syntax.Expr) *types.Sym {
name := p.name(expr.X.(*syntax.Name))
def := asNode(name.Def)
if def == nil {
yyerror("undefined: %v", name)
base.Errorf("undefined: %v", name)
return name
}
var pkg *types.Pkg
if def.Op != OPACK {
yyerror("%v is not a package", name)
base.Errorf("%v is not a package", name)
pkg = localpkg
} else {
def.Name.SetUsed(true)
@ -1026,7 +1027,7 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) *Node {
op = OCONTINUE
case syntax.Fallthrough:
if !fallOK {
yyerror("fallthrough statement out of place")
base.Errorf("fallthrough statement out of place")
}
op = OFALL
case syntax.Goto:
@ -1066,7 +1067,7 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) *Node {
break
}
if asNode(ln.Sym.Def) != ln {
yyerror("%s is shadowed during return", ln.Sym.Name)
base.Errorf("%s is shadowed during return", ln.Sym.Name)
}
}
}
@ -1107,7 +1108,7 @@ func (p *noder) assignList(expr syntax.Expr, defn *Node, colas bool) []*Node {
name, ok := expr.(*syntax.Name)
if !ok {
p.yyerrorpos(expr.Pos(), "non-name %v on left side of :=", p.expr(expr))
p.errorAt(expr.Pos(), "non-name %v on left side of :=", p.expr(expr))
newOrErr = true
continue
}
@ -1118,7 +1119,7 @@ func (p *noder) assignList(expr syntax.Expr, defn *Node, colas bool) []*Node {
}
if seen[sym] {
p.yyerrorpos(expr.Pos(), "%v repeated on left side of :=", sym)
p.errorAt(expr.Pos(), "%v repeated on left side of :=", sym)
newOrErr = true
continue
}
@ -1138,7 +1139,7 @@ func (p *noder) assignList(expr syntax.Expr, defn *Node, colas bool) []*Node {
}
if !newOrErr {
yyerrorl(defn.Pos, "no new variables on left side of :=")
base.ErrorfAt(defn.Pos, "no new variables on left side of :=")
}
return res
}
@ -1256,10 +1257,10 @@ func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node, rbrace
n.Nbody.Set(p.stmtsFall(body, true))
if l := n.Nbody.Len(); l > 0 && n.Nbody.Index(l-1).Op == OFALL {
if tswitch != nil {
yyerror("cannot fallthrough in type switch")
base.Errorf("cannot fallthrough in type switch")
}
if i+1 == len(clauses) {
yyerror("cannot fallthrough final case in switch")
base.Errorf("cannot fallthrough final case in switch")
}
}
@ -1378,7 +1379,7 @@ func checkLangCompat(lit *syntax.BasicLit) {
}
// len(s) > 2
if strings.Contains(s, "_") {
yyerrorv("go1.13", "underscores in numeric literals")
base.ErrorfVers("go1.13", "underscores in numeric literals")
return
}
if s[0] != '0' {
@ -1386,15 +1387,15 @@ func checkLangCompat(lit *syntax.BasicLit) {
}
radix := s[1]
if radix == 'b' || radix == 'B' {
yyerrorv("go1.13", "binary literals")
base.ErrorfVers("go1.13", "binary literals")
return
}
if radix == 'o' || radix == 'O' {
yyerrorv("go1.13", "0o/0O-style octal literals")
base.ErrorfVers("go1.13", "0o/0O-style octal literals")
return
}
if lit.Kind != syntax.IntLit && (radix == 'x' || radix == 'X') {
yyerrorv("go1.13", "hexadecimal floating-point literals")
base.ErrorfVers("go1.13", "hexadecimal floating-point literals")
}
}
@ -1415,7 +1416,7 @@ func (p *noder) basicLit(lit *syntax.BasicLit) constant.Value {
v := constant.MakeFromLiteral(lit.Value, tokenForLitKind[lit.Kind], 0)
if v.Kind() == constant.Unknown {
// TODO(mdempsky): Better error message?
p.yyerrorpos(lit.Pos(), "malformed constant: %s", lit.Value)
p.errorAt(lit.Pos(), "malformed constant: %s", lit.Value)
}
// go/constant uses big.Rat by default, which is more precise, but
@ -1474,7 +1475,7 @@ func (p *noder) nodSym(orig syntax.Node, op Op, left *Node, sym *types.Sym) *Nod
func (p *noder) pos(n syntax.Node) src.XPos {
// TODO(gri): orig.Pos() should always be known - fix package syntax
xpos := lineno
xpos := base.Pos
if pos := n.Pos(); pos.IsKnown() {
xpos = p.makeXPos(pos)
}
@ -1483,7 +1484,7 @@ func (p *noder) pos(n syntax.Node) src.XPos {
func (p *noder) setlineno(n syntax.Node) {
if n != nil {
lineno = p.pos(n)
base.Pos = p.pos(n)
}
}
@ -1525,12 +1526,12 @@ type PragmaEmbed struct {
func (p *noder) checkUnused(pragma *Pragma) {
for _, pos := range pragma.Pos {
if pos.Flag&pragma.Flag != 0 {
p.yyerrorpos(pos.Pos, "misplaced compiler directive")
p.errorAt(pos.Pos, "misplaced compiler directive")
}
}
if len(pragma.Embeds) > 0 {
for _, e := range pragma.Embeds {
p.yyerrorpos(e.Pos, "misplaced go:embed directive")
p.errorAt(e.Pos, "misplaced go:embed directive")
}
}
}
@ -1619,7 +1620,7 @@ func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.P
// For security, we disallow //go:cgo_* directives other
// than cgo_import_dynamic outside cgo-generated files.
// Exception: they are allowed in the standard library, for runtime and syscall.
if !isCgoGeneratedFile(pos) && !Flag.Std {
if !isCgoGeneratedFile(pos) && !base.Flag.Std {
p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in cgo-generated code", text)})
}
p.pragcgo(pos, text)
@ -1631,10 +1632,10 @@ func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.P
}
flag := pragmaFlag(verb)
const runtimePragmas = Systemstack | Nowritebarrier | Nowritebarrierrec | Yeswritebarrierrec
if !Flag.CompilingRuntime && flag&runtimePragmas != 0 {
if !base.Flag.CompilingRuntime && flag&runtimePragmas != 0 {
p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in runtime", verb)})
}
if flag == 0 && !allowedStdPragmas[verb] && Flag.Std {
if flag == 0 && !allowedStdPragmas[verb] && base.Flag.Std {
p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s is not allowed in the standard library", verb)})
}
pragma.Flag |= flag