]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/cmd/compile/internal/gc/main.go
[dev.typeparams] all: merge dev.regabi (37f138d) into dev.typeparams
[gostls13.git] / src / cmd / compile / internal / gc / main.go
index b9454604f0d5814289d7d15f6a11a28d76dfc517..c5870c650a2267048b3e341a2e0960158cd53e69 100644 (file)
@@ -10,30 +10,29 @@ import (
        "bufio"
        "bytes"
        "cmd/compile/internal/base"
+       "cmd/compile/internal/dwarfgen"
+       "cmd/compile/internal/escape"
+       "cmd/compile/internal/inline"
        "cmd/compile/internal/ir"
        "cmd/compile/internal/logopt"
+       "cmd/compile/internal/noder"
+       "cmd/compile/internal/pkginit"
+       "cmd/compile/internal/reflectdata"
        "cmd/compile/internal/ssa"
+       "cmd/compile/internal/ssagen"
+       "cmd/compile/internal/staticdata"
+       "cmd/compile/internal/typecheck"
        "cmd/compile/internal/types"
-       "cmd/internal/bio"
+       "cmd/compile/internal/walk"
        "cmd/internal/dwarf"
-       "cmd/internal/goobj"
        "cmd/internal/obj"
        "cmd/internal/objabi"
        "cmd/internal/src"
        "flag"
        "fmt"
-       "go/constant"
-       "internal/goversion"
-       "io"
-       "io/ioutil"
        "log"
        "os"
-       "path"
-       "regexp"
        "runtime"
-       "sort"
-       "strconv"
-       "strings"
 )
 
 func hidePanic() {
@@ -51,20 +50,17 @@ func hidePanic() {
        }
 }
 
-// Target is the package being compiled.
-var Target *ir.Package
-
 // 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.
-func Main(archInit func(*Arch)) {
-       timings.Start("fe", "init")
+func Main(archInit func(*ssagen.ArchInfo)) {
+       base.Timer.Start("fe", "init")
 
        defer hidePanic()
 
-       archInit(&thearch)
+       archInit(&ssagen.Arch)
 
-       base.Ctxt = obj.Linknew(thearch.LinkArch)
+       base.Ctxt = obj.Linknew(ssagen.Arch.LinkArch)
        base.Ctxt.DiagFunc = base.Errorf
        base.Ctxt.DiagFlush = base.FlushErrors
        base.Ctxt.Bso = bufio.NewWriter(os.Stdout)
@@ -88,32 +84,32 @@ func Main(archInit func(*Arch)) {
        types.BuiltinPkg.Prefix = "go.builtin"            // not go%2ebuiltin
 
        // pseudo-package, accessed by import "unsafe"
-       unsafepkg = types.NewPkg("unsafe", "unsafe")
+       ir.Pkgs.Unsafe = types.NewPkg("unsafe", "unsafe")
 
        // Pseudo-package that contains the compiler's builtin
        // declarations for package runtime. These are declared in a
        // separate package to avoid conflicts with package runtime's
        // actual declarations, which may differ intentionally but
        // insignificantly.
-       Runtimepkg = types.NewPkg("go.runtime", "runtime")
-       Runtimepkg.Prefix = "runtime"
+       ir.Pkgs.Runtime = types.NewPkg("go.runtime", "runtime")
+       ir.Pkgs.Runtime.Prefix = "runtime"
 
        // pseudo-packages used in symbol tables
-       itabpkg = types.NewPkg("go.itab", "go.itab")
-       itabpkg.Prefix = "go.itab" // not go%2eitab
+       ir.Pkgs.Itab = types.NewPkg("go.itab", "go.itab")
+       ir.Pkgs.Itab.Prefix = "go.itab" // not go%2eitab
 
-       itablinkpkg = types.NewPkg("go.itablink", "go.itablink")
-       itablinkpkg.Prefix = "go.itablink" // not go%2eitablink
+       ir.Pkgs.Itablink = types.NewPkg("go.itablink", "go.itablink")
+       ir.Pkgs.Itablink.Prefix = "go.itablink" // not go%2eitablink
 
-       trackpkg = types.NewPkg("go.track", "go.track")
-       trackpkg.Prefix = "go.track" // not go%2etrack
+       ir.Pkgs.Track = types.NewPkg("go.track", "go.track")
+       ir.Pkgs.Track.Prefix = "go.track" // not go%2etrack
 
        // pseudo-package used for map zero values
-       mappkg = types.NewPkg("go.map", "go.map")
-       mappkg.Prefix = "go.map"
+       ir.Pkgs.Map = types.NewPkg("go.map", "go.map")
+       ir.Pkgs.Map.Prefix = "go.map"
 
        // pseudo-package used for methods with anonymous receivers
-       gopkg = types.NewPkg("go", "")
+       ir.Pkgs.Go = types.NewPkg("go", "")
 
        base.DebugSSA = ssa.PhaseOption
        base.ParseFlags()
@@ -121,9 +117,9 @@ func Main(archInit func(*Arch)) {
        // Record flags that affect the build result. (And don't
        // record flags that don't, since that would cause spurious
        // changes in the binary.)
-       recordFlags("B", "N", "l", "msan", "race", "shared", "dynlink", "dwarflocationlists", "dwarfbasentries", "smallframes", "spectre")
+       dwarfgen.RecordFlags("B", "N", "l", "msan", "race", "shared", "dynlink", "dwarflocationlists", "dwarfbasentries", "smallframes", "spectre")
 
-       if !enableTrace && base.Flag.LowerT {
+       if !base.EnableTrace && base.Flag.LowerT {
                log.Fatalf("compiler not built with support for -t")
        }
 
@@ -136,13 +132,13 @@ func Main(archInit func(*Arch)) {
        }
 
        if base.Flag.SmallFrames {
-               maxStackVarSize = 128 * 1024
-               maxImplicitStackVarSize = 16 * 1024
+               ir.MaxStackVarSize = 128 * 1024
+               ir.MaxImplicitStackVarSize = 16 * 1024
        }
 
        if base.Flag.Dwarf {
-               base.Ctxt.DebugInfo = debuginfo
-               base.Ctxt.GenAbstractFunc = genAbstractFunc
+               base.Ctxt.DebugInfo = dwarfgen.Info
+               base.Ctxt.GenAbstractFunc = dwarfgen.AbstractFunc
                base.Ctxt.DwFixups = obj.NewDwarfFixupTable(base.Ctxt)
        } else {
                // turn off inline generation if no dwarf at all
@@ -153,104 +149,104 @@ func Main(archInit func(*Arch)) {
                log.Fatalf("location lists requested but register mapping not available on %v", base.Ctxt.Arch.Name)
        }
 
-       checkLang()
+       types.ParseLangFlag()
 
        if base.Flag.SymABIs != "" {
-               readSymABIs(base.Flag.SymABIs, base.Ctxt.Pkgpath)
+               ssagen.ReadSymABIs(base.Flag.SymABIs, base.Ctxt.Pkgpath)
        }
 
-       if ispkgin(omit_pkgs) {
+       if base.Compiling(base.NoInstrumentPkgs) {
                base.Flag.Race = false
                base.Flag.MSan = false
        }
 
-       thearch.LinkArch.Init(base.Ctxt)
+       ssagen.Arch.LinkArch.Init(base.Ctxt)
        startProfile()
        if base.Flag.Race {
-               racepkg = types.NewPkg("runtime/race", "")
+               ir.Pkgs.Race = types.NewPkg("runtime/race", "")
        }
        if base.Flag.MSan {
-               msanpkg = types.NewPkg("runtime/msan", "")
+               ir.Pkgs.Msan = types.NewPkg("runtime/msan", "")
        }
        if base.Flag.Race || base.Flag.MSan {
-               instrumenting = true
+               base.Flag.Cfg.Instrumenting = true
        }
        if base.Flag.Dwarf {
                dwarf.EnableLogging(base.Debug.DwarfInl != 0)
        }
        if base.Debug.SoftFloat != 0 {
-               thearch.SoftFloat = true
+               ssagen.Arch.SoftFloat = true
        }
 
        if base.Flag.JSON != "" { // parse version,destination from json logging optimization.
                logopt.LogJsonOption(base.Flag.JSON)
        }
 
-       ir.EscFmt = escFmt
-       IsIntrinsicCall = isIntrinsicCall
-       SSADumpInline = ssaDumpInline
-       initSSAEnv()
-       initSSATables()
+       ir.EscFmt = escape.Fmt
+       ir.IsIntrinsicCall = ssagen.IsIntrinsicCall
+       inline.SSADumpInline = ssagen.DumpInline
+       ssagen.InitEnv()
+       ssagen.InitTables()
 
-       Widthptr = thearch.LinkArch.PtrSize
-       Widthreg = thearch.LinkArch.RegSize
-       MaxWidth = thearch.MAXWIDTH
+       types.PtrSize = ssagen.Arch.LinkArch.PtrSize
+       types.RegSize = ssagen.Arch.LinkArch.RegSize
+       types.MaxWidth = ssagen.Arch.MAXWIDTH
        types.TypeLinkSym = func(t *types.Type) *obj.LSym {
-               return typenamesym(t).Linksym()
+               return reflectdata.TypeSym(t).Linksym()
        }
 
-       Target = new(ir.Package)
+       typecheck.Target = new(ir.Package)
 
-       NeedFuncSym = makefuncsym
-       NeedITab = func(t, iface *types.Type) { itabname(t, iface) }
-       NeedRuntimeType = addsignat // TODO(rsc): typenamesym for lock?
+       typecheck.NeedFuncSym = staticdata.NeedFuncSym
+       typecheck.NeedITab = func(t, iface *types.Type) { reflectdata.ITabAddr(t, iface) }
+       typecheck.NeedRuntimeType = reflectdata.NeedRuntimeType // TODO(rsc): typenamesym for lock?
 
-       autogeneratedPos = makePos(src.NewFileBase("<autogenerated>", "<autogenerated>"), 1, 0)
+       base.AutogeneratedPos = makePos(src.NewFileBase("<autogenerated>", "<autogenerated>"), 1, 0)
 
        types.TypeLinkSym = func(t *types.Type) *obj.LSym {
-               return typenamesym(t).Linksym()
+               return reflectdata.TypeSym(t).Linksym()
        }
-       TypecheckInit()
+       typecheck.Init()
 
        // Parse input.
-       timings.Start("fe", "parse")
-       lines := parseFiles(flag.Args())
-       cgoSymABIs()
-       timings.Stop()
-       timings.AddEvent(int64(lines), "lines")
+       base.Timer.Start("fe", "parse")
+       lines := noder.ParseFiles(flag.Args())
+       ssagen.CgoSymABIs()
+       base.Timer.Stop()
+       base.Timer.AddEvent(int64(lines), "lines")
        if base.Flag.G != 0 && base.Flag.G < 3 {
                // can only parse generic code for now
                base.ExitIfErrors()
                return
        }
 
-       recordPackageName()
+       dwarfgen.RecordPackageName()
 
        // Typecheck.
-       TypecheckPackage()
+       typecheck.Package()
 
        // With all user code typechecked, it's now safe to verify unused dot imports.
-       checkDotImports()
+       noder.CheckDotImports()
        base.ExitIfErrors()
 
        // Build init task.
-       if initTask := fninit(); initTask != nil {
-               exportsym(initTask)
+       if initTask := pkginit.Task(); initTask != nil {
+               typecheck.Export(initTask)
        }
 
        // Inlining
-       timings.Start("fe", "inlining")
+       base.Timer.Start("fe", "inlining")
        if base.Flag.LowerL != 0 {
-               InlinePackage()
+               inline.InlinePackage()
        }
 
        // Devirtualize.
-       for _, n := range Target.Decls {
+       for _, n := range typecheck.Target.Decls {
                if n.Op() == ir.ODCLFUNC {
-                       devirtualize(n.(*ir.Func))
+                       inline.Devirtualize(n.(*ir.Func))
                }
        }
-       Curfn = nil
+       ir.CurFunc = nil
 
        // Escape analysis.
        // Required for moving heap allocations onto stack,
@@ -260,27 +256,27 @@ func Main(archInit func(*Arch)) {
        // or else the stack copier will not update it.
        // Large values are also moved off stack in escape analysis;
        // because large values may contain pointers, it must happen early.
-       timings.Start("fe", "escapes")
-       escapes(Target.Decls)
+       base.Timer.Start("fe", "escapes")
+       escape.Funcs(typecheck.Target.Decls)
 
        // Collect information for go:nowritebarrierrec
        // checking. This must happen before transformclosure.
        // We'll do the final check after write barriers are
        // inserted.
        if base.Flag.CompilingRuntime {
-               EnableNoWriteBarrierRecCheck()
+               ssagen.EnableNoWriteBarrierRecCheck()
        }
 
        // 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 {
+       base.Timer.Start("fe", "xclosures")
+       for _, n := range typecheck.Target.Decls {
                if n.Op() == ir.ODCLFUNC {
                        n := n.(*ir.Func)
-                       if n.Func().OClosure != nil {
-                               Curfn = n
-                               transformclosure(n)
+                       if n.OClosure != nil {
+                               ir.CurFunc = n
+                               walk.Closure(n)
                        }
                }
        }
@@ -288,32 +284,32 @@ func Main(archInit func(*Arch)) {
        // Prepare for SSA compilation.
        // This must be before peekitabs, because peekitabs
        // can trigger function compilation.
-       initssaconfig()
+       ssagen.InitConfig()
 
        // Just before compilation, compile itabs found on
        // the right side of OCONVIFACE so that methods
        // can be de-virtualized during compilation.
-       Curfn = nil
-       peekitabs()
+       ir.CurFunc = nil
+       reflectdata.CompileITabs()
 
        // Compile top level functions.
        // Don't use range--walk can add functions to Target.Decls.
-       timings.Start("be", "compilefuncs")
+       base.Timer.Start("be", "compilefuncs")
        fcount := int64(0)
-       for i := 0; i < len(Target.Decls); i++ {
-               n := Target.Decls[i]
+       for i := 0; i < len(typecheck.Target.Decls); i++ {
+               n := typecheck.Target.Decls[i]
                if n.Op() == ir.ODCLFUNC {
                        funccompile(n.(*ir.Func))
                        fcount++
                }
        }
-       timings.AddEvent(fcount, "funcs")
+       base.Timer.AddEvent(fcount, "funcs")
 
        compileFunctions()
 
        if base.Flag.CompilingRuntime {
                // Write barriers are now known. Check the call graph.
-               NoWriteBarrierRecCheck()
+               ssagen.NoWriteBarrierRecCheck()
        }
 
        // Finalize DWARF inline routine DIEs, then explicitly turn off
@@ -326,7 +322,7 @@ func Main(archInit func(*Arch)) {
        }
 
        // Write object data to disk.
-       timings.Start("be", "dumpobj")
+       base.Timer.Start("be", "dumpobj")
        dumpdata()
        base.Ctxt.NumberSyms()
        dumpobj()
@@ -334,8 +330,8 @@ func Main(archInit func(*Arch)) {
                dumpasmhdr()
        }
 
-       CheckLargeStacks()
-       CheckFuncStack()
+       ssagen.CheckLargeStacks()
+       typecheck.CheckFuncStack()
 
        if len(compilequeue) != 0 {
                base.Fatalf("%d uncompiled functions", len(compilequeue))
@@ -345,7 +341,7 @@ func Main(archInit func(*Arch)) {
        base.ExitIfErrors()
 
        base.FlushErrors()
-       timings.Stop()
+       base.Timer.Stop()
 
        if base.Flag.Bench != "" {
                if err := writebench(base.Flag.Bench); err != nil {
@@ -354,45 +350,6 @@ func Main(archInit func(*Arch)) {
        }
 }
 
-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.
-       for _, prag := range Target.CgoPragmas {
-               switch prag[0] {
-               case "cgo_export_static", "cgo_export_dynamic":
-                       if symabiRefs == nil {
-                               symabiRefs = make(map[string]obj.ABI)
-                       }
-                       symabiRefs[prag[1]] = obj.ABI0
-               }
-       }
-}
-
-// numNonClosures returns the number of functions in list which are not closures.
-func numNonClosures(list []*ir.Func) int {
-       count := 0
-       for _, fn := range list {
-               if fn.OClosure == nil {
-                       count++
-               }
-       }
-       return count
-}
-
 func writebench(filename string) error {
        f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
        if err != nil {
@@ -403,7 +360,7 @@ func writebench(filename string) error {
        fmt.Fprintln(&buf, "commit:", objabi.Version)
        fmt.Fprintln(&buf, "goos:", runtime.GOOS)
        fmt.Fprintln(&buf, "goarch:", runtime.GOARCH)
-       timings.Write(&buf, "BenchmarkCompile:"+base.Ctxt.Pkgpath+":")
+       base.Timer.Write(&buf, "BenchmarkCompile:"+base.Ctxt.Pkgpath+":")
 
        n, err := f.Write(buf.Bytes())
        if err != nil {
@@ -416,642 +373,6 @@ func writebench(filename string) error {
        return f.Close()
 }
 
-// symabiDefs and symabiRefs record the defined and referenced ABIs of
-// symbols required by non-Go code. These are keyed by link symbol
-// name, where the local package prefix is always `"".`
-var symabiDefs, symabiRefs map[string]obj.ABI
-
-// readSymABIs reads a symabis file that specifies definitions and
-// references of text symbols by ABI.
-//
-// The symabis format is a set of lines, where each line is a sequence
-// of whitespace-separated fields. The first field is a verb and is
-// either "def" for defining a symbol ABI or "ref" for referencing a
-// symbol using an ABI. For both "def" and "ref", the second field is
-// the symbol name and the third field is the ABI name, as one of the
-// named cmd/internal/obj.ABI constants.
-func readSymABIs(file, myimportpath string) {
-       data, err := ioutil.ReadFile(file)
-       if err != nil {
-               log.Fatalf("-symabis: %v", err)
-       }
-
-       symabiDefs = make(map[string]obj.ABI)
-       symabiRefs = make(map[string]obj.ABI)
-
-       localPrefix := ""
-       if myimportpath != "" {
-               // Symbols in this package may be written either as
-               // "".X or with the package's import path already in
-               // the symbol.
-               localPrefix = objabi.PathToPrefix(myimportpath) + "."
-       }
-
-       for lineNum, line := range strings.Split(string(data), "\n") {
-               lineNum++ // 1-based
-               line = strings.TrimSpace(line)
-               if line == "" || strings.HasPrefix(line, "#") {
-                       continue
-               }
-
-               parts := strings.Fields(line)
-               switch parts[0] {
-               case "def", "ref":
-                       // Parse line.
-                       if len(parts) != 3 {
-                               log.Fatalf(`%s:%d: invalid symabi: syntax is "%s sym abi"`, file, lineNum, parts[0])
-                       }
-                       sym, abistr := parts[1], parts[2]
-                       abi, valid := obj.ParseABI(abistr)
-                       if !valid {
-                               log.Fatalf(`%s:%d: invalid symabi: unknown abi "%s"`, file, lineNum, abistr)
-                       }
-
-                       // If the symbol is already prefixed with
-                       // myimportpath, rewrite it to start with ""
-                       // so it matches the compiler's internal
-                       // symbol names.
-                       if localPrefix != "" && strings.HasPrefix(sym, localPrefix) {
-                               sym = `"".` + sym[len(localPrefix):]
-                       }
-
-                       // Record for later.
-                       if parts[0] == "def" {
-                               symabiDefs[sym] = abi
-                       } else {
-                               symabiRefs[sym] = abi
-                       }
-               default:
-                       log.Fatalf(`%s:%d: invalid symabi type "%s"`, file, lineNum, parts[0])
-               }
-       }
-}
-
-func arsize(b *bufio.Reader, name string) int {
-       var buf [ArhdrSize]byte
-       if _, err := io.ReadFull(b, buf[:]); err != nil {
-               return -1
-       }
-       aname := strings.Trim(string(buf[0:16]), " ")
-       if !strings.HasPrefix(aname, name) {
-               return -1
-       }
-       asize := strings.Trim(string(buf[48:58]), " ")
-       i, _ := strconv.Atoi(asize)
-       return i
-}
-
-func isDriveLetter(b byte) bool {
-       return 'a' <= b && b <= 'z' || 'A' <= b && b <= 'Z'
-}
-
-// is this path a local name? begins with ./ or ../ or /
-func islocalname(name string) bool {
-       return strings.HasPrefix(name, "/") ||
-               runtime.GOOS == "windows" && len(name) >= 3 && isDriveLetter(name[0]) && name[1] == ':' && name[2] == '/' ||
-               strings.HasPrefix(name, "./") || name == "." ||
-               strings.HasPrefix(name, "../") || name == ".."
-}
-
-func findpkg(name string) (file string, ok bool) {
-       if islocalname(name) {
-               if base.Flag.NoLocalImports {
-                       return "", false
-               }
-
-               if base.Flag.Cfg.PackageFile != nil {
-                       file, ok = base.Flag.Cfg.PackageFile[name]
-                       return file, ok
-               }
-
-               // try .a before .6.  important for building libraries:
-               // if there is an array.6 in the array.a library,
-               // want to find all of array.a, not just array.6.
-               file = fmt.Sprintf("%s.a", name)
-               if _, err := os.Stat(file); err == nil {
-                       return file, true
-               }
-               file = fmt.Sprintf("%s.o", name)
-               if _, err := os.Stat(file); err == nil {
-                       return file, true
-               }
-               return "", false
-       }
-
-       // local imports should be canonicalized already.
-       // don't want to see "encoding/../encoding/base64"
-       // as different from "encoding/base64".
-       if q := path.Clean(name); q != name {
-               base.Errorf("non-canonical import path %q (should be %q)", name, q)
-               return "", false
-       }
-
-       if base.Flag.Cfg.PackageFile != nil {
-               file, ok = base.Flag.Cfg.PackageFile[name]
-               return file, ok
-       }
-
-       for _, dir := range base.Flag.Cfg.ImportDirs {
-               file = fmt.Sprintf("%s/%s.a", dir, name)
-               if _, err := os.Stat(file); err == nil {
-                       return file, true
-               }
-               file = fmt.Sprintf("%s/%s.o", dir, name)
-               if _, err := os.Stat(file); err == nil {
-                       return file, true
-               }
-       }
-
-       if objabi.GOROOT != "" {
-               suffix := ""
-               suffixsep := ""
-               if base.Flag.InstallSuffix != "" {
-                       suffixsep = "_"
-                       suffix = base.Flag.InstallSuffix
-               } else if base.Flag.Race {
-                       suffixsep = "_"
-                       suffix = "race"
-               } else if base.Flag.MSan {
-                       suffixsep = "_"
-                       suffix = "msan"
-               }
-
-               file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.a", objabi.GOROOT, objabi.GOOS, objabi.GOARCH, suffixsep, suffix, name)
-               if _, err := os.Stat(file); err == nil {
-                       return file, true
-               }
-               file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.o", objabi.GOROOT, objabi.GOOS, objabi.GOARCH, suffixsep, suffix, name)
-               if _, err := os.Stat(file); err == nil {
-                       return file, true
-               }
-       }
-
-       return "", false
-}
-
-// loadsys loads the definitions for the low-level runtime functions,
-// so that the compiler can generate calls to them,
-// but does not make them visible to user code.
-func loadsys() {
-       types.Block = 1
-
-       inimport = true
-       typecheckok = true
-
-       typs := runtimeTypes()
-       for _, d := range &runtimeDecls {
-               sym := Runtimepkg.Lookup(d.name)
-               typ := typs[d.typ]
-               switch d.tag {
-               case funcTag:
-                       importfunc(Runtimepkg, src.NoXPos, sym, typ)
-               case varTag:
-                       importvar(Runtimepkg, src.NoXPos, sym, typ)
-               default:
-                       base.Fatalf("unhandled declaration tag %v", d.tag)
-               }
-       }
-
-       typecheckok = false
-       inimport = false
-}
-
-// myheight tracks the local package's height based on packages
-// imported so far.
-var myheight int
-
-func importfile(f constant.Value) *types.Pkg {
-       if f.Kind() != constant.String {
-               base.Errorf("import path must be a string")
-               return nil
-       }
-
-       path_ := constant.StringVal(f)
-       if len(path_) == 0 {
-               base.Errorf("import path is empty")
-               return nil
-       }
-
-       if isbadimport(path_, false) {
-               return nil
-       }
-
-       // The package name main is no longer reserved,
-       // but we reserve the import path "main" to identify
-       // the main package, just as we reserve the import
-       // path "math" to identify the standard math package.
-       if path_ == "main" {
-               base.Errorf("cannot import \"main\"")
-               base.ErrorExit()
-       }
-
-       if base.Ctxt.Pkgpath != "" && path_ == base.Ctxt.Pkgpath {
-               base.Errorf("import %q while compiling that package (import cycle)", path_)
-               base.ErrorExit()
-       }
-
-       if mapped, ok := base.Flag.Cfg.ImportMap[path_]; ok {
-               path_ = mapped
-       }
-
-       if path_ == "unsafe" {
-               return unsafepkg
-       }
-
-       if islocalname(path_) {
-               if path_[0] == '/' {
-                       base.Errorf("import path cannot be absolute path")
-                       return nil
-               }
-
-               prefix := base.Ctxt.Pathname
-               if base.Flag.D != "" {
-                       prefix = base.Flag.D
-               }
-               path_ = path.Join(prefix, path_)
-
-               if isbadimport(path_, true) {
-                       return nil
-               }
-       }
-
-       file, found := findpkg(path_)
-       if !found {
-               base.Errorf("can't find import: %q", path_)
-               base.ErrorExit()
-       }
-
-       importpkg := types.NewPkg(path_, "")
-       if importpkg.Imported {
-               return importpkg
-       }
-
-       importpkg.Imported = true
-
-       imp, err := bio.Open(file)
-       if err != nil {
-               base.Errorf("can't open import: %q: %v", path_, err)
-               base.ErrorExit()
-       }
-       defer imp.Close()
-
-       // check object header
-       p, err := imp.ReadString('\n')
-       if err != nil {
-               base.Errorf("import %s: reading input: %v", file, err)
-               base.ErrorExit()
-       }
-
-       if p == "!<arch>\n" { // package archive
-               // package export block should be first
-               sz := arsize(imp.Reader, "__.PKGDEF")
-               if sz <= 0 {
-                       base.Errorf("import %s: not a package file", file)
-                       base.ErrorExit()
-               }
-               p, err = imp.ReadString('\n')
-               if err != nil {
-                       base.Errorf("import %s: reading input: %v", file, err)
-                       base.ErrorExit()
-               }
-       }
-
-       if !strings.HasPrefix(p, "go object ") {
-               base.Errorf("import %s: not a go object file: %s", file, p)
-               base.ErrorExit()
-       }
-       q := fmt.Sprintf("%s %s %s %s\n", objabi.GOOS, objabi.GOARCH, objabi.Version, objabi.Expstring())
-       if p[10:] != q {
-               base.Errorf("import %s: object is [%s] expected [%s]", file, p[10:], q)
-               base.ErrorExit()
-       }
-
-       // process header lines
-       for {
-               p, err = imp.ReadString('\n')
-               if err != nil {
-                       base.Errorf("import %s: reading input: %v", file, err)
-                       base.ErrorExit()
-               }
-               if p == "\n" {
-                       break // header ends with blank line
-               }
-       }
-
-       // Expect $$B\n to signal binary import format.
-
-       // look for $$
-       var c byte
-       for {
-               c, err = imp.ReadByte()
-               if err != nil {
-                       break
-               }
-               if c == '$' {
-                       c, err = imp.ReadByte()
-                       if c == '$' || err != nil {
-                               break
-                       }
-               }
-       }
-
-       // get character after $$
-       if err == nil {
-               c, _ = imp.ReadByte()
-       }
-
-       var fingerprint goobj.FingerprintType
-       switch c {
-       case '\n':
-               base.Errorf("cannot import %s: old export format no longer supported (recompile library)", path_)
-               return nil
-
-       case 'B':
-               if base.Debug.Export != 0 {
-                       fmt.Printf("importing %s (%s)\n", path_, file)
-               }
-               imp.ReadByte() // skip \n after $$B
-
-               c, err = imp.ReadByte()
-               if err != nil {
-                       base.Errorf("import %s: reading input: %v", file, err)
-                       base.ErrorExit()
-               }
-
-               // Indexed format is distinguished by an 'i' byte,
-               // whereas previous export formats started with 'c', 'd', or 'v'.
-               if c != 'i' {
-                       base.Errorf("import %s: unexpected package format byte: %v", file, c)
-                       base.ErrorExit()
-               }
-               fingerprint = iimport(importpkg, imp)
-
-       default:
-               base.Errorf("no import in %q", path_)
-               base.ErrorExit()
-       }
-
-       // assume files move (get installed) so don't record the full path
-       if base.Flag.Cfg.PackageFile != nil {
-               // If using a packageFile map, assume path_ can be recorded directly.
-               base.Ctxt.AddImport(path_, fingerprint)
-       } else {
-               // For file "/Users/foo/go/pkg/darwin_amd64/math.a" record "math.a".
-               base.Ctxt.AddImport(file[len(file)-len(path_)-len(".a"):], fingerprint)
-       }
-
-       if importpkg.Height >= myheight {
-               myheight = importpkg.Height + 1
-       }
-
-       return importpkg
-}
-
-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 IsAlias(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)
-       }
-}
-
-func IsAlias(sym *types.Sym) bool {
-       return sym.Def != nil && sym.Def.Sym() != sym
-}
-
-// recordFlags records the specified command-line flags to be placed
-// in the DWARF info.
-func recordFlags(flags ...string) {
-       if base.Ctxt.Pkgpath == "" {
-               // We can't record the flags if we don't know what the
-               // package name is.
-               return
-       }
-
-       type BoolFlag interface {
-               IsBoolFlag() bool
-       }
-       type CountFlag interface {
-               IsCountFlag() bool
-       }
-       var cmd bytes.Buffer
-       for _, name := range flags {
-               f := flag.Lookup(name)
-               if f == nil {
-                       continue
-               }
-               getter := f.Value.(flag.Getter)
-               if getter.String() == f.DefValue {
-                       // Flag has default value, so omit it.
-                       continue
-               }
-               if bf, ok := f.Value.(BoolFlag); ok && bf.IsBoolFlag() {
-                       val, ok := getter.Get().(bool)
-                       if ok && val {
-                               fmt.Fprintf(&cmd, " -%s", f.Name)
-                               continue
-                       }
-               }
-               if cf, ok := f.Value.(CountFlag); ok && cf.IsCountFlag() {
-                       val, ok := getter.Get().(int)
-                       if ok && val == 1 {
-                               fmt.Fprintf(&cmd, " -%s", f.Name)
-                               continue
-                       }
-               }
-               fmt.Fprintf(&cmd, " -%s=%v", f.Name, getter.Get())
-       }
-
-       if cmd.Len() == 0 {
-               return
-       }
-       s := base.Ctxt.Lookup(dwarf.CUInfoPrefix + "producer." + base.Ctxt.Pkgpath)
-       s.Type = objabi.SDWARFCUINFO
-       // Sometimes (for example when building tests) we can link
-       // together two package main archives. So allow dups.
-       s.Set(obj.AttrDuplicateOK, true)
-       base.Ctxt.Data = append(base.Ctxt.Data, s)
-       s.P = cmd.Bytes()[1:]
-}
-
-// recordPackageName records the name of the package being
-// compiled, so that the linker can save it in the compile unit's DIE.
-func recordPackageName() {
-       s := base.Ctxt.Lookup(dwarf.CUInfoPrefix + "packagename." + base.Ctxt.Pkgpath)
-       s.Type = objabi.SDWARFCUINFO
-       // Sometimes (for example when building tests) we can link
-       // together two package main archives. So allow dups.
-       s.Set(obj.AttrDuplicateOK, true)
-       base.Ctxt.Data = append(base.Ctxt.Data, s)
-       s.P = []byte(types.LocalPkg.Name)
-}
-
-// currentLang returns the current language version.
-func currentLang() string {
-       return fmt.Sprintf("go1.%d", goversion.Version)
-}
-
-// goVersionRE is a regular expression that matches the valid
-// arguments to the -lang flag.
-var goVersionRE = regexp.MustCompile(`^go([1-9][0-9]*)\.(0|[1-9][0-9]*)$`)
-
-// A lang is a language version broken into major and minor numbers.
-type lang struct {
-       major, minor int
-}
-
-// langWant is the desired language version set by the -lang flag.
-// If the -lang flag is not set, this is the zero value, meaning that
-// any language version is supported.
-var langWant lang
-
-// 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
-       }
-       if 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() {
-       if base.Flag.Lang == "" {
-               return
-       }
-
-       var err error
-       langWant, err = parseLang(base.Flag.Lang)
-       if err != nil {
-               log.Fatalf("invalid value %q for -lang: %v", base.Flag.Lang, err)
-       }
-
-       if def := currentLang(); base.Flag.Lang != def {
-               defVers, err := parseLang(def)
-               if err != nil {
-                       log.Fatalf("internal error parsing default lang %q: %v", def, err)
-               }
-               if langWant.major > defVers.major || (langWant.major == defVers.major && langWant.minor > defVers.minor) {
-                       log.Fatalf("invalid value %q for -lang: max known version is %q", base.Flag.Lang, def)
-               }
-       }
-}
-
-// parseLang parses a -lang option into a langVer.
-func parseLang(s string) (lang, error) {
-       matches := goVersionRE.FindStringSubmatch(s)
-       if matches == nil {
-               return lang{}, fmt.Errorf(`should be something like "go1.12"`)
-       }
-       major, err := strconv.Atoi(matches[1])
-       if err != nil {
-               return lang{}, err
-       }
-       minor, err := strconv.Atoi(matches[2])
-       if err != nil {
-               return lang{}, err
-       }
-       return lang{major: major, minor: minor}, nil
-}
-
-// 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)
-       }
-
-       return true
+func makePos(b *src.PosBase, line, col uint) src.XPos {
+       return base.Ctxt.PosTable.XPos(src.MakePos(b, line, col))
 }