]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.typeparams] all: merge dev.regabi (ec741b0) into dev.typeparams
authorRuss Cox <rsc@golang.org>
Tue, 22 Dec 2020 22:08:15 +0000 (17:08 -0500)
committerRuss Cox <rsc@golang.org>
Tue, 22 Dec 2020 22:08:17 +0000 (17:08 -0500)
Conflicts:

* src/cmd/compile/internal/gc/main.go

Merge List:

* 2020-12-22 ec741b0447 [dev.regabi] all: merge master (c9fb4eb) into dev.regabi
* 2020-12-22 acc32ea124 [dev.regabi] codereview.cfg: add config for dev.regabi
* 2020-12-22 c9fb4eb0a2 cmd/link: handle grouped resource sections
* 2020-12-22 c40934b33d [dev.regabi] cmd/compile: adjust one case in walkexpr
* 2020-12-22 280e7fd1ee [dev.regabi] cmd/compile: only access Func method on concrete types
* 2020-12-22 51ba53f5c2 [dev.regabi] cmd/compile: separate misc for gc split
* 2020-12-22 572f168ed2 [dev.regabi] cmd/compile: separate various from Main
* 2020-12-22 3b12c6dc08 [dev.regabi] cmd/compile: separate typecheck more cleanly
* 2020-12-22 7c8f5356ab [dev.regabi] cmd/compile: separate dowidth better
* 2020-12-22 c06a354bcc test: trigger SIGSEGV instead of SIGTRAP in issue11656.go
* 2020-12-22 0aa9b4709a cmd/pack: r command create output file if not exist
* 2020-12-22 cb28c96be8 [dev.regabi] cmd/compile,cmd/link: initial support for ABI wrappers
* 2020-12-22 c8610e4700 [dev.regabi] cmd/compile: add ir.BasicLit to represent literals
* 2020-12-22 3512cde10a [dev.regabi] cmd/compile: stop reusing Ntype for OSLICELIT length
* 2020-12-22 2755361e6a [dev.regabi] cmd/compile: change noder.declNames to returns ir.Names
* 2020-12-22 301af2cb71 [dev.regabi] runtime/race: adjust test pattern match for ABI wrapper
* 2020-12-22 4d27c4c223 runtime: correct error handling in several FreeBSD syscall wrappers
* 2020-12-22 9b6147120a cmd/pack: treat compiler's -linkobj output as "compiler object"
* 2020-12-22 306b2451c8 [dev.regabi] runtime: fix ABI targets in runtime.panic{Index,Slice} shims
* 2020-12-21 bc7e4d9257 syscall: don't generate ptrace on iOS
* 2020-12-21 94cfeca0a5 [dev.regabi] cmd/compile: stop using ONONAME with Name
* 2020-12-21 cb4898a77d [dev.regabi] cmd/compile: simplify declaration importing
* 2020-12-21 06915ac14d [dev.regabi] cmd/compile: move itabname call out of implements
* 2020-12-21 6cff874c47 runtime/metrics: add Read examples
* 2020-12-21 8438a5779b runtime: use _exit on darwin
* 2020-12-21 cb95819cf6 runtime: detect netbsd netpoll overrun in sysmon
* 2020-12-21 53c984d976 runtime: skip wakep call in wakeNetPoller on Plan 9
* 2020-12-21 9abbe27710 test: skip issue11656.go on mips/mips64/ppc64

Change-Id: Ia12a1892195f5e08bb41465374124c71a1a135f6

1  2 
src/cmd/compile/internal/base/flag.go
src/cmd/compile/internal/gc/go.go
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/gc/noder.go

index 240258d6b8e23e79c71827b6ee5795f84cd39b66,ce87ff730eaa7c19ee5101012be71d0809dd97ec..898cb5470b7fbb6872f513e2ede5e63593d54618
@@@ -54,7 -54,6 +54,7 @@@ type CmdFlags struct 
        C CountFlag    "help:\"disable printing of columns in error messages\""
        D string       "help:\"set relative `path` for local imports\""
        E CountFlag    "help:\"debug symbol export\""
 +      G CountFlag    "help:\"accept generic code\""
        I func(string) "help:\"add `directory` to import search path\""
        K CountFlag    "help:\"debug missing line numbers\""
        L CountFlag    "help:\"show full file names in error messages\""
@@@ -82,6 -81,8 +82,8 @@@
        CompilingRuntime bool "flag:\"+\" help:\"compiling runtime\""
  
        // Longer names
+       ABIWrap            bool         "help:\"enable generation of ABI wrappers\""
+       ABIWrapLimit       int          "help:\"emit at most N ABI wrappers (for debugging)\""
        AsmHdr             string       "help:\"write assembly header to `file`\""
        Bench              string       "help:\"append benchmark times to `file`\""
        BlockProfile       string       "help:\"write block profile to `file`\""
@@@ -141,6 -142,7 +143,7 @@@ func ParseFlags() 
        Flag.LowerP = &Ctxt.Pkgpath
        Flag.LowerV = &Ctxt.Debugvlog
  
+       Flag.ABIWrap = objabi.Regabi_enabled != 0
        Flag.Dwarf = objabi.GOARCH != "wasm"
        Flag.DwarfBASEntries = &Ctxt.UseBASEntries
        Flag.DwarfLocationLists = &Ctxt.Flag_locationlists
index a132d5803f11bfd29d498f8d8deb9d83682a97ce,df91f6f530aa43114e1b63c8c733d579805af7df..9e8719dc0bb2fdfb9383c52008878cf714b395ee
@@@ -80,8 -80,6 +80,8 @@@ var pragcgobuf [][]strin
  
  var decldepth int32
  
 +var nolocalimports bool
 +
  var inimport bool // set during import
  
  var itabpkg *types.Pkg // fake pkg for itab entries
@@@ -131,8 -129,6 +131,6 @@@ var 
        iscmp [ir.OEND]bool
  )
  
- var importlist []*ir.Func // imported functions and methods with inlinable bodies
  var (
        funcsymsmu sync.Mutex // protects funcsyms and associated package lookups (see func funcsym)
        funcsyms   []*types.Sym
index ff5c208d0230cb8e12c141cfa7fd7d03e57fcad8,94b4e0e674e82f8ae6a6b577d19c18eb667227a9..b9454604f0d5814289d7d15f6a11a28d76dfc517
@@@ -54,9 -54,6 +54,6 @@@ func hidePanic() 
  // Target is the package being compiled.
  var Target *ir.Package
  
- // timing data for compiler phases
- var timings Timings
  // Main parses flags and Go source files specified in the command-line
  // arguments, type-checks the parsed Go package, compiles functions to machine
  // code, and finally writes the compiled package definition to disk.
@@@ -189,179 -186,59 +186,65 @@@ func Main(archInit func(*Arch)) 
                logopt.LogJsonOption(base.Flag.JSON)
        }
  
+       ir.EscFmt = escFmt
        IsIntrinsicCall = isIntrinsicCall
        SSADumpInline = ssaDumpInline
-       ssaDump = os.Getenv("GOSSAFUNC")
-       ssaDir = os.Getenv("GOSSADIR")
-       if ssaDump != "" {
-               if strings.HasSuffix(ssaDump, "+") {
-                       ssaDump = ssaDump[:len(ssaDump)-1]
-                       ssaDumpStdout = true
-               }
-               spl := strings.Split(ssaDump, ":")
-               if len(spl) > 1 {
-                       ssaDump = spl[0]
-                       ssaDumpCFG = spl[1]
-               }
-       }
+       initSSAEnv()
+       initSSATables()
  
        Widthptr = thearch.LinkArch.PtrSize
        Widthreg = thearch.LinkArch.RegSize
+       MaxWidth = thearch.MAXWIDTH
+       types.TypeLinkSym = func(t *types.Type) *obj.LSym {
+               return typenamesym(t).Linksym()
+       }
  
        Target = new(ir.Package)
  
-       // initialize types package
-       // (we need to do this to break dependencies that otherwise
-       // would lead to import cycles)
-       initializeTypesPackage()
-       dclcontext = ir.PEXTERN
+       NeedFuncSym = makefuncsym
+       NeedITab = func(t, iface *types.Type) { itabname(t, iface) }
+       NeedRuntimeType = addsignat // TODO(rsc): typenamesym for lock?
  
        autogeneratedPos = makePos(src.NewFileBase("<autogenerated>", "<autogenerated>"), 1, 0)
  
-       timings.Start("fe", "loadsys")
-       loadsys()
+       types.TypeLinkSym = func(t *types.Type) *obj.LSym {
+               return typenamesym(t).Linksym()
+       }
+       TypecheckInit()
  
+       // Parse input.
        timings.Start("fe", "parse")
        lines := parseFiles(flag.Args())
        cgoSymABIs()
        timings.Stop()
        timings.AddEvent(int64(lines), "lines")
-       finishUniverse()
 +      if base.Flag.G != 0 && base.Flag.G < 3 {
 +              // can only parse generic code for now
 +              base.ExitIfErrors()
 +              return
 +      }
 +
        recordPackageName()
  
-       typecheckok = true
-       // Process top-level declarations in phases.
-       // Phase 1: const, type, and names and types of funcs.
-       //   This will gather all the information about types
-       //   and methods but doesn't depend on any of it.
-       //
-       //   We also defer type alias declarations until phase 2
-       //   to avoid cycles like #18640.
-       //   TODO(gri) Remove this again once we have a fix for #25838.
-       // Don't use range--typecheck can add closures to Target.Decls.
-       timings.Start("fe", "typecheck", "top1")
-       for i := 0; i < len(Target.Decls); i++ {
-               n := Target.Decls[i]
-               if op := n.Op(); op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.(*ir.Decl).Left().Name().Alias()) {
-                       Target.Decls[i] = typecheck(n, ctxStmt)
-               }
-       }
-       // Phase 2: Variable assignments.
-       //   To check interface assignments, depends on phase 1.
-       // Don't use range--typecheck can add closures to Target.Decls.
-       timings.Start("fe", "typecheck", "top2")
-       for i := 0; i < len(Target.Decls); i++ {
-               n := Target.Decls[i]
-               if op := n.Op(); op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.(*ir.Decl).Left().Name().Alias() {
-                       Target.Decls[i] = typecheck(n, ctxStmt)
-               }
-       }
-       // Phase 3: Type check function bodies.
-       // Don't use range--typecheck can add closures to Target.Decls.
-       timings.Start("fe", "typecheck", "func")
-       var fcount int64
-       for i := 0; i < len(Target.Decls); i++ {
-               n := Target.Decls[i]
-               if n.Op() == ir.ODCLFUNC {
-                       Curfn = n.(*ir.Func)
-                       decldepth = 1
-                       errorsBefore := base.Errors()
-                       typecheckslice(Curfn.Body().Slice(), ctxStmt)
-                       checkreturn(Curfn)
-                       if base.Errors() > errorsBefore {
-                               Curfn.PtrBody().Set(nil) // type errors; do not compile
-                       }
-                       // Now that we've checked whether n terminates,
-                       // we can eliminate some obviously dead code.
-                       deadcode(Curfn)
-                       fcount++
-               }
-       }
+       // Typecheck.
+       TypecheckPackage()
  
-       // Phase 3.11: Check external declarations.
-       // TODO(mdempsky): This should be handled when type checking their
-       // corresponding ODCL nodes.
-       timings.Start("fe", "typecheck", "externdcls")
-       for i, n := range Target.Externs {
-               if n.Op() == ir.ONAME {
-                       Target.Externs[i] = typecheck(Target.Externs[i], ctxExpr)
-               }
-       }
-       // Phase 3.14: With all user code type-checked, it's now safe to verify map keys
-       // and unused dot imports.
-       checkMapKeys()
+       // With all user code typechecked, it's now safe to verify unused dot imports.
        checkDotImports()
        base.ExitIfErrors()
  
-       timings.AddEvent(fcount, "funcs")
+       // Build init task.
        if initTask := fninit(); initTask != nil {
                exportsym(initTask)
        }
  
-       // Phase 4: Decide how to capture closed variables.
-       // This needs to run before escape analysis,
-       // because variables captured by value do not escape.
-       timings.Start("fe", "capturevars")
-       for _, n := range Target.Decls {
-               if n.Op() == ir.ODCLFUNC && n.Func().OClosure != nil {
-                       Curfn = n.(*ir.Func)
-                       capturevars(Curfn)
-               }
-       }
-       capturevarscomplete = true
-       Curfn = nil
-       base.ExitIfErrors()
-       // Phase 5: Inlining
+       // Inlining
        timings.Start("fe", "inlining")
-       if base.Debug.TypecheckInl != 0 {
-               // Typecheck imported function bodies if Debug.l > 1,
-               // otherwise lazily when used or re-exported.
-               for _, n := range importlist {
-                       if n.Inl != nil {
-                               typecheckinl(n)
-                       }
-               }
-               base.ExitIfErrors()
-       }
        if base.Flag.LowerL != 0 {
-               // Find functions that can be inlined and clone them before walk expands them.
-               visitBottomUp(Target.Decls, func(list []*ir.Func, recursive bool) {
-                       numfns := numNonClosures(list)
-                       for _, n := range list {
-                               if !recursive || numfns > 1 {
-                                       // We allow inlining if there is no
-                                       // recursion, or the recursion cycle is
-                                       // across more than one function.
-                                       caninl(n)
-                               } else {
-                                       if base.Flag.LowerM > 1 {
-                                               fmt.Printf("%v: cannot inline %v: recursive\n", ir.Line(n), n.Nname)
-                                       }
-                               }
-                               inlcalls(n)
-                       }
-               })
+               InlinePackage()
        }
  
+       // Devirtualize.
        for _, n := range Target.Decls {
                if n.Op() == ir.ODCLFUNC {
                        devirtualize(n.(*ir.Func))
        }
        Curfn = nil
  
-       // Phase 6: Escape analysis.
+       // Escape analysis.
        // Required for moving heap allocations onto stack,
        // which in turn is required by the closure implementation,
        // which stores the addresses of stack variables into the closure.
                EnableNoWriteBarrierRecCheck()
        }
  
-       // Phase 7: Transform closure bodies to properly reference captured variables.
+       // Transform closure bodies to properly reference captured variables.
        // This needs to happen before walk, because closures must be transformed
        // before walk reaches a call of a closure.
        timings.Start("fe", "xclosures")
        for _, n := range Target.Decls {
-               if n.Op() == ir.ODCLFUNC && n.Func().OClosure != nil {
-                       Curfn = n.(*ir.Func)
-                       transformclosure(Curfn)
+               if n.Op() == ir.ODCLFUNC {
+                       n := n.(*ir.Func)
+                       if n.Func().OClosure != nil {
+                               Curfn = n
+                               transformclosure(n)
+                       }
                }
        }
  
        Curfn = nil
        peekitabs()
  
-       // Phase 8: Compile top level functions.
+       // Compile top level functions.
        // Don't use range--walk can add functions to Target.Decls.
        timings.Start("be", "compilefuncs")
-       fcount = 0
+       fcount := int64(0)
        for i := 0; i < len(Target.Decls); i++ {
                n := Target.Decls[i]
                if n.Op() == ir.ODCLFUNC {
                dumpasmhdr()
        }
  
-       // Check whether any of the functions we have compiled have gigantic stack frames.
-       sort.Slice(largeStackFrames, func(i, j int) bool {
-               return largeStackFrames[i].pos.Before(largeStackFrames[j].pos)
-       })
-       for _, large := range largeStackFrames {
-               if large.callee != 0 {
-                       base.ErrorfAt(large.pos, "stack frame too large (>1GB): %d MB locals + %d MB args + %d MB callee", large.locals>>20, large.args>>20, large.callee>>20)
-               } else {
-                       base.ErrorfAt(large.pos, "stack frame too large (>1GB): %d MB locals + %d MB args", large.locals>>20, large.args>>20)
-               }
-       }
+       CheckLargeStacks()
+       CheckFuncStack()
  
-       if len(funcStack) != 0 {
-               base.Fatalf("funcStack is non-empty: %v", len(funcStack))
-       }
        if len(compilequeue) != 0 {
                base.Fatalf("%d uncompiled functions", len(compilequeue))
        }
        }
  }
  
+ func CheckLargeStacks() {
+       // Check whether any of the functions we have compiled have gigantic stack frames.
+       sort.Slice(largeStackFrames, func(i, j int) bool {
+               return largeStackFrames[i].pos.Before(largeStackFrames[j].pos)
+       })
+       for _, large := range largeStackFrames {
+               if large.callee != 0 {
+                       base.ErrorfAt(large.pos, "stack frame too large (>1GB): %d MB locals + %d MB args + %d MB callee", large.locals>>20, large.args>>20, large.callee>>20)
+               } else {
+                       base.ErrorfAt(large.pos, "stack frame too large (>1GB): %d MB locals + %d MB args", large.locals>>20, large.args>>20)
+               }
+       }
+ }
  func cgoSymABIs() {
        // The linker expects an ABI0 wrapper for all cgo-exported
        // functions.
@@@ -1081,9 -963,11 +969,11 @@@ type lang struct 
  // any language version is supported.
  var langWant lang
  
- // langSupported reports whether language version major.minor is
- // supported in a particular package.
- func langSupported(major, minor int, pkg *types.Pkg) bool {
+ // AllowsGoVersion reports whether a particular package
+ // is allowed to use Go version major.minor.
+ // We assume the imported packages have all been checked,
+ // so we only have to check the local package against the -lang flag.
+ func AllowsGoVersion(pkg *types.Pkg, major, minor int) bool {
        if pkg == nil {
                // TODO(mdempsky): Set Pkg for local types earlier.
                pkg = types.LocalPkg
                // Assume imported packages passed type-checking.
                return true
        }
        if langWant.major == 0 && langWant.minor == 0 {
                return true
        }
        return langWant.major > major || (langWant.major == major && langWant.minor >= minor)
  }
  
+ func langSupported(major, minor int, pkg *types.Pkg) bool {
+       return AllowsGoVersion(pkg, major, minor)
+ }
  // checkLang verifies that the -lang flag holds a valid value, and
  // exits if not. It initializes data used by langSupported.
  func checkLang() {
@@@ -1140,12 -1027,25 +1033,25 @@@ func parseLang(s string) (lang, error) 
        return lang{major: major, minor: minor}, nil
  }
  
- func initializeTypesPackage() {
-       types.Widthptr = Widthptr
-       types.Dowidth = dowidth
-       types.TypeLinkSym = func(t *types.Type) *obj.LSym {
-               return typenamesym(t).Linksym()
+ // useNewABIWrapGen returns TRUE if the compiler should generate an
+ // ABI wrapper for the function 'f'.
+ func useABIWrapGen(f *ir.Func) bool {
+       if !base.Flag.ABIWrap {
+               return false
+       }
+       // Support limit option for bisecting.
+       if base.Flag.ABIWrapLimit == 1 {
+               return false
+       }
+       if base.Flag.ABIWrapLimit < 1 {
+               return true
+       }
+       base.Flag.ABIWrapLimit--
+       if base.Debug.ABIWrap != 0 && base.Flag.ABIWrapLimit == 1 {
+               fmt.Fprintf(os.Stderr, "=-= limit reached after new wrapper for %s\n",
+                       f.LSym.Name)
        }
  
-       initUniverse()
+       return true
  }
index e3f3e1813212f65bdcfa127df363b65fd4771930,97a9ac4396194ac51348f32378c95f9538a73f83..8beef0d18b0f22f25aa3c500485c8e244ed67fdd
@@@ -8,7 -8,6 +8,7 @@@ import 
        "fmt"
        "go/constant"
        "go/token"
 +      "io"
        "os"
        "path/filepath"
        "runtime"
        "unicode/utf8"
  
        "cmd/compile/internal/base"
 +      "cmd/compile/internal/importer"
        "cmd/compile/internal/ir"
        "cmd/compile/internal/syntax"
        "cmd/compile/internal/types"
 +      "cmd/compile/internal/types2"
        "cmd/internal/objabi"
        "cmd/internal/src"
  )
@@@ -31,7 -28,7 +31,7 @@@
  // Each declaration in every *syntax.File is converted to a syntax tree
  // and its root represented by *Node is appended to Target.Decls.
  // Returns the total count of parsed lines.
 -func parseFiles(filenames []string) uint {
 +func parseFiles(filenames []string) (lines uint) {
        noders := make([]*noder, 0, len(filenames))
        // Limit the number of simultaneously open files.
        sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)
@@@ -48,7 -45,7 +48,7 @@@
                        sem <- struct{}{}
                        defer func() { <-sem }()
                        defer close(p.err)
 -                      base := syntax.NewFileBase(filename)
 +                      fbase := syntax.NewFileBase(filename)
  
                        f, err := os.Open(filename)
                        if err != nil {
                        }
                        defer f.Close()
  
 -                      p.file, _ = syntax.Parse(base, f, p.error, p.pragma, syntax.CheckBranches) // errors are tracked via p.error
 +                      mode := syntax.CheckBranches
 +                      if base.Flag.G != 0 {
 +                              mode |= syntax.AllowGenerics
 +                      }
 +                      p.file, _ = syntax.Parse(fbase, f, p.error, p.pragma, mode) // errors are tracked via p.error
                }(filename)
        }
  
 -      var lines uint
 +      // generic noding phase (using new typechecker)
 +      if base.Flag.G != 0 {
 +              // setup and syntax error reporting
 +              nodersmap := make(map[string]*noder)
 +              var files []*syntax.File
 +              for _, p := range noders {
 +                      for e := range p.err {
 +                              p.errorAt(e.Pos, "%s", e.Msg)
 +                      }
 +
 +                      nodersmap[p.file.Pos().RelFilename()] = p
 +                      files = append(files, p.file)
 +                      lines += p.file.EOF.Line()
 +
 +              }
 +              if base.SyntaxErrors() != 0 {
 +                      base.ErrorExit()
 +              }
 +
 +              // typechecking
 +              conf := types2.Config{
 +                      InferFromConstraints:  true,
 +                      IgnoreBranches:        true, // parser already checked via syntax.CheckBranches mode
 +                      CompilerErrorMessages: true, // use error strings matching existing compiler errors
 +                      Error: func(err error) {
 +                              terr := err.(types2.Error)
 +                              if len(terr.Msg) > 0 && terr.Msg[0] == '\t' {
 +                                      // types2 reports error clarifications via separate
 +                                      // error messages which are indented with a tab.
 +                                      // Ignore them to satisfy tools and tests that expect
 +                                      // only one error in such cases.
 +                                      // TODO(gri) Need to adjust error reporting in types2.
 +                                      return
 +                              }
 +                              p := nodersmap[terr.Pos.RelFilename()]
 +                              base.ErrorfAt(p.makeXPos(terr.Pos), "%s", terr.Msg)
 +                      },
 +                      Importer: &gcimports{
 +                              packages: make(map[string]*types2.Package),
 +                              lookup: func(path string) (io.ReadCloser, error) {
 +                                      file, ok := findpkg(path)
 +                                      if !ok {
 +                                              return nil, fmt.Errorf("can't find import: %q", path)
 +                                      }
 +                                      return os.Open(file)
 +                              },
 +                      },
 +              }
 +              info := types2.Info{
 +                      Types:      make(map[syntax.Expr]types2.TypeAndValue),
 +                      Defs:       make(map[*syntax.Name]types2.Object),
 +                      Uses:       make(map[*syntax.Name]types2.Object),
 +                      Selections: make(map[*syntax.SelectorExpr]*types2.Selection),
 +                      // expand as needed
 +              }
 +              conf.Check(base.Ctxt.Pkgpath, files, &info)
 +              base.ExitIfErrors()
 +              if base.Flag.G < 2 {
 +                      return
 +              }
 +
 +              // noding
 +              for _, p := range noders {
 +                      // errors have already been reported
 +
 +                      p.typeInfo = &info
 +                      p.node()
 +                      lines += p.file.EOF.Line()
 +                      p.file = nil // release memory
 +                      base.ExitIfErrors()
 +
 +                      // Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
 +                      testdclstack()
 +              }
 +
 +              types.LocalPkg.Height = myheight
 +              return
 +      }
 +
 +      // traditional (non-generic) noding phase
        for _, p := range noders {
                for e := range p.err {
                        p.errorAt(e.Pos, "%s", e.Msg)
                }
  
                p.node()
 -              lines += p.file.Lines
 +              lines += p.file.EOF.Line()
                p.file = nil // release memory
 -
                if base.SyntaxErrors() != 0 {
                        base.ErrorExit()
                }
 +
                // Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
                testdclstack()
        }
        }
  
        types.LocalPkg.Height = myheight
 +      return
 +}
  
 -      return lines
 +// Temporary import helper to get type2-based type-checking going.
 +type gcimports struct {
 +      packages map[string]*types2.Package
 +      lookup   func(path string) (io.ReadCloser, error)
 +}
 +
 +func (m *gcimports) Import(path string) (*types2.Package, error) {
 +      return m.ImportFrom(path, "" /* no vendoring */, 0)
 +}
 +
 +func (m *gcimports) ImportFrom(path, srcDir string, mode types2.ImportMode) (*types2.Package, error) {
 +      if mode != 0 {
 +              panic("mode must be 0")
 +      }
 +      return importer.Import(m.packages, path, srcDir, m.lookup)
  }
  
  // makeSrcPosBase translates from a *syntax.PosBase to a *src.PosBase.
@@@ -256,40 -154,9 +256,40 @@@ type noder struct 
        trackScopes bool
        scopeVars   []int
  
 +      // typeInfo provides access to the type information computed by the new
 +      // typechecker. It is only present if -G is set, and all noders point to
 +      // the same types.Info. For now this is a local field, if need be we can
 +      // make it global.
 +      typeInfo *types2.Info
 +
        lastCloseScopePos syntax.Pos
  }
  
 +// For now we provide these basic accessors to get to type and object
 +// information of expression nodes during noding. Eventually we will
 +// attach this information directly to the syntax tree which should
 +// simplify access and make it more efficient as well.
 +
 +// typ returns the type and value information for the given expression.
 +func (p *noder) typ(x syntax.Expr) types2.TypeAndValue {
 +      return p.typeInfo.Types[x]
 +}
 +
 +// def returns the object for the given name in its declaration.
 +func (p *noder) def(x *syntax.Name) types2.Object {
 +      return p.typeInfo.Defs[x]
 +}
 +
 +// use returns the object for the given name outside its declaration.
 +func (p *noder) use(x *syntax.Name) types2.Object {
 +      return p.typeInfo.Uses[x]
 +}
 +
 +// sel returns the selection information for the given selector expression.
 +func (p *noder) sel(x *syntax.SelectorExpr) *types2.Selection {
 +      return p.typeInfo.Selections[x]
 +}
 +
  func (p *noder) funcBody(fn *ir.Func, block *syntax.BlockStmt) {
        oldScope := p.scope
        p.scope = 0
@@@ -451,7 -318,7 +451,7 @@@ func (p *noder) decls(decls []syntax.De
  }
  
  func (p *noder) importDecl(imp *syntax.ImportDecl) {
 -      if imp.Path.Bad {
 +      if imp.Path == nil || imp.Path.Bad {
                return // avoid follow-on errors if there was a syntax error
        }
  
  }
  
  func (p *noder) varDecl(decl *syntax.VarDecl) []ir.Node {
-       names := p.declNames(decl.NameList)
+       names := p.declNames(ir.ONAME, decl.NameList)
        typ := p.typeExprOrNil(decl.Type)
  
        var exprs []ir.Node
@@@ -558,7 -425,7 +558,7 @@@ func (p *noder) constDecl(decl *syntax.
                p.checkUnused(pragma)
        }
  
-       names := p.declNames(decl.NameList)
+       names := p.declNames(ir.OLITERAL, decl.NameList)
        typ := p.typeExprOrNil(decl.Type)
  
        var values []ir.Node
  
        nn := make([]ir.Node, 0, len(names))
        for i, n := range names {
-               n := n.(*ir.Name)
                if i >= len(values) {
                        base.Errorf("missing value in const declaration")
                        break
                if decl.Values == nil {
                        v = ir.DeepCopy(n.Pos(), v)
                }
-               n.SetOp(ir.OLITERAL)
                declare(n, dclcontext)
  
                n.Ntype = typ
  }
  
  func (p *noder) typeDecl(decl *syntax.TypeDecl) ir.Node {
-       n := p.declName(decl.Name)
-       n.SetOp(ir.OTYPE)
+       n := p.declName(ir.OTYPE, decl.Name)
        declare(n, dclcontext)
  
        // decl.Type may be nil but in that case we got a syntax error during parsing
        return nod
  }
  
- func (p *noder) declNames(names []*syntax.Name) []ir.Node {
-       nodes := make([]ir.Node, 0, len(names))
+ 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(name))
+               nodes = append(nodes, p.declName(op, name))
        }
        return nodes
  }
  
- func (p *noder) declName(name *syntax.Name) *ir.Name {
-       return ir.NewDeclNameAt(p.pos(name), p.name(name))
+ 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 {