]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: remove a bunch of dead noder code
authorMatthew Dempsky <mdempsky@google.com>
Mon, 28 Feb 2022 22:35:52 +0000 (14:35 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Tue, 1 Mar 2022 19:45:51 +0000 (19:45 +0000)
This code was only needed for supporting -G=0 mode, which is now gone.

Change-Id: I504887ab179e357a3cd21ef582f9edae49f6cbb6
Reviewed-on: https://go-review.googlesource.com/c/go/+/388536
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/noder/import.go
src/cmd/compile/internal/noder/noder.go

index 58dffbad1e4d5c0c11850383ea5e391d9d6ea59d..0898a298ebc5496095a95bb9079927a04e457522 100644 (file)
@@ -11,7 +11,6 @@ import (
        "os"
        pathpkg "path"
        "runtime"
-       "sort"
        "strconv"
        "strings"
        "unicode"
@@ -20,7 +19,6 @@ import (
        "cmd/compile/internal/base"
        "cmd/compile/internal/importer"
        "cmd/compile/internal/ir"
-       "cmd/compile/internal/syntax"
        "cmd/compile/internal/typecheck"
        "cmd/compile/internal/types"
        "cmd/compile/internal/types2"
@@ -28,7 +26,6 @@ import (
        "cmd/internal/bio"
        "cmd/internal/goobj"
        "cmd/internal/objabi"
-       "cmd/internal/src"
 )
 
 // haveLegacyImports records whether we've imported any packages
@@ -141,10 +138,6 @@ func openPackage(path string) (*os.File, error) {
        return nil, errors.New("file not found")
 }
 
-// myheight tracks the local package's height based on packages
-// imported so far.
-var myheight int
-
 // resolveImportPath resolves an import path as it appears in a Go
 // source file to the package's full path.
 func resolveImportPath(path string) (string, error) {
@@ -187,42 +180,6 @@ func resolveImportPath(path string) (string, error) {
        return path, nil
 }
 
-func importfile(decl *syntax.ImportDecl) *types.Pkg {
-       path, err := parseImportPath(decl.Path)
-       if err != nil {
-               base.Errorf("%s", err)
-               return nil
-       }
-
-       pkg, _, err := readImportFile(path, typecheck.Target, nil, nil)
-       if err != nil {
-               base.Errorf("%s", err)
-               return nil
-       }
-
-       if pkg != types.UnsafePkg && pkg.Height >= myheight {
-               myheight = pkg.Height + 1
-       }
-       return pkg
-}
-
-func parseImportPath(pathLit *syntax.BasicLit) (string, error) {
-       if pathLit.Kind != syntax.StringLit {
-               return "", errors.New("import path must be a string")
-       }
-
-       path, err := strconv.Unquote(pathLit.Value)
-       if err != nil {
-               return "", errors.New("import path must be a string")
-       }
-
-       if err := checkImportPath(path, false); err != nil {
-               return "", err
-       }
-
-       return path, err
-}
-
 // readImportFile reads the import file for the given package path and
 // returns its types.Pkg representation. If packages is non-nil, the
 // types2.Package representation is also returned.
@@ -467,135 +424,3 @@ func checkImportPath(path string, allowSpace bool) error {
 
        return nil
 }
-
-func pkgnotused(lineno src.XPos, path string, name string) {
-       // If the package was imported with a name other than the final
-       // import path element, show it explicitly in the error message.
-       // Note that this handles both renamed imports and imports of
-       // packages containing unconventional package declarations.
-       // Note that this uses / always, even on Windows, because Go import
-       // paths always use forward slashes.
-       elem := path
-       if i := strings.LastIndex(elem, "/"); i >= 0 {
-               elem = elem[i+1:]
-       }
-       if name == "" || elem == name {
-               base.ErrorfAt(lineno, "imported and not used: %q", path)
-       } else {
-               base.ErrorfAt(lineno, "imported and not used: %q as %s", path, name)
-       }
-}
-
-func mkpackage(pkgname string) {
-       if types.LocalPkg.Name == "" {
-               if pkgname == "_" {
-                       base.Errorf("invalid package name _")
-               }
-               types.LocalPkg.Name = pkgname
-       } else {
-               if pkgname != types.LocalPkg.Name {
-                       base.Errorf("package %s; expected %s", pkgname, types.LocalPkg.Name)
-               }
-       }
-}
-
-func clearImports() {
-       type importedPkg struct {
-               pos  src.XPos
-               path string
-               name string
-       }
-       var unused []importedPkg
-
-       for _, s := range types.LocalPkg.Syms {
-               n := ir.AsNode(s.Def)
-               if n == nil {
-                       continue
-               }
-               if n.Op() == ir.OPACK {
-                       // throw away top-level package name left over
-                       // from previous file.
-                       // leave s->block set to cause redeclaration
-                       // errors if a conflicting top-level name is
-                       // introduced by a different file.
-                       p := n.(*ir.PkgName)
-                       if !p.Used && base.SyntaxErrors() == 0 {
-                               unused = append(unused, importedPkg{p.Pos(), p.Pkg.Path, s.Name})
-                       }
-                       s.Def = nil
-                       continue
-               }
-               if s.Def != nil && s.Def.Sym() != s {
-                       // throw away top-level name left over
-                       // from previous import . "x"
-                       // We'll report errors after type checking in CheckDotImports.
-                       s.Def = nil
-                       continue
-               }
-       }
-
-       sort.Slice(unused, func(i, j int) bool { return unused[i].pos.Before(unused[j].pos) })
-       for _, pkg := range unused {
-               pkgnotused(pkg.pos, pkg.path, pkg.name)
-       }
-}
-
-// CheckDotImports reports errors for any unused dot imports.
-func CheckDotImports() {
-       for _, pack := range dotImports {
-               if !pack.Used {
-                       base.ErrorfAt(pack.Pos(), "imported and not used: %q", pack.Pkg.Path)
-               }
-       }
-
-       // No longer needed; release memory.
-       dotImports = nil
-       typecheck.DotImportRefs = nil
-}
-
-// dotImports tracks all PkgNames that have been dot-imported.
-var dotImports []*ir.PkgName
-
-// find all the exported symbols in package referenced by PkgName,
-// and make them available in the current package
-func importDot(pack *ir.PkgName) {
-       if typecheck.DotImportRefs == nil {
-               typecheck.DotImportRefs = make(map[*ir.Ident]*ir.PkgName)
-       }
-
-       opkg := pack.Pkg
-       for _, s := range opkg.Syms {
-               if s.Def == nil {
-                       if _, ok := typecheck.DeclImporter[s]; !ok {
-                               continue
-                       }
-               }
-               if !types.IsExported(s.Name) || strings.ContainsRune(s.Name, 0xb7) { // 0xb7 = center dot
-                       continue
-               }
-               s1 := typecheck.Lookup(s.Name)
-               if s1.Def != nil {
-                       pkgerror := fmt.Sprintf("during import %q", opkg.Path)
-                       typecheck.Redeclared(base.Pos, s1, pkgerror)
-                       continue
-               }
-
-               id := ir.NewIdent(src.NoXPos, s)
-               typecheck.DotImportRefs[id] = pack
-               s1.Def = id
-               s1.Block = 1
-       }
-
-       dotImports = append(dotImports, pack)
-}
-
-// importName is like oldname,
-// but it reports an error if sym is from another package and not exported.
-func importName(sym *types.Sym) ir.Node {
-       n := oldname(sym)
-       if !types.IsExported(sym.Name) && sym.Pkg != types.LocalPkg {
-               n.SetDiag(true)
-               base.Errorf("cannot refer to unexported name %s.%s", sym.Pkg.Name, sym.Name)
-       }
-       return n
-}
index 2cd7218c55c6b97dd456bd9fc99e124526c9ebaf..7d84c2dab9aec67c5c4949baab296ad3bcffb6b5 100644 (file)
@@ -7,8 +7,6 @@ package noder
 import (
        "errors"
        "fmt"
-       "go/constant"
-       "go/token"
        "os"
        "path/filepath"
        "runtime"
@@ -18,7 +16,6 @@ import (
        "unicode/utf8"
 
        "cmd/compile/internal/base"
-       "cmd/compile/internal/dwarfgen"
        "cmd/compile/internal/ir"
        "cmd/compile/internal/syntax"
        "cmd/compile/internal/typecheck"
@@ -38,8 +35,7 @@ func LoadPackage(filenames []string) {
        noders := make([]*noder, len(filenames))
        for i, filename := range filenames {
                p := noder{
-                       err:         make(chan syntax.Error),
-                       trackScopes: base.Flag.Dwarf,
+                       err: make(chan syntax.Error),
                }
                noders[i] = &p
 
@@ -115,76 +111,6 @@ type noder struct {
        err            chan syntax.Error
        importedUnsafe bool
        importedEmbed  bool
-       trackScopes    bool
-
-       funcState *funcState
-}
-
-// funcState tracks all per-function state to make handling nested
-// functions easier.
-type funcState struct {
-       // scopeVars is a stack tracking the number of variables declared in
-       // the current function at the moment each open scope was opened.
-       scopeVars []int
-       marker    dwarfgen.ScopeMarker
-
-       lastCloseScopePos syntax.Pos
-}
-
-func (p *noder) funcBody(fn *ir.Func, block *syntax.BlockStmt) {
-       outerFuncState := p.funcState
-       p.funcState = new(funcState)
-       typecheck.StartFuncBody(fn)
-
-       if block != nil {
-               body := p.stmts(block.List)
-               if body == nil {
-                       body = []ir.Node{ir.NewBlockStmt(base.Pos, nil)}
-               }
-               fn.Body = body
-
-               base.Pos = p.makeXPos(block.Rbrace)
-               fn.Endlineno = base.Pos
-       }
-
-       typecheck.FinishFuncBody()
-       p.funcState.marker.WriteTo(fn)
-       p.funcState = outerFuncState
-}
-
-func (p *noder) openScope(pos syntax.Pos) {
-       fs := p.funcState
-       types.Markdcl()
-
-       if p.trackScopes {
-               fs.scopeVars = append(fs.scopeVars, len(ir.CurFunc.Dcl))
-               fs.marker.Push(p.makeXPos(pos))
-       }
-}
-
-func (p *noder) closeScope(pos syntax.Pos) {
-       fs := p.funcState
-       fs.lastCloseScopePos = pos
-       types.Popdcl()
-
-       if p.trackScopes {
-               scopeVars := fs.scopeVars[len(fs.scopeVars)-1]
-               fs.scopeVars = fs.scopeVars[:len(fs.scopeVars)-1]
-               if scopeVars == len(ir.CurFunc.Dcl) {
-                       // no variables were declared in this scope, so we can retract it.
-                       fs.marker.Unpush()
-               } else {
-                       fs.marker.Pop(p.makeXPos(pos))
-               }
-       }
-}
-
-// closeAnotherScope is like closeScope, but it reuses the same mark
-// position as the last closeScope call. This is useful for "for" and
-// "if" statements, as their implicit blocks always end at the same
-// position as an explicit block.
-func (p *noder) closeAnotherScope() {
-       p.closeScope(p.funcState.lastCloseScopePos)
 }
 
 // linkname records a //go:linkname directive.
@@ -194,24 +120,6 @@ type linkname struct {
        remote string
 }
 
-func (p *noder) node() {
-       p.importedUnsafe = false
-       p.importedEmbed = false
-
-       p.setlineno(p.file.PkgName)
-       mkpackage(p.file.PkgName.Value)
-
-       if pragma, ok := p.file.Pragma.(*pragmas); ok {
-               pragma.Flag &^= ir.GoBuildPragma
-               p.checkUnused(pragma)
-       }
-
-       typecheck.Target.Decls = append(typecheck.Target.Decls, p.decls(p.file.DeclList)...)
-
-       base.Pos = src.NoXPos
-       clearImports()
-}
-
 func (p *noder) processPragmas() {
        for _, l := range p.linknames {
                if !p.importedUnsafe {
@@ -232,1074 +140,6 @@ func (p *noder) processPragmas() {
        typecheck.Target.CgoPragmas = append(typecheck.Target.CgoPragmas, p.pragcgobuf...)
 }
 
-func (p *noder) decls(decls []syntax.Decl) (l []ir.Node) {
-       var cs constState
-
-       for _, decl := range decls {
-               p.setlineno(decl)
-               switch decl := decl.(type) {
-               case *syntax.ImportDecl:
-                       p.importDecl(decl)
-
-               case *syntax.VarDecl:
-                       l = append(l, p.varDecl(decl)...)
-
-               case *syntax.ConstDecl:
-                       l = append(l, p.constDecl(decl, &cs)...)
-
-               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) {
-       if imp.Path == nil || imp.Path.Bad {
-               return // avoid follow-on errors if there was a syntax error
-       }
-
-       if pragma, ok := imp.Pragma.(*pragmas); ok {
-               p.checkUnused(pragma)
-       }
-
-       ipkg := importfile(imp)
-       if ipkg == nil {
-               if base.Errors() == 0 {
-                       base.Fatalf("phase error in import")
-               }
-               return
-       }
-
-       if ipkg == types.UnsafePkg {
-               p.importedUnsafe = true
-       }
-       if ipkg.Path == "embed" {
-               p.importedEmbed = true
-       }
-
-       var my *types.Sym
-       if imp.LocalPkgName != nil {
-               my = p.name(imp.LocalPkgName)
-       } else {
-               my = typecheck.Lookup(ipkg.Name)
-       }
-
-       pack := ir.NewPkgName(p.pos(imp), my, ipkg)
-
-       switch my.Name {
-       case ".":
-               importDot(pack)
-               return
-       case "init":
-               base.ErrorfAt(pack.Pos(), "cannot import package as init - init must be a func")
-               return
-       case "_":
-               return
-       }
-       if my.Def != nil {
-               typecheck.Redeclared(pack.Pos(), 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) []ir.Node {
-       names := p.declNames(ir.ONAME, decl.NameList)
-       typ := p.typeExprOrNil(decl.Type)
-       exprs := p.exprList(decl.Values)
-
-       if pragma, ok := decl.Pragma.(*pragmas); ok {
-               varEmbed(p.makeXPos, names[0], decl, pragma, p.importedEmbed)
-               p.checkUnused(pragma)
-       }
-
-       var init []ir.Node
-       p.setlineno(decl)
-
-       if len(names) > 1 && len(exprs) == 1 {
-               as2 := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, exprs)
-               for _, v := range names {
-                       as2.Lhs.Append(v)
-                       typecheck.Declare(v, typecheck.DeclContext)
-                       v.Ntype = typ
-                       v.Defn = as2
-                       if ir.CurFunc != nil {
-                               init = append(init, ir.NewDecl(base.Pos, ir.ODCL, v))
-                       }
-               }
-
-               return append(init, as2)
-       }
-
-       for i, v := range names {
-               var e ir.Node
-               if i < len(exprs) {
-                       e = exprs[i]
-               }
-
-               typecheck.Declare(v, typecheck.DeclContext)
-               v.Ntype = typ
-
-               if ir.CurFunc != nil {
-                       init = append(init, ir.NewDecl(base.Pos, ir.ODCL, v))
-               }
-               as := ir.NewAssignStmt(base.Pos, v, e)
-               init = append(init, as)
-               if e != nil || ir.CurFunc == nil {
-                       v.Defn = as
-               }
-       }
-
-       if len(exprs) != 0 && len(names) != len(exprs) {
-               base.Errorf("assignment mismatch: %d variables but %d values", len(names), len(exprs))
-       }
-
-       return init
-}
-
-// constState tracks state between constant specifiers within a
-// declaration group. This state is kept separate from noder so nested
-// constant declarations are handled correctly (e.g., issue 15550).
-type constState struct {
-       group  *syntax.Group
-       typ    ir.Ntype
-       values syntax.Expr
-       iota   int64
-}
-
-func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []ir.Node {
-       if decl.Group == nil || decl.Group != cs.group {
-               *cs = constState{
-                       group: decl.Group,
-               }
-       }
-
-       if pragma, ok := decl.Pragma.(*pragmas); ok {
-               p.checkUnused(pragma)
-       }
-
-       names := p.declNames(ir.OLITERAL, decl.NameList)
-       typ := p.typeExprOrNil(decl.Type)
-
-       if decl.Values != nil {
-               cs.typ, cs.values = typ, decl.Values
-       } else {
-               if typ != nil {
-                       base.Errorf("const declaration cannot have type without expression")
-               }
-               typ = cs.typ
-       }
-       values := p.exprList(cs.values)
-
-       nn := make([]ir.Node, 0, len(names))
-       for i, n := range names {
-               if i >= len(values) {
-                       base.Errorf("missing value in const declaration")
-                       break
-               }
-
-               v := values[i]
-               if decl.Values == nil {
-                       ir.Visit(v, func(v ir.Node) {
-                               if ir.HasUniquePos(v) {
-                                       v.SetPos(n.Pos())
-                               }
-                       })
-               }
-
-               typecheck.Declare(n, typecheck.DeclContext)
-
-               n.Ntype = typ
-               n.Defn = v
-               n.SetIota(cs.iota)
-
-               nn = append(nn, ir.NewDecl(p.pos(decl), ir.ODCLCONST, n))
-       }
-
-       if len(values) > len(names) {
-               base.Errorf("extra expression in const declaration")
-       }
-
-       cs.iota++
-
-       return nn
-}
-
-func (p *noder) typeDecl(decl *syntax.TypeDecl) ir.Node {
-       n := p.declName(ir.OTYPE, decl.Name)
-       typecheck.Declare(n, typecheck.DeclContext)
-
-       // decl.Type may be nil but in that case we got a syntax error during parsing
-       typ := p.typeExprOrNil(decl.Type)
-
-       n.Ntype = typ
-       n.SetAlias(decl.Alias)
-       if pragma, ok := decl.Pragma.(*pragmas); ok {
-               if !decl.Alias {
-                       n.SetPragma(pragma.Flag & typePragmas)
-                       pragma.Flag &^= typePragmas
-               }
-               p.checkUnused(pragma)
-       }
-
-       nod := ir.NewDecl(p.pos(decl), ir.ODCLTYPE, n)
-       if n.Alias() && !types.AllowsGoVersion(types.LocalPkg, 1, 9) {
-               base.ErrorfAt(nod.Pos(), "type aliases only supported as of -lang=go1.9")
-       }
-       return nod
-}
-
-func (p *noder) declNames(op ir.Op, names []*syntax.Name) []*ir.Name {
-       nodes := make([]*ir.Name, 0, len(names))
-       for _, name := range names {
-               nodes = append(nodes, p.declName(op, name))
-       }
-       return nodes
-}
-
-func (p *noder) declName(op ir.Op, name *syntax.Name) *ir.Name {
-       return ir.NewDeclNameAt(p.pos(name), op, p.name(name))
-}
-
-func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node {
-       name := p.name(fun.Name)
-       t := p.signature(fun.Recv, fun.Type)
-       f := ir.NewFunc(p.pos(fun))
-
-       if fun.Recv == nil {
-               if name.Name == "init" {
-                       name = renameinit()
-                       if len(t.Params) > 0 || len(t.Results) > 0 {
-                               base.ErrorfAt(f.Pos(), "func init must have no arguments and no return values")
-                       }
-                       typecheck.Target.Inits = append(typecheck.Target.Inits, f)
-               }
-
-               if types.LocalPkg.Name == "main" && name.Name == "main" {
-                       if len(t.Params) > 0 || len(t.Results) > 0 {
-                               base.ErrorfAt(f.Pos(), "func main must have no arguments and no return values")
-                       }
-               }
-       } else {
-               f.Shortname = name
-               name = ir.BlankNode.Sym() // filled in by tcFunc
-       }
-
-       f.Nname = ir.NewNameAt(p.pos(fun.Name), name)
-       f.Nname.Func = f
-       f.Nname.Defn = f
-       f.Nname.Ntype = t
-
-       if pragma, ok := fun.Pragma.(*pragmas); ok {
-               f.Pragma = pragma.Flag & funcPragmas
-               if pragma.Flag&ir.Systemstack != 0 && pragma.Flag&ir.Nosplit != 0 {
-                       base.ErrorfAt(f.Pos(), "go:nosplit and go:systemstack cannot be combined")
-               }
-               pragma.Flag &^= funcPragmas
-               p.checkUnused(pragma)
-       }
-
-       if fun.Recv == nil {
-               typecheck.Declare(f.Nname, ir.PFUNC)
-       }
-
-       p.funcBody(f, fun.Body)
-
-       if fun.Body != nil {
-               if f.Pragma&ir.Noescape != 0 {
-                       base.ErrorfAt(f.Pos(), "can only use //go:noescape with external func implementations")
-               }
-       } else {
-               if base.Flag.Complete || strings.HasPrefix(ir.FuncName(f), "init.") {
-                       // Linknamed functions are allowed to have no body. Hopefully
-                       // the linkname target has a body. See issue 23311.
-                       isLinknamed := false
-                       for _, n := range p.linknames {
-                               if ir.FuncName(f) == n.local {
-                                       isLinknamed = true
-                                       break
-                               }
-                       }
-                       if !isLinknamed {
-                               base.ErrorfAt(f.Pos(), "missing function body")
-                       }
-               }
-       }
-
-       return f
-}
-
-func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) *ir.FuncType {
-       var rcvr *ir.Field
-       if recv != nil {
-               rcvr = p.param(recv, false, false)
-       }
-       return ir.NewFuncType(p.pos(typ), rcvr,
-               p.params(typ.ParamList, true),
-               p.params(typ.ResultList, false))
-}
-
-func (p *noder) params(params []*syntax.Field, dddOk bool) []*ir.Field {
-       nodes := make([]*ir.Field, 0, len(params))
-       for i, param := range params {
-               p.setlineno(param)
-               nodes = append(nodes, p.param(param, dddOk, i+1 == len(params)))
-               if i > 0 && params[i].Type == params[i-1].Type {
-                       nodes[i].Ntype = nodes[i-1].Ntype
-               }
-       }
-       return nodes
-}
-
-func (p *noder) param(param *syntax.Field, dddOk, final bool) *ir.Field {
-       var name *types.Sym
-       if param.Name != nil {
-               name = p.name(param.Name)
-       }
-
-       typ := p.typeExpr(param.Type)
-       n := ir.NewField(p.pos(param), name, typ, nil)
-
-       // rewrite ...T parameter
-       if typ, ok := typ.(*ir.SliceType); ok && typ.DDD {
-               if !dddOk {
-                       // We mark these as syntax errors to get automatic elimination
-                       // 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 {
-                               base.Errorf("syntax error: cannot use ... with non-final parameter")
-                       } else {
-                               p.errorAt(param.Name.Pos(), "syntax error: cannot use ... with non-final parameter %s", param.Name.Value)
-                       }
-               }
-               typ.DDD = false
-               n.IsDDD = true
-       }
-
-       return n
-}
-
-func (p *noder) exprList(expr syntax.Expr) []ir.Node {
-       switch expr := expr.(type) {
-       case nil:
-               return nil
-       case *syntax.ListExpr:
-               return p.exprs(expr.ElemList)
-       default:
-               return []ir.Node{p.expr(expr)}
-       }
-}
-
-func (p *noder) exprs(exprs []syntax.Expr) []ir.Node {
-       nodes := make([]ir.Node, 0, len(exprs))
-       for _, expr := range exprs {
-               nodes = append(nodes, p.expr(expr))
-       }
-       return nodes
-}
-
-func (p *noder) expr(expr syntax.Expr) ir.Node {
-       p.setlineno(expr)
-       switch expr := expr.(type) {
-       case nil, *syntax.BadExpr:
-               return nil
-       case *syntax.Name:
-               return p.mkname(expr)
-       case *syntax.BasicLit:
-               n := ir.NewBasicLit(p.pos(expr), p.basicLit(expr))
-               if expr.Kind == syntax.RuneLit {
-                       n.SetType(types.UntypedRune)
-               }
-               n.SetDiag(expr.Bad || n.Val().Kind() == constant.Unknown) // avoid follow-on errors if there was a syntax error
-               return n
-       case *syntax.CompositeLit:
-               n := ir.NewCompLitExpr(p.pos(expr), ir.OCOMPLIT, p.typeExpr(expr.Type), nil)
-               l := p.exprs(expr.ElemList)
-               for i, e := range l {
-                       l[i] = p.wrapname(expr.ElemList[i], e)
-               }
-               n.List = l
-               base.Pos = p.makeXPos(expr.Rbrace)
-               return n
-       case *syntax.KeyValueExpr:
-               // use position of expr.Key rather than of expr (which has position of ':')
-               return ir.NewKeyExpr(p.pos(expr.Key), p.expr(expr.Key), p.wrapname(expr.Value, p.expr(expr.Value)))
-       case *syntax.FuncLit:
-               return p.funcLit(expr)
-       case *syntax.ParenExpr:
-               return ir.NewParenExpr(p.pos(expr), p.expr(expr.X))
-       case *syntax.SelectorExpr:
-               // parser.new_dotname
-               obj := p.expr(expr.X)
-               if obj.Op() == ir.OPACK {
-                       pack := obj.(*ir.PkgName)
-                       pack.Used = true
-                       return importName(pack.Pkg.Lookup(expr.Sel.Value))
-               }
-               n := ir.NewSelectorExpr(base.Pos, ir.OXDOT, obj, p.name(expr.Sel))
-               n.SetPos(p.pos(expr)) // lineno may have been changed by p.expr(expr.X)
-               return n
-       case *syntax.IndexExpr:
-               return ir.NewIndexExpr(p.pos(expr), p.expr(expr.X), p.expr(expr.Index))
-       case *syntax.SliceExpr:
-               op := ir.OSLICE
-               if expr.Full {
-                       op = ir.OSLICE3
-               }
-               x := p.expr(expr.X)
-               var index [3]ir.Node
-               for i, n := range &expr.Index {
-                       if n != nil {
-                               index[i] = p.expr(n)
-                       }
-               }
-               return ir.NewSliceExpr(p.pos(expr), op, x, index[0], index[1], index[2])
-       case *syntax.AssertExpr:
-               return ir.NewTypeAssertExpr(p.pos(expr), p.expr(expr.X), p.typeExpr(expr.Type))
-       case *syntax.Operation:
-               if expr.Op == syntax.Add && expr.Y != nil {
-                       return p.sum(expr)
-               }
-               x := p.expr(expr.X)
-               if expr.Y == nil {
-                       pos, op := p.pos(expr), p.unOp(expr.Op)
-                       switch op {
-                       case ir.OADDR:
-                               return typecheck.NodAddrAt(pos, x)
-                       case ir.ODEREF:
-                               return ir.NewStarExpr(pos, x)
-                       }
-                       return ir.NewUnaryExpr(pos, op, x)
-               }
-
-               pos, op, y := p.pos(expr), p.binOp(expr.Op), p.expr(expr.Y)
-               switch op {
-               case ir.OANDAND, ir.OOROR:
-                       return ir.NewLogicalExpr(pos, op, x, y)
-               }
-               return ir.NewBinaryExpr(pos, op, x, y)
-       case *syntax.CallExpr:
-               n := ir.NewCallExpr(p.pos(expr), ir.OCALL, p.expr(expr.Fun), p.exprs(expr.ArgList))
-               n.IsDDD = expr.HasDots
-               return n
-
-       case *syntax.ArrayType:
-               var len ir.Node
-               if expr.Len != nil {
-                       len = p.expr(expr.Len)
-               }
-               return ir.NewArrayType(p.pos(expr), len, p.typeExpr(expr.Elem))
-       case *syntax.SliceType:
-               return ir.NewSliceType(p.pos(expr), p.typeExpr(expr.Elem))
-       case *syntax.DotsType:
-               t := ir.NewSliceType(p.pos(expr), p.typeExpr(expr.Elem))
-               t.DDD = true
-               return t
-       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 ir.NewMapType(p.pos(expr),
-                       p.typeExpr(expr.Key), p.typeExpr(expr.Value))
-       case *syntax.ChanType:
-               return ir.NewChanType(p.pos(expr),
-                       p.typeExpr(expr.Elem), p.chanDir(expr.Dir))
-
-       case *syntax.TypeSwitchGuard:
-               var tag *ir.Ident
-               if expr.Lhs != nil {
-                       tag = ir.NewIdent(p.pos(expr.Lhs), p.name(expr.Lhs))
-                       if ir.IsBlank(tag) {
-                               base.Errorf("invalid variable name %v in type switch", tag)
-                       }
-               }
-               return ir.NewTypeSwitchGuard(p.pos(expr), tag, p.expr(expr.X))
-       }
-       panic("unhandled Expr")
-}
-
-// sum efficiently handles very large summation expressions (such as
-// in issue #16394). In particular, it avoids left recursion and
-// collapses string literals.
-func (p *noder) sum(x syntax.Expr) ir.Node {
-       // While we need to handle long sums with asymptotic
-       // efficiency, the vast majority of sums are very small: ~95%
-       // have only 2 or 3 operands, and ~99% of string literals are
-       // never concatenated.
-
-       adds := make([]*syntax.Operation, 0, 2)
-       for {
-               add, ok := x.(*syntax.Operation)
-               if !ok || add.Op != syntax.Add || add.Y == nil {
-                       break
-               }
-               adds = append(adds, add)
-               x = add.X
-       }
-
-       // nstr is the current rightmost string literal in the
-       // summation (if any), and chunks holds its accumulated
-       // substrings.
-       //
-       // Consider the expression x + "a" + "b" + "c" + y. When we
-       // reach the string literal "a", we assign nstr to point to
-       // its corresponding Node and initialize chunks to {"a"}.
-       // Visiting the subsequent string literals "b" and "c", we
-       // simply append their values to chunks. Finally, when we
-       // reach the non-constant operand y, we'll join chunks to form
-       // "abc" and reassign the "a" string literal's value.
-       //
-       // N.B., we need to be careful about named string constants
-       // (indicated by Sym != nil) because 1) we can't modify their
-       // value, as doing so would affect other uses of the string
-       // constant, and 2) they may have types, which we need to
-       // handle correctly. For now, we avoid these problems by
-       // treating named string constants the same as non-constant
-       // operands.
-       var nstr ir.Node
-       chunks := make([]string, 0, 1)
-
-       n := p.expr(x)
-       if ir.IsConst(n, constant.String) && n.Sym() == nil {
-               nstr = n
-               chunks = append(chunks, ir.StringVal(nstr))
-       }
-
-       for i := len(adds) - 1; i >= 0; i-- {
-               add := adds[i]
-
-               r := p.expr(add.Y)
-               if ir.IsConst(r, constant.String) && r.Sym() == nil {
-                       if nstr != nil {
-                               // Collapse r into nstr instead of adding to n.
-                               chunks = append(chunks, ir.StringVal(r))
-                               continue
-                       }
-
-                       nstr = r
-                       chunks = append(chunks, ir.StringVal(nstr))
-               } else {
-                       if len(chunks) > 1 {
-                               nstr.SetVal(constant.MakeString(strings.Join(chunks, "")))
-                       }
-                       nstr = nil
-                       chunks = chunks[:0]
-               }
-               n = ir.NewBinaryExpr(p.pos(add), ir.OADD, n, r)
-       }
-       if len(chunks) > 1 {
-               nstr.SetVal(constant.MakeString(strings.Join(chunks, "")))
-       }
-
-       return n
-}
-
-func (p *noder) typeExpr(typ syntax.Expr) ir.Ntype {
-       // TODO(mdempsky): Be stricter? typecheck should handle errors anyway.
-       n := p.expr(typ)
-       if n == nil {
-               return nil
-       }
-       return n.(ir.Ntype)
-}
-
-func (p *noder) typeExprOrNil(typ syntax.Expr) ir.Ntype {
-       if typ != nil {
-               return p.typeExpr(typ)
-       }
-       return nil
-}
-
-func (p *noder) chanDir(dir syntax.ChanDir) types.ChanDir {
-       switch dir {
-       case 0:
-               return types.Cboth
-       case syntax.SendOnly:
-               return types.Csend
-       case syntax.RecvOnly:
-               return types.Crecv
-       }
-       panic("unhandled ChanDir")
-}
-
-func (p *noder) structType(expr *syntax.StructType) ir.Node {
-       l := make([]*ir.Field, 0, len(expr.FieldList))
-       for i, field := range expr.FieldList {
-               p.setlineno(field)
-               var n *ir.Field
-               if field.Name == nil {
-                       n = p.embedded(field.Type)
-               } else {
-                       n = ir.NewField(p.pos(field), p.name(field.Name), p.typeExpr(field.Type), nil)
-               }
-               if i > 0 && expr.FieldList[i].Type == expr.FieldList[i-1].Type {
-                       n.Ntype = l[i-1].Ntype
-               }
-               if i < len(expr.TagList) && expr.TagList[i] != nil {
-                       n.Note = constant.StringVal(p.basicLit(expr.TagList[i]))
-               }
-               l = append(l, n)
-       }
-
-       p.setlineno(expr)
-       return ir.NewStructType(p.pos(expr), l)
-}
-
-func (p *noder) interfaceType(expr *syntax.InterfaceType) ir.Node {
-       l := make([]*ir.Field, 0, len(expr.MethodList))
-       for _, method := range expr.MethodList {
-               p.setlineno(method)
-               var n *ir.Field
-               if method.Name == nil {
-                       n = ir.NewField(p.pos(method), nil, importName(p.packname(method.Type)).(ir.Ntype), nil)
-               } else {
-                       mname := p.name(method.Name)
-                       if mname.IsBlank() {
-                               base.Errorf("methods must have a unique non-blank name")
-                               continue
-                       }
-                       sig := p.typeExpr(method.Type).(*ir.FuncType)
-                       sig.Recv = fakeRecv()
-                       n = ir.NewField(p.pos(method), mname, sig, nil)
-               }
-               l = append(l, n)
-       }
-
-       return ir.NewInterfaceType(p.pos(expr), l)
-}
-
-func (p *noder) packname(expr syntax.Expr) *types.Sym {
-       switch expr := expr.(type) {
-       case *syntax.Name:
-               name := p.name(expr)
-               if n := oldname(name); n.Name() != nil && n.Name().PkgName != nil {
-                       n.Name().PkgName.Used = true
-               }
-               return name
-       case *syntax.SelectorExpr:
-               name := p.name(expr.X.(*syntax.Name))
-               def := ir.AsNode(name.Def)
-               if def == nil {
-                       base.Errorf("undefined: %v", name)
-                       return name
-               }
-               var pkg *types.Pkg
-               if def.Op() != ir.OPACK {
-                       base.Errorf("%v is not a package", name)
-                       pkg = types.LocalPkg
-               } else {
-                       def := def.(*ir.PkgName)
-                       def.Used = true
-                       pkg = def.Pkg
-               }
-               return pkg.Lookup(expr.Sel.Value)
-       }
-       panic(fmt.Sprintf("unexpected packname: %#v", expr))
-}
-
-func (p *noder) embedded(typ syntax.Expr) *ir.Field {
-       pos := p.pos(syntax.StartPos(typ))
-
-       op, isStar := typ.(*syntax.Operation)
-       if isStar {
-               if op.Op != syntax.Mul || op.Y != nil {
-                       panic("unexpected Operation")
-               }
-               typ = op.X
-       }
-
-       sym := p.packname(typ)
-       n := ir.NewField(pos, typecheck.Lookup(sym.Name), importName(sym).(ir.Ntype), nil)
-       n.Embedded = true
-
-       if isStar {
-               n.Ntype = ir.NewStarExpr(pos, n.Ntype)
-       }
-       return n
-}
-
-func (p *noder) stmts(stmts []syntax.Stmt) []ir.Node {
-       return p.stmtsFall(stmts, false)
-}
-
-func (p *noder) stmtsFall(stmts []syntax.Stmt, fallOK bool) []ir.Node {
-       var nodes []ir.Node
-       for i, stmt := range stmts {
-               s := p.stmtFall(stmt, fallOK && i+1 == len(stmts))
-               if s == nil {
-               } else if s.Op() == ir.OBLOCK && len(s.(*ir.BlockStmt).List) > 0 {
-                       // Inline non-empty block.
-                       // Empty blocks must be preserved for CheckReturn.
-                       nodes = append(nodes, s.(*ir.BlockStmt).List...)
-               } else {
-                       nodes = append(nodes, s)
-               }
-       }
-       return nodes
-}
-
-func (p *noder) stmt(stmt syntax.Stmt) ir.Node {
-       return p.stmtFall(stmt, false)
-}
-
-func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
-       p.setlineno(stmt)
-       switch stmt := stmt.(type) {
-       case nil, *syntax.EmptyStmt:
-               return nil
-       case *syntax.LabeledStmt:
-               return p.labeledStmt(stmt, fallOK)
-       case *syntax.BlockStmt:
-               l := p.blockStmt(stmt)
-               if len(l) == 0 {
-                       // TODO(mdempsky): Line number?
-                       return ir.NewBlockStmt(base.Pos, nil)
-               }
-               return ir.NewBlockStmt(src.NoXPos, l)
-       case *syntax.ExprStmt:
-               return p.wrapname(stmt, p.expr(stmt.X))
-       case *syntax.SendStmt:
-               return ir.NewSendStmt(p.pos(stmt), p.expr(stmt.Chan), p.expr(stmt.Value))
-       case *syntax.DeclStmt:
-               return ir.NewBlockStmt(src.NoXPos, p.decls(stmt.DeclList))
-       case *syntax.AssignStmt:
-               if stmt.Rhs == nil {
-                       pos := p.pos(stmt)
-                       n := ir.NewAssignOpStmt(pos, p.binOp(stmt.Op), p.expr(stmt.Lhs), ir.NewBasicLit(pos, one))
-                       n.IncDec = true
-                       return n
-               }
-
-               if stmt.Op != 0 && stmt.Op != syntax.Def {
-                       n := ir.NewAssignOpStmt(p.pos(stmt), p.binOp(stmt.Op), p.expr(stmt.Lhs), p.expr(stmt.Rhs))
-                       return n
-               }
-
-               rhs := p.exprList(stmt.Rhs)
-               if list, ok := stmt.Lhs.(*syntax.ListExpr); ok && len(list.ElemList) != 1 || len(rhs) != 1 {
-                       n := ir.NewAssignListStmt(p.pos(stmt), ir.OAS2, nil, nil)
-                       n.Def = stmt.Op == syntax.Def
-                       n.Lhs = p.assignList(stmt.Lhs, n, n.Def)
-                       n.Rhs = rhs
-                       return n
-               }
-
-               n := ir.NewAssignStmt(p.pos(stmt), nil, nil)
-               n.Def = stmt.Op == syntax.Def
-               n.X = p.assignList(stmt.Lhs, n, n.Def)[0]
-               n.Y = rhs[0]
-               return n
-
-       case *syntax.BranchStmt:
-               var op ir.Op
-               switch stmt.Tok {
-               case syntax.Break:
-                       op = ir.OBREAK
-               case syntax.Continue:
-                       op = ir.OCONTINUE
-               case syntax.Fallthrough:
-                       if !fallOK {
-                               base.Errorf("fallthrough statement out of place")
-                       }
-                       op = ir.OFALL
-               case syntax.Goto:
-                       op = ir.OGOTO
-               default:
-                       panic("unhandled BranchStmt")
-               }
-               var sym *types.Sym
-               if stmt.Label != nil {
-                       sym = p.name(stmt.Label)
-               }
-               return ir.NewBranchStmt(p.pos(stmt), op, sym)
-       case *syntax.CallStmt:
-               var op ir.Op
-               switch stmt.Tok {
-               case syntax.Defer:
-                       op = ir.ODEFER
-               case syntax.Go:
-                       op = ir.OGO
-               default:
-                       panic("unhandled CallStmt")
-               }
-               return ir.NewGoDeferStmt(p.pos(stmt), op, p.expr(stmt.Call))
-       case *syntax.ReturnStmt:
-               n := ir.NewReturnStmt(p.pos(stmt), p.exprList(stmt.Results))
-               if len(n.Results) == 0 && ir.CurFunc != nil {
-                       for _, ln := range ir.CurFunc.Dcl {
-                               if ln.Class == ir.PPARAM {
-                                       continue
-                               }
-                               if ln.Class != ir.PPARAMOUT {
-                                       break
-                               }
-                               if ln.Sym().Def != ln {
-                                       base.Errorf("%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) assignList(expr syntax.Expr, defn ir.InitNode, colas bool) []ir.Node {
-       if !colas {
-               return p.exprList(expr)
-       }
-
-       var exprs []syntax.Expr
-       if list, ok := expr.(*syntax.ListExpr); ok {
-               exprs = list.ElemList
-       } else {
-               exprs = []syntax.Expr{expr}
-       }
-
-       res := make([]ir.Node, len(exprs))
-       seen := make(map[*types.Sym]bool, len(exprs))
-
-       newOrErr := false
-       for i, expr := range exprs {
-               p.setlineno(expr)
-               res[i] = ir.BlankNode
-
-               name, ok := expr.(*syntax.Name)
-               if !ok {
-                       p.errorAt(expr.Pos(), "non-name %v on left side of :=", p.expr(expr))
-                       newOrErr = true
-                       continue
-               }
-
-               sym := p.name(name)
-               if sym.IsBlank() {
-                       continue
-               }
-
-               if seen[sym] {
-                       p.errorAt(expr.Pos(), "%v repeated on left side of :=", sym)
-                       newOrErr = true
-                       continue
-               }
-               seen[sym] = true
-
-               if sym.Block == types.Block {
-                       res[i] = oldname(sym)
-                       continue
-               }
-
-               newOrErr = true
-               n := typecheck.NewName(sym)
-               typecheck.Declare(n, typecheck.DeclContext)
-               n.Defn = defn
-               defn.PtrInit().Append(ir.NewDecl(base.Pos, ir.ODCL, n))
-               res[i] = n
-       }
-
-       if !newOrErr {
-               base.ErrorfAt(defn.Pos(), "no new variables on left side of :=")
-       }
-       return res
-}
-
-func (p *noder) blockStmt(stmt *syntax.BlockStmt) []ir.Node {
-       p.openScope(stmt.Pos())
-       nodes := p.stmts(stmt.List)
-       p.closeScope(stmt.Rbrace)
-       return nodes
-}
-
-func (p *noder) ifStmt(stmt *syntax.IfStmt) ir.Node {
-       p.openScope(stmt.Pos())
-       init := p.stmt(stmt.Init)
-       n := ir.NewIfStmt(p.pos(stmt), p.expr(stmt.Cond), p.blockStmt(stmt.Then), nil)
-       if init != nil {
-               n.SetInit([]ir.Node{init})
-       }
-       if stmt.Else != nil {
-               e := p.stmt(stmt.Else)
-               if e.Op() == ir.OBLOCK {
-                       e := e.(*ir.BlockStmt)
-                       n.Else = e.List
-               } else {
-                       n.Else = []ir.Node{e}
-               }
-       }
-       p.closeAnotherScope()
-       return n
-}
-
-func (p *noder) forStmt(stmt *syntax.ForStmt) ir.Node {
-       p.openScope(stmt.Pos())
-       if r, ok := stmt.Init.(*syntax.RangeClause); ok {
-               if stmt.Cond != nil || stmt.Post != nil {
-                       panic("unexpected RangeClause")
-               }
-
-               n := ir.NewRangeStmt(p.pos(r), nil, nil, p.expr(r.X), nil)
-               if r.Lhs != nil {
-                       n.Def = r.Def
-                       lhs := p.assignList(r.Lhs, n, n.Def)
-                       n.Key = lhs[0]
-                       if len(lhs) > 1 {
-                               n.Value = lhs[1]
-                       }
-               }
-               n.Body = p.blockStmt(stmt.Body)
-               p.closeAnotherScope()
-               return n
-       }
-
-       n := ir.NewForStmt(p.pos(stmt), p.stmt(stmt.Init), p.expr(stmt.Cond), p.stmt(stmt.Post), p.blockStmt(stmt.Body))
-       p.closeAnotherScope()
-       return n
-}
-
-func (p *noder) switchStmt(stmt *syntax.SwitchStmt) ir.Node {
-       p.openScope(stmt.Pos())
-
-       init := p.stmt(stmt.Init)
-       n := ir.NewSwitchStmt(p.pos(stmt), p.expr(stmt.Tag), nil)
-       if init != nil {
-               n.SetInit([]ir.Node{init})
-       }
-
-       var tswitch *ir.TypeSwitchGuard
-       if l := n.Tag; l != nil && l.Op() == ir.OTYPESW {
-               tswitch = l.(*ir.TypeSwitchGuard)
-       }
-       n.Cases = p.caseClauses(stmt.Body, tswitch, stmt.Rbrace)
-
-       p.closeScope(stmt.Rbrace)
-       return n
-}
-
-func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *ir.TypeSwitchGuard, rbrace syntax.Pos) []*ir.CaseClause {
-       nodes := make([]*ir.CaseClause, 0, len(clauses))
-       for i, clause := range clauses {
-               p.setlineno(clause)
-               if i > 0 {
-                       p.closeScope(clause.Pos())
-               }
-               p.openScope(clause.Pos())
-
-               n := ir.NewCaseStmt(p.pos(clause), p.exprList(clause.Cases), nil)
-               if tswitch != nil && tswitch.Tag != nil {
-                       nn := typecheck.NewName(tswitch.Tag.Sym())
-                       typecheck.Declare(nn, typecheck.DeclContext)
-                       n.Var = nn
-                       // keep track of the instances for reporting unused
-                       nn.Defn = tswitch
-               }
-
-               // Trim trailing empty statements. We omit them from
-               // the Node AST anyway, and it's easier to identify
-               // out-of-place fallthrough statements without them.
-               body := clause.Body
-               for len(body) > 0 {
-                       if _, ok := body[len(body)-1].(*syntax.EmptyStmt); !ok {
-                               break
-                       }
-                       body = body[:len(body)-1]
-               }
-
-               n.Body = p.stmtsFall(body, true)
-               if l := len(n.Body); l > 0 && n.Body[l-1].Op() == ir.OFALL {
-                       if tswitch != nil {
-                               base.Errorf("cannot fallthrough in type switch")
-                       }
-                       if i+1 == len(clauses) {
-                               base.Errorf("cannot fallthrough final case in switch")
-                       }
-               }
-
-               nodes = append(nodes, n)
-       }
-       if len(clauses) > 0 {
-               p.closeScope(rbrace)
-       }
-       return nodes
-}
-
-func (p *noder) selectStmt(stmt *syntax.SelectStmt) ir.Node {
-       return ir.NewSelectStmt(p.pos(stmt), p.commClauses(stmt.Body, stmt.Rbrace))
-}
-
-func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []*ir.CommClause {
-       nodes := make([]*ir.CommClause, len(clauses))
-       for i, clause := range clauses {
-               p.setlineno(clause)
-               if i > 0 {
-                       p.closeScope(clause.Pos())
-               }
-               p.openScope(clause.Pos())
-
-               nodes[i] = ir.NewCommStmt(p.pos(clause), p.stmt(clause.Comm), p.stmts(clause.Body))
-       }
-       if len(clauses) > 0 {
-               p.closeScope(rbrace)
-       }
-       return nodes
-}
-
-func (p *noder) labeledStmt(label *syntax.LabeledStmt, fallOK bool) ir.Node {
-       sym := p.name(label.Label)
-       lhs := ir.NewLabelStmt(p.pos(label), sym)
-
-       var ls ir.Node
-       if label.Stmt != nil { // TODO(mdempsky): Should always be present.
-               ls = p.stmtFall(label.Stmt, fallOK)
-               // Attach label directly to control statement too.
-               if ls != nil {
-                       switch ls.Op() {
-                       case ir.OFOR:
-                               ls := ls.(*ir.ForStmt)
-                               ls.Label = sym
-                       case ir.ORANGE:
-                               ls := ls.(*ir.RangeStmt)
-                               ls.Label = sym
-                       case ir.OSWITCH:
-                               ls := ls.(*ir.SwitchStmt)
-                               ls.Label = sym
-                       case ir.OSELECT:
-                               ls := ls.(*ir.SelectStmt)
-                               ls.Label = sym
-                       }
-               }
-       }
-
-       l := []ir.Node{lhs}
-       if ls != nil {
-               if ls.Op() == ir.OBLOCK {
-                       ls := ls.(*ir.BlockStmt)
-                       l = append(l, ls.List...)
-               } else {
-                       l = append(l, ls)
-               }
-       }
-       return ir.NewBlockStmt(src.NoXPos, l)
-}
-
 var unOps = [...]ir.Op{
        syntax.Recv: ir.ORECV,
        syntax.Mul:  ir.ODEREF,
@@ -1311,13 +151,6 @@ var unOps = [...]ir.Op{
        syntax.Sub: ir.ONEG,
 }
 
-func (p *noder) unOp(op syntax.Operator) ir.Op {
-       if uint64(op) >= uint64(len(unOps)) || unOps[op] == 0 {
-               panic("invalid Operator")
-       }
-       return unOps[op]
-}
-
 var binOps = [...]ir.Op{
        syntax.OrOr:   ir.OOROR,
        syntax.AndAnd: ir.OANDAND,
@@ -1343,96 +176,6 @@ var binOps = [...]ir.Op{
        syntax.Shr:    ir.ORSH,
 }
 
-func (p *noder) binOp(op syntax.Operator) ir.Op {
-       if uint64(op) >= uint64(len(binOps)) || binOps[op] == 0 {
-               panic("invalid Operator")
-       }
-       return binOps[op]
-}
-
-// checkLangCompat reports an error if the representation of a numeric
-// literal is not compatible with the current language version.
-func checkLangCompat(lit *syntax.BasicLit) {
-       s := lit.Value
-       if len(s) <= 2 || types.AllowsGoVersion(types.LocalPkg, 1, 13) {
-               return
-       }
-       // len(s) > 2
-       if strings.Contains(s, "_") {
-               base.ErrorfVers("go1.13", "underscores in numeric literals")
-               return
-       }
-       if s[0] != '0' {
-               return
-       }
-       radix := s[1]
-       if radix == 'b' || radix == 'B' {
-               base.ErrorfVers("go1.13", "binary literals")
-               return
-       }
-       if radix == 'o' || radix == 'O' {
-               base.ErrorfVers("go1.13", "0o/0O-style octal literals")
-               return
-       }
-       if lit.Kind != syntax.IntLit && (radix == 'x' || radix == 'X') {
-               base.ErrorfVers("go1.13", "hexadecimal floating-point literals")
-       }
-}
-
-func (p *noder) basicLit(lit *syntax.BasicLit) constant.Value {
-       // We don't use the errors of the conversion routines to determine
-       // if a literal string is valid because the conversion routines may
-       // accept a wider syntax than the language permits. Rely on lit.Bad
-       // instead.
-       if lit.Bad {
-               return constant.MakeUnknown()
-       }
-
-       switch lit.Kind {
-       case syntax.IntLit, syntax.FloatLit, syntax.ImagLit:
-               checkLangCompat(lit)
-               // The max. mantissa precision for untyped numeric values
-               // is 512 bits, or 4048 bits for each of the two integer
-               // parts of a fraction for floating-point numbers that are
-               // represented accurately in the go/constant package.
-               // Constant literals that are longer than this many bits
-               // are not meaningful; and excessively long constants may
-               // consume a lot of space and time for a useless conversion.
-               // Cap constant length with a generous upper limit that also
-               // allows for separators between all digits.
-               const limit = 10000
-               if len(lit.Value) > limit {
-                       p.errorAt(lit.Pos(), "excessively long constant: %s... (%d chars)", lit.Value[:10], len(lit.Value))
-                       return constant.MakeUnknown()
-               }
-       }
-
-       v := constant.MakeFromLiteral(lit.Value, tokenForLitKind[lit.Kind], 0)
-       if v.Kind() == constant.Unknown {
-               // TODO(mdempsky): Better error message?
-               p.errorAt(lit.Pos(), "malformed constant: %s", lit.Value)
-       }
-
-       return v
-}
-
-var tokenForLitKind = [...]token.Token{
-       syntax.IntLit:    token.INT,
-       syntax.RuneLit:   token.CHAR,
-       syntax.FloatLit:  token.FLOAT,
-       syntax.ImagLit:   token.IMAG,
-       syntax.StringLit: token.STRING,
-}
-
-func (p *noder) name(name *syntax.Name) *types.Sym {
-       return typecheck.Lookup(name.Value)
-}
-
-func (p *noder) mkname(name *syntax.Name) ir.Node {
-       // TODO(mdempsky): Set line number?
-       return mkname(p.name(name))
-}
-
 func wrapname(pos src.XPos, x ir.Node) ir.Node {
        // These nodes do not carry line numbers.
        // Introduce a wrapper node to give them the correct line.
@@ -1450,16 +193,6 @@ func wrapname(pos src.XPos, x ir.Node) ir.Node {
        return x
 }
 
-func (p *noder) wrapname(n syntax.Node, x ir.Node) ir.Node {
-       return wrapname(p.pos(n), x)
-}
-
-func (p *noder) setlineno(n syntax.Node) {
-       if n != nil {
-               base.Pos = p.pos(n)
-       }
-}
-
 // error is called concurrently if files are parsed concurrently.
 func (p *noder) error(err error) {
        p.err <- err.(syntax.Error)
@@ -1495,19 +228,6 @@ type pragmaEmbed struct {
        Patterns []string
 }
 
-func (p *noder) checkUnused(pragma *pragmas) {
-       for _, pos := range pragma.Pos {
-               if pos.Flag&pragma.Flag != 0 {
-                       p.errorAt(pos.Pos, "misplaced compiler directive")
-               }
-       }
-       if len(pragma.Embeds) > 0 {
-               for _, e := range pragma.Embeds {
-                       p.errorAt(e.Pos, "misplaced go:embed directive")
-               }
-       }
-}
-
 func (p *noder) checkUnusedDuringParse(pragma *pragmas) {
        for _, pos := range pragma.Pos {
                if pos.Flag&pragma.Flag != 0 {
@@ -1646,14 +366,6 @@ func safeArg(name string) bool {
        return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf
 }
 
-func mkname(sym *types.Sym) ir.Node {
-       n := oldname(sym)
-       if n.Name() != nil && n.Name().PkgName != nil {
-               n.Name().PkgName.Used = true
-       }
-       return n
-}
-
 // parseGoEmbed parses the text following "//go:embed" to extract the glob patterns.
 // It accepts unquoted space-separated patterns as well as double-quoted and back-quoted Go strings.
 // go/build/read.go also processes these strings and contains similar logic.
@@ -1715,21 +427,6 @@ func parseGoEmbed(args string) ([]string, error) {
        return list, nil
 }
 
-func fakeRecv() *ir.Field {
-       return ir.NewField(base.Pos, nil, nil, types.FakeRecvType())
-}
-
-func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node {
-       fn := ir.NewClosureFunc(p.pos(expr), ir.CurFunc != nil)
-       fn.Nname.Ntype = p.typeExpr(expr.Type)
-
-       p.funcBody(fn, expr.Body)
-
-       ir.FinishCaptureNames(base.Pos, ir.CurFunc, fn)
-
-       return fn.OClosure
-}
-
 // A function named init is a special case.
 // It is called by the initialization before main is run.
 // To make it unique within a package and also uncallable,
@@ -1742,34 +439,6 @@ func renameinit() *types.Sym {
        return s
 }
 
-// oldname returns the Node that declares symbol s in the current scope.
-// If no such Node currently exists, an ONONAME Node is returned instead.
-// Automatically creates a new closure variable if the referenced symbol was
-// declared in a different (containing) function.
-func oldname(s *types.Sym) ir.Node {
-       if s.Pkg != types.LocalPkg {
-               return ir.NewIdent(base.Pos, s)
-       }
-
-       n := ir.AsNode(s.Def)
-       if n == nil {
-               // Maybe a top-level declaration will come along later to
-               // define s. resolve will check s.Def again once all input
-               // source has been processed.
-               return ir.NewIdent(base.Pos, s)
-       }
-
-       if n, ok := n.(*ir.Name); ok {
-               // TODO(rsc): If there is an outer variable x and we
-               // are parsing x := 5 inside the closure, until we get to
-               // the := it looks like a reference to the outer x so we'll
-               // make x a closure variable unnecessarily.
-               return ir.CaptureName(base.Pos, ir.CurFunc, n)
-       }
-
-       return n
-}
-
 func varEmbed(makeXPos func(syntax.Pos) src.XPos, name *ir.Name, decl *syntax.VarDecl, pragma *pragmas, haveEmbed bool) {
        pragmaEmbeds := pragma.Embeds
        pragma.Embeds = nil