github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/compile/internal/gc/main.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:generate go run mkbuiltin.go
     6  
     7  package gc
     8  
     9  import (
    10  	"bufio"
    11  	"bytes"
    12  	"github.com/gagliardetto/golang-go/cmd/compile/internal/logopt"
    13  	"github.com/gagliardetto/golang-go/cmd/compile/internal/ssa"
    14  	"github.com/gagliardetto/golang-go/cmd/compile/internal/types"
    15  	"github.com/gagliardetto/golang-go/cmd/internal/bio"
    16  	"github.com/gagliardetto/golang-go/cmd/internal/dwarf"
    17  	"github.com/gagliardetto/golang-go/cmd/internal/obj"
    18  	"github.com/gagliardetto/golang-go/cmd/internal/objabi"
    19  	"github.com/gagliardetto/golang-go/cmd/internal/src"
    20  	"github.com/gagliardetto/golang-go/cmd/internal/sys"
    21  	"flag"
    22  	"fmt"
    23  	"github.com/gagliardetto/golang-go/not-internal/goversion"
    24  	"io"
    25  	"io/ioutil"
    26  	"log"
    27  	"os"
    28  	"path"
    29  	"regexp"
    30  	"runtime"
    31  	"sort"
    32  	"strconv"
    33  	"strings"
    34  )
    35  
    36  var imported_unsafe bool
    37  
    38  var (
    39  	buildid string
    40  )
    41  
    42  var (
    43  	Debug_append       int
    44  	Debug_checkptr     int
    45  	Debug_closure      int
    46  	Debug_compilelater int
    47  	debug_dclstack     int
    48  	Debug_libfuzzer    int
    49  	Debug_panic        int
    50  	Debug_slice        int
    51  	Debug_vlog         bool
    52  	Debug_wb           int
    53  	Debug_pctab        string
    54  	Debug_locationlist int
    55  	Debug_typecheckinl int
    56  	Debug_gendwarfinl  int
    57  	Debug_softfloat    int
    58  	Debug_defer        int
    59  )
    60  
    61  // Debug arguments.
    62  // These can be specified with the -d flag, as in "-d nil"
    63  // to set the debug_checknil variable.
    64  // Multiple options can be comma-separated.
    65  // Each option accepts an optional argument, as in "gcprog=2"
    66  var debugtab = []struct {
    67  	name string
    68  	help string
    69  	val  interface{} // must be *int or *string
    70  }{
    71  	{"append", "print information about append compilation", &Debug_append},
    72  	{"checkptr", "instrument unsafe pointer conversions", &Debug_checkptr},
    73  	{"closure", "print information about closure compilation", &Debug_closure},
    74  	{"compilelater", "compile functions as late as possible", &Debug_compilelater},
    75  	{"disablenil", "disable nil checks", &disable_checknil},
    76  	{"dclstack", "run internal dclstack check", &debug_dclstack},
    77  	{"gcprog", "print dump of GC programs", &Debug_gcprog},
    78  	{"libfuzzer", "coverage instrumentation for libfuzzer", &Debug_libfuzzer},
    79  	{"nil", "print information about nil checks", &Debug_checknil},
    80  	{"panic", "do not hide any compiler panic", &Debug_panic},
    81  	{"slice", "print information about slice compilation", &Debug_slice},
    82  	{"typeassert", "print information about type assertion inlining", &Debug_typeassert},
    83  	{"wb", "print information about write barriers", &Debug_wb},
    84  	{"export", "print export data", &Debug_export},
    85  	{"pctab", "print named pc-value table", &Debug_pctab},
    86  	{"locationlists", "print information about DWARF location list creation", &Debug_locationlist},
    87  	{"typecheckinl", "eager typechecking of inline function bodies", &Debug_typecheckinl},
    88  	{"dwarfinl", "print information about DWARF inlined function creation", &Debug_gendwarfinl},
    89  	{"softfloat", "force compiler to emit soft-float code", &Debug_softfloat},
    90  	{"defer", "print information about defer compilation", &Debug_defer},
    91  }
    92  
    93  const debugHelpHeader = `usage: -d arg[,arg]* and arg is <key>[=<value>]
    94  
    95  <key> is one of:
    96  
    97  `
    98  
    99  const debugHelpFooter = `
   100  <value> is key-specific.
   101  
   102  Key "checkptr" supports values:
   103  	"0": instrumentation disabled
   104  	"1": conversions involving unsafe.Pointer are instrumented
   105  	"2": conversions to unsafe.Pointer force heap allocation
   106  
   107  Key "pctab" supports values:
   108  	"pctospadj", "pctofile", "pctoline", "pctoinline", "pctopcdata"
   109  `
   110  
   111  func usage() {
   112  	fmt.Fprintf(os.Stderr, "usage: compile [options] file.go...\n")
   113  	objabi.Flagprint(os.Stderr)
   114  	Exit(2)
   115  }
   116  
   117  func hidePanic() {
   118  	if Debug_panic == 0 && nsavederrors+nerrors > 0 {
   119  		// If we've already complained about things
   120  		// in the program, don't bother complaining
   121  		// about a panic too; let the user clean up
   122  		// the code and try again.
   123  		if err := recover(); err != nil {
   124  			errorexit()
   125  		}
   126  	}
   127  }
   128  
   129  // supportsDynlink reports whether or not the code generator for the given
   130  // architecture supports the -shared and -dynlink flags.
   131  func supportsDynlink(arch *sys.Arch) bool {
   132  	return arch.InFamily(sys.AMD64, sys.ARM, sys.ARM64, sys.I386, sys.PPC64, sys.S390X)
   133  }
   134  
   135  // timing data for compiler phases
   136  var timings Timings
   137  var benchfile string
   138  
   139  var nowritebarrierrecCheck *nowritebarrierrecChecker
   140  
   141  // Main parses flags and Go source files specified in the command-line
   142  // arguments, type-checks the parsed Go package, compiles functions to machine
   143  // code, and finally writes the compiled package definition to disk.
   144  func Main(archInit func(*Arch)) {
   145  	timings.Start("fe", "init")
   146  
   147  	defer hidePanic()
   148  
   149  	archInit(&thearch)
   150  
   151  	Ctxt = obj.Linknew(thearch.LinkArch)
   152  	Ctxt.DiagFunc = yyerror
   153  	Ctxt.DiagFlush = flusherrors
   154  	Ctxt.Bso = bufio.NewWriter(os.Stdout)
   155  
   156  	// UseBASEntries is preferred because it shaves about 2% off build time, but LLDB, dsymutil, and dwarfdump
   157  	// on Darwin don't support it properly, especially since macOS 10.14 (Mojave).  This is exposed as a flag
   158  	// to allow testing with LLVM tools on Linux, and to help with reporting this bug to the LLVM project.
   159  	// See bugs 31188 and 21945 (CLs 170638, 98075, 72371).
   160  	Ctxt.UseBASEntries = Ctxt.Headtype != objabi.Hdarwin
   161  
   162  	localpkg = types.NewPkg("", "")
   163  	localpkg.Prefix = "\"\""
   164  
   165  	// We won't know localpkg's height until after import
   166  	// processing. In the mean time, set to MaxPkgHeight to ensure
   167  	// height comparisons at least work until then.
   168  	localpkg.Height = types.MaxPkgHeight
   169  
   170  	// pseudo-package, for scoping
   171  	builtinpkg = types.NewPkg("go.builtin", "") // TODO(gri) name this package go.builtin?
   172  	builtinpkg.Prefix = "go.builtin"            // not go%2ebuiltin
   173  
   174  	// pseudo-package, accessed by import "unsafe"
   175  	unsafepkg = types.NewPkg("unsafe", "unsafe")
   176  
   177  	// Pseudo-package that contains the compiler's builtin
   178  	// declarations for package runtime. These are declared in a
   179  	// separate package to avoid conflicts with package runtime's
   180  	// actual declarations, which may differ intentionally but
   181  	// insignificantly.
   182  	Runtimepkg = types.NewPkg("go.runtime", "runtime")
   183  	Runtimepkg.Prefix = "runtime"
   184  
   185  	// pseudo-packages used in symbol tables
   186  	itabpkg = types.NewPkg("go.itab", "go.itab")
   187  	itabpkg.Prefix = "go.itab" // not go%2eitab
   188  
   189  	itablinkpkg = types.NewPkg("go.itablink", "go.itablink")
   190  	itablinkpkg.Prefix = "go.itablink" // not go%2eitablink
   191  
   192  	trackpkg = types.NewPkg("go.track", "go.track")
   193  	trackpkg.Prefix = "go.track" // not go%2etrack
   194  
   195  	// pseudo-package used for map zero values
   196  	mappkg = types.NewPkg("go.map", "go.map")
   197  	mappkg.Prefix = "go.map"
   198  
   199  	// pseudo-package used for methods with anonymous receivers
   200  	gopkg = types.NewPkg("go", "")
   201  
   202  	Wasm := objabi.GOARCH == "wasm"
   203  
   204  	// Whether the limit for stack-allocated objects is much smaller than normal.
   205  	// This can be helpful for diagnosing certain causes of GC latency. See #27732.
   206  	smallFrames := false
   207  	jsonLogOpt := ""
   208  
   209  	flag.BoolVar(&compiling_runtime, "+", false, "compiling runtime")
   210  	flag.BoolVar(&compiling_std, "std", false, "compiling standard library")
   211  	objabi.Flagcount("%", "debug non-static initializers", &Debug['%'])
   212  	objabi.Flagcount("B", "disable bounds checking", &Debug['B'])
   213  	objabi.Flagcount("C", "disable printing of columns in error messages", &Debug['C']) // TODO(gri) remove eventually
   214  	flag.StringVar(&localimport, "D", "", "set relative `path` for local imports")
   215  	objabi.Flagcount("E", "debug symbol export", &Debug['E'])
   216  	objabi.Flagfn1("I", "add `directory` to import search path", addidir)
   217  	objabi.Flagcount("K", "debug missing line numbers", &Debug['K'])
   218  	objabi.Flagcount("L", "show full file names in error messages", &Debug['L'])
   219  	objabi.Flagcount("N", "disable optimizations", &Debug['N'])
   220  	objabi.Flagcount("S", "print assembly listing", &Debug['S'])
   221  	objabi.AddVersionFlag() // -V
   222  	objabi.Flagcount("W", "debug parse tree after type checking", &Debug['W'])
   223  	flag.StringVar(&asmhdr, "asmhdr", "", "write assembly header to `file`")
   224  	flag.StringVar(&buildid, "buildid", "", "record `id` as the build id in the export metadata")
   225  	flag.IntVar(&nBackendWorkers, "c", 1, "concurrency during compilation, 1 means no concurrency")
   226  	flag.BoolVar(&pure_go, "complete", false, "compiling complete package (no C or assembly)")
   227  	flag.StringVar(&debugstr, "d", "", "print debug information about items in `list`; try -d help")
   228  	flag.BoolVar(&flagDWARF, "dwarf", !Wasm, "generate DWARF symbols")
   229  	flag.BoolVar(&Ctxt.Flag_locationlists, "dwarflocationlists", true, "add location lists to DWARF in optimized mode")
   230  	flag.IntVar(&genDwarfInline, "gendwarfinl", 2, "generate DWARF inline info records")
   231  	objabi.Flagcount("e", "no limit on number of errors reported", &Debug['e'])
   232  	objabi.Flagcount("h", "halt on error", &Debug['h'])
   233  	objabi.Flagfn1("importmap", "add `definition` of the form source=actual to import map", addImportMap)
   234  	objabi.Flagfn1("importcfg", "read import configuration from `file`", readImportCfg)
   235  	flag.StringVar(&flag_installsuffix, "installsuffix", "", "set pkg directory `suffix`")
   236  	objabi.Flagcount("j", "debug runtime-initialized variables", &Debug['j'])
   237  	objabi.Flagcount("l", "disable inlining", &Debug['l'])
   238  	flag.StringVar(&flag_lang, "lang", "", "release to compile for")
   239  	flag.StringVar(&linkobj, "linkobj", "", "write linker-specific object to `file`")
   240  	objabi.Flagcount("live", "debug liveness analysis", &debuglive)
   241  	objabi.Flagcount("m", "print optimization decisions", &Debug['m'])
   242  	if sys.MSanSupported(objabi.GOOS, objabi.GOARCH) {
   243  		flag.BoolVar(&flag_msan, "msan", false, "build code compatible with C/C++ memory sanitizer")
   244  	}
   245  	flag.BoolVar(&nolocalimports, "nolocalimports", false, "reject local (relative) imports")
   246  	flag.StringVar(&outfile, "o", "", "write output to `file`")
   247  	flag.StringVar(&myimportpath, "p", "", "set expected package import `path`")
   248  	flag.BoolVar(&writearchive, "pack", false, "write to file.a instead of file.o")
   249  	objabi.Flagcount("r", "debug generated wrappers", &Debug['r'])
   250  	if sys.RaceDetectorSupported(objabi.GOOS, objabi.GOARCH) {
   251  		flag.BoolVar(&flag_race, "race", false, "enable race detector")
   252  	}
   253  	if enableTrace {
   254  		flag.BoolVar(&trace, "t", false, "trace type-checking")
   255  	}
   256  	flag.StringVar(&pathPrefix, "trimpath", "", "remove `prefix` from recorded source file paths")
   257  	flag.BoolVar(&Debug_vlog, "v", false, "increase debug verbosity")
   258  	objabi.Flagcount("w", "debug type checking", &Debug['w'])
   259  	flag.BoolVar(&use_writebarrier, "wb", true, "enable write barrier")
   260  	var flag_shared bool
   261  	var flag_dynlink bool
   262  	if supportsDynlink(thearch.LinkArch.Arch) {
   263  		flag.BoolVar(&flag_shared, "shared", false, "generate code that can be linked into a shared library")
   264  		flag.BoolVar(&flag_dynlink, "dynlink", false, "support references to Go symbols defined in other shared libraries")
   265  		flag.BoolVar(&Ctxt.Flag_linkshared, "linkshared", false, "generate code that will be linked against Go shared libraries")
   266  	}
   267  	flag.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to `file`")
   268  	flag.StringVar(&memprofile, "memprofile", "", "write memory profile to `file`")
   269  	flag.Int64Var(&memprofilerate, "memprofilerate", 0, "set runtime.MemProfileRate to `rate`")
   270  	var goversion string
   271  	flag.StringVar(&goversion, "goversion", "", "required version of the runtime")
   272  	var symabisPath string
   273  	flag.StringVar(&symabisPath, "symabis", "", "read symbol ABIs from `file`")
   274  	flag.StringVar(&traceprofile, "traceprofile", "", "write an execution trace to `file`")
   275  	flag.StringVar(&blockprofile, "blockprofile", "", "write block profile to `file`")
   276  	flag.StringVar(&mutexprofile, "mutexprofile", "", "write mutex profile to `file`")
   277  	flag.StringVar(&benchfile, "bench", "", "append benchmark times to `file`")
   278  	flag.BoolVar(&smallFrames, "smallframes", false, "reduce the size limit for stack allocated objects")
   279  	flag.BoolVar(&Ctxt.UseBASEntries, "dwarfbasentries", Ctxt.UseBASEntries, "use base address selection entries in DWARF")
   280  	flag.BoolVar(&Ctxt.Flag_newobj, "newobj", false, "use new object file format")
   281  	flag.StringVar(&jsonLogOpt, "json", "", "version,destination for JSON compiler/optimizer logging")
   282  
   283  	objabi.Flagparse(usage)
   284  
   285  	// Record flags that affect the build result. (And don't
   286  	// record flags that don't, since that would cause spurious
   287  	// changes in the binary.)
   288  	recordFlags("B", "N", "l", "msan", "race", "shared", "dynlink", "dwarflocationlists", "dwarfbasentries", "smallframes", "newobj")
   289  
   290  	if smallFrames {
   291  		maxStackVarSize = 128 * 1024
   292  		maxImplicitStackVarSize = 16 * 1024
   293  	}
   294  
   295  	Ctxt.Flag_shared = flag_dynlink || flag_shared
   296  	Ctxt.Flag_dynlink = flag_dynlink
   297  	Ctxt.Flag_optimize = Debug['N'] == 0
   298  
   299  	Ctxt.Debugasm = Debug['S']
   300  	Ctxt.Debugvlog = Debug_vlog
   301  	if flagDWARF {
   302  		Ctxt.DebugInfo = debuginfo
   303  		Ctxt.GenAbstractFunc = genAbstractFunc
   304  		Ctxt.DwFixups = obj.NewDwarfFixupTable(Ctxt)
   305  	} else {
   306  		// turn off inline generation if no dwarf at all
   307  		genDwarfInline = 0
   308  		Ctxt.Flag_locationlists = false
   309  	}
   310  
   311  	if flag.NArg() < 1 && debugstr != "help" && debugstr != "ssa/help" {
   312  		usage()
   313  	}
   314  
   315  	if goversion != "" && goversion != runtime.Version() {
   316  		fmt.Printf("compile: version %q does not match go tool version %q\n", runtime.Version(), goversion)
   317  		Exit(2)
   318  	}
   319  
   320  	checkLang()
   321  
   322  	if symabisPath != "" {
   323  		readSymABIs(symabisPath, myimportpath)
   324  	}
   325  
   326  	thearch.LinkArch.Init(Ctxt)
   327  
   328  	if outfile == "" {
   329  		p := flag.Arg(0)
   330  		if i := strings.LastIndex(p, "/"); i >= 0 {
   331  			p = p[i+1:]
   332  		}
   333  		if runtime.GOOS == "windows" {
   334  			if i := strings.LastIndex(p, `\`); i >= 0 {
   335  				p = p[i+1:]
   336  			}
   337  		}
   338  		if i := strings.LastIndex(p, "."); i >= 0 {
   339  			p = p[:i]
   340  		}
   341  		suffix := ".o"
   342  		if writearchive {
   343  			suffix = ".a"
   344  		}
   345  		outfile = p + suffix
   346  	}
   347  
   348  	startProfile()
   349  
   350  	if flag_race && flag_msan {
   351  		log.Fatal("cannot use both -race and -msan")
   352  	}
   353  	if (flag_race || flag_msan) && objabi.GOOS != "windows" {
   354  		// -race and -msan imply -d=checkptr for now (except on windows).
   355  		// TODO(mdempsky): Re-evaluate before Go 1.14. See #34964.
   356  		Debug_checkptr = 1
   357  	}
   358  	if ispkgin(omit_pkgs) {
   359  		flag_race = false
   360  		flag_msan = false
   361  	}
   362  	if flag_race {
   363  		racepkg = types.NewPkg("runtime/race", "")
   364  	}
   365  	if flag_msan {
   366  		msanpkg = types.NewPkg("runtime/msan", "")
   367  	}
   368  	if flag_race || flag_msan {
   369  		instrumenting = true
   370  	}
   371  
   372  	if compiling_runtime && Debug['N'] != 0 {
   373  		log.Fatal("cannot disable optimizations while compiling runtime")
   374  	}
   375  	if nBackendWorkers < 1 {
   376  		log.Fatalf("-c must be at least 1, got %d", nBackendWorkers)
   377  	}
   378  	if nBackendWorkers > 1 && !concurrentBackendAllowed() {
   379  		log.Fatalf("cannot use concurrent backend compilation with provided flags; invoked as %v", os.Args)
   380  	}
   381  	if Ctxt.Flag_locationlists && len(Ctxt.Arch.DWARFRegisters) == 0 {
   382  		log.Fatalf("location lists requested but register mapping not available on %v", Ctxt.Arch.Name)
   383  	}
   384  
   385  	// parse -d argument
   386  	if debugstr != "" {
   387  	Split:
   388  		for _, name := range strings.Split(debugstr, ",") {
   389  			if name == "" {
   390  				continue
   391  			}
   392  			// display help about the -d option itself and quit
   393  			if name == "help" {
   394  				fmt.Print(debugHelpHeader)
   395  				maxLen := len("ssa/help")
   396  				for _, t := range debugtab {
   397  					if len(t.name) > maxLen {
   398  						maxLen = len(t.name)
   399  					}
   400  				}
   401  				for _, t := range debugtab {
   402  					fmt.Printf("\t%-*s\t%s\n", maxLen, t.name, t.help)
   403  				}
   404  				// ssa options have their own help
   405  				fmt.Printf("\t%-*s\t%s\n", maxLen, "ssa/help", "print help about SSA debugging")
   406  				fmt.Print(debugHelpFooter)
   407  				os.Exit(0)
   408  			}
   409  			val, valstring, haveInt := 1, "", true
   410  			if i := strings.IndexAny(name, "=:"); i >= 0 {
   411  				var err error
   412  				name, valstring = name[:i], name[i+1:]
   413  				val, err = strconv.Atoi(valstring)
   414  				if err != nil {
   415  					val, haveInt = 1, false
   416  				}
   417  			}
   418  			for _, t := range debugtab {
   419  				if t.name != name {
   420  					continue
   421  				}
   422  				switch vp := t.val.(type) {
   423  				case nil:
   424  					// Ignore
   425  				case *string:
   426  					*vp = valstring
   427  				case *int:
   428  					if !haveInt {
   429  						log.Fatalf("invalid debug value %v", name)
   430  					}
   431  					*vp = val
   432  				default:
   433  					panic("bad debugtab type")
   434  				}
   435  				continue Split
   436  			}
   437  			// special case for ssa for now
   438  			if strings.HasPrefix(name, "ssa/") {
   439  				// expect form ssa/phase/flag
   440  				// e.g. -d=ssa/generic_cse/time
   441  				// _ in phase name also matches space
   442  				phase := name[4:]
   443  				flag := "debug" // default flag is debug
   444  				if i := strings.Index(phase, "/"); i >= 0 {
   445  					flag = phase[i+1:]
   446  					phase = phase[:i]
   447  				}
   448  				err := ssa.PhaseOption(phase, flag, val, valstring)
   449  				if err != "" {
   450  					log.Fatalf(err)
   451  				}
   452  				continue Split
   453  			}
   454  			log.Fatalf("unknown debug key -d %s\n", name)
   455  		}
   456  	}
   457  
   458  	if compiling_runtime {
   459  		// Runtime can't use -d=checkptr, at least not yet.
   460  		Debug_checkptr = 0
   461  
   462  		// Fuzzing the runtime isn't interesting either.
   463  		Debug_libfuzzer = 0
   464  	}
   465  
   466  	// set via a -d flag
   467  	Ctxt.Debugpcln = Debug_pctab
   468  	if flagDWARF {
   469  		dwarf.EnableLogging(Debug_gendwarfinl != 0)
   470  	}
   471  
   472  	if Debug_softfloat != 0 {
   473  		thearch.SoftFloat = true
   474  	}
   475  
   476  	// enable inlining.  for now:
   477  	//	default: inlining on.  (debug['l'] == 1)
   478  	//	-l: inlining off  (debug['l'] == 0)
   479  	//	-l=2, -l=3: inlining on again, with extra debugging (debug['l'] > 1)
   480  	if Debug['l'] <= 1 {
   481  		Debug['l'] = 1 - Debug['l']
   482  	}
   483  
   484  	if jsonLogOpt != "" { // parse version,destination from json logging optimization.
   485  		logopt.LogJsonOption(jsonLogOpt)
   486  	}
   487  
   488  	ssaDump = os.Getenv("GOSSAFUNC")
   489  	if ssaDump != "" {
   490  		if strings.HasSuffix(ssaDump, "+") {
   491  			ssaDump = ssaDump[:len(ssaDump)-1]
   492  			ssaDumpStdout = true
   493  		}
   494  		spl := strings.Split(ssaDump, ":")
   495  		if len(spl) > 1 {
   496  			ssaDump = spl[0]
   497  			ssaDumpCFG = spl[1]
   498  		}
   499  	}
   500  
   501  	trackScopes = flagDWARF
   502  
   503  	Widthptr = thearch.LinkArch.PtrSize
   504  	Widthreg = thearch.LinkArch.RegSize
   505  
   506  	// initialize types package
   507  	// (we need to do this to break dependencies that otherwise
   508  	// would lead to import cycles)
   509  	types.Widthptr = Widthptr
   510  	types.Dowidth = dowidth
   511  	types.Fatalf = Fatalf
   512  	types.Sconv = func(s *types.Sym, flag, mode int) string {
   513  		return sconv(s, FmtFlag(flag), fmtMode(mode))
   514  	}
   515  	types.Tconv = func(t *types.Type, flag, mode int) string {
   516  		return tconv(t, FmtFlag(flag), fmtMode(mode))
   517  	}
   518  	types.FormatSym = func(sym *types.Sym, s fmt.State, verb rune, mode int) {
   519  		symFormat(sym, s, verb, fmtMode(mode))
   520  	}
   521  	types.FormatType = func(t *types.Type, s fmt.State, verb rune, mode int) {
   522  		typeFormat(t, s, verb, fmtMode(mode))
   523  	}
   524  	types.TypeLinkSym = func(t *types.Type) *obj.LSym {
   525  		return typenamesym(t).Linksym()
   526  	}
   527  	types.FmtLeft = int(FmtLeft)
   528  	types.FmtUnsigned = int(FmtUnsigned)
   529  	types.FErr = int(FErr)
   530  	types.Ctxt = Ctxt
   531  
   532  	initUniverse()
   533  
   534  	dclcontext = PEXTERN
   535  	nerrors = 0
   536  
   537  	autogeneratedPos = makePos(src.NewFileBase("<autogenerated>", "<autogenerated>"), 1, 0)
   538  
   539  	timings.Start("fe", "loadsys")
   540  	loadsys()
   541  
   542  	timings.Start("fe", "parse")
   543  	lines := parseFiles(flag.Args())
   544  	timings.Stop()
   545  	timings.AddEvent(int64(lines), "lines")
   546  
   547  	finishUniverse()
   548  
   549  	recordPackageName()
   550  
   551  	typecheckok = true
   552  
   553  	// Process top-level declarations in phases.
   554  
   555  	// Phase 1: const, type, and names and types of funcs.
   556  	//   This will gather all the information about types
   557  	//   and methods but doesn't depend on any of it.
   558  	//
   559  	//   We also defer type alias declarations until phase 2
   560  	//   to avoid cycles like #18640.
   561  	//   TODO(gri) Remove this again once we have a fix for #25838.
   562  
   563  	// Don't use range--typecheck can add closures to xtop.
   564  	timings.Start("fe", "typecheck", "top1")
   565  	for i := 0; i < len(xtop); i++ {
   566  		n := xtop[i]
   567  		if op := n.Op; op != ODCL && op != OAS && op != OAS2 && (op != ODCLTYPE || !n.Left.Name.Param.Alias) {
   568  			xtop[i] = typecheck(n, ctxStmt)
   569  		}
   570  	}
   571  
   572  	// Phase 2: Variable assignments.
   573  	//   To check interface assignments, depends on phase 1.
   574  
   575  	// Don't use range--typecheck can add closures to xtop.
   576  	timings.Start("fe", "typecheck", "top2")
   577  	for i := 0; i < len(xtop); i++ {
   578  		n := xtop[i]
   579  		if op := n.Op; op == ODCL || op == OAS || op == OAS2 || op == ODCLTYPE && n.Left.Name.Param.Alias {
   580  			xtop[i] = typecheck(n, ctxStmt)
   581  		}
   582  	}
   583  
   584  	// Phase 3: Type check function bodies.
   585  	// Don't use range--typecheck can add closures to xtop.
   586  	timings.Start("fe", "typecheck", "func")
   587  	var fcount int64
   588  	for i := 0; i < len(xtop); i++ {
   589  		n := xtop[i]
   590  		if op := n.Op; op == ODCLFUNC || op == OCLOSURE {
   591  			Curfn = n
   592  			decldepth = 1
   593  			saveerrors()
   594  			typecheckslice(Curfn.Nbody.Slice(), ctxStmt)
   595  			checkreturn(Curfn)
   596  			if nerrors != 0 {
   597  				Curfn.Nbody.Set(nil) // type errors; do not compile
   598  			}
   599  			// Now that we've checked whether n terminates,
   600  			// we can eliminate some obviously dead code.
   601  			deadcode(Curfn)
   602  			fcount++
   603  		}
   604  	}
   605  	// With all types checked, it's now safe to verify map keys. One single
   606  	// check past phase 9 isn't sufficient, as we may exit with other errors
   607  	// before then, thus skipping map key errors.
   608  	checkMapKeys()
   609  	timings.AddEvent(fcount, "funcs")
   610  
   611  	if nsavederrors+nerrors != 0 {
   612  		errorexit()
   613  	}
   614  
   615  	// Phase 4: Decide how to capture closed variables.
   616  	// This needs to run before escape analysis,
   617  	// because variables captured by value do not escape.
   618  	timings.Start("fe", "capturevars")
   619  	for _, n := range xtop {
   620  		if n.Op == ODCLFUNC && n.Func.Closure != nil {
   621  			Curfn = n
   622  			capturevars(n)
   623  		}
   624  	}
   625  	capturevarscomplete = true
   626  
   627  	Curfn = nil
   628  
   629  	if nsavederrors+nerrors != 0 {
   630  		errorexit()
   631  	}
   632  
   633  	// Phase 5: Inlining
   634  	timings.Start("fe", "inlining")
   635  	if Debug_typecheckinl != 0 {
   636  		// Typecheck imported function bodies if debug['l'] > 1,
   637  		// otherwise lazily when used or re-exported.
   638  		for _, n := range importlist {
   639  			if n.Func.Inl != nil {
   640  				saveerrors()
   641  				typecheckinl(n)
   642  			}
   643  		}
   644  
   645  		if nsavederrors+nerrors != 0 {
   646  			errorexit()
   647  		}
   648  	}
   649  
   650  	if Debug['l'] != 0 {
   651  		// Find functions that can be inlined and clone them before walk expands them.
   652  		visitBottomUp(xtop, func(list []*Node, recursive bool) {
   653  			for _, n := range list {
   654  				if !recursive {
   655  					caninl(n)
   656  				} else {
   657  					if Debug['m'] > 1 {
   658  						fmt.Printf("%v: cannot inline %v: recursive\n", n.Line(), n.Func.Nname)
   659  					}
   660  				}
   661  				inlcalls(n)
   662  			}
   663  		})
   664  	}
   665  
   666  	// Phase 6: Escape analysis.
   667  	// Required for moving heap allocations onto stack,
   668  	// which in turn is required by the closure implementation,
   669  	// which stores the addresses of stack variables into the closure.
   670  	// If the closure does not escape, it needs to be on the stack
   671  	// or else the stack copier will not update it.
   672  	// Large values are also moved off stack in escape analysis;
   673  	// because large values may contain pointers, it must happen early.
   674  	timings.Start("fe", "escapes")
   675  	escapes(xtop)
   676  
   677  	// Collect information for go:nowritebarrierrec
   678  	// checking. This must happen before transformclosure.
   679  	// We'll do the final check after write barriers are
   680  	// inserted.
   681  	if compiling_runtime {
   682  		nowritebarrierrecCheck = newNowritebarrierrecChecker()
   683  	}
   684  
   685  	// Phase 7: Transform closure bodies to properly reference captured variables.
   686  	// This needs to happen before walk, because closures must be transformed
   687  	// before walk reaches a call of a closure.
   688  	timings.Start("fe", "xclosures")
   689  	for _, n := range xtop {
   690  		if n.Op == ODCLFUNC && n.Func.Closure != nil {
   691  			Curfn = n
   692  			transformclosure(n)
   693  		}
   694  	}
   695  
   696  	// Prepare for SSA compilation.
   697  	// This must be before peekitabs, because peekitabs
   698  	// can trigger function compilation.
   699  	initssaconfig()
   700  
   701  	// Just before compilation, compile itabs found on
   702  	// the right side of OCONVIFACE so that methods
   703  	// can be de-virtualized during compilation.
   704  	Curfn = nil
   705  	peekitabs()
   706  
   707  	// Phase 8: Compile top level functions.
   708  	// Don't use range--walk can add functions to xtop.
   709  	timings.Start("be", "compilefuncs")
   710  	fcount = 0
   711  	for i := 0; i < len(xtop); i++ {
   712  		n := xtop[i]
   713  		if n.Op == ODCLFUNC {
   714  			funccompile(n)
   715  			fcount++
   716  		}
   717  	}
   718  	timings.AddEvent(fcount, "funcs")
   719  
   720  	if nsavederrors+nerrors == 0 {
   721  		fninit(xtop)
   722  	}
   723  
   724  	compileFunctions()
   725  
   726  	if nowritebarrierrecCheck != nil {
   727  		// Write barriers are now known. Check the
   728  		// call graph.
   729  		nowritebarrierrecCheck.check()
   730  		nowritebarrierrecCheck = nil
   731  	}
   732  
   733  	// Finalize DWARF inline routine DIEs, then explicitly turn off
   734  	// DWARF inlining gen so as to avoid problems with generated
   735  	// method wrappers.
   736  	if Ctxt.DwFixups != nil {
   737  		Ctxt.DwFixups.Finalize(myimportpath, Debug_gendwarfinl != 0)
   738  		Ctxt.DwFixups = nil
   739  		genDwarfInline = 0
   740  	}
   741  
   742  	// Phase 9: Check external declarations.
   743  	timings.Start("be", "externaldcls")
   744  	for i, n := range externdcl {
   745  		if n.Op == ONAME {
   746  			externdcl[i] = typecheck(externdcl[i], ctxExpr)
   747  		}
   748  	}
   749  	// Check the map keys again, since we typechecked the external
   750  	// declarations.
   751  	checkMapKeys()
   752  
   753  	if nerrors+nsavederrors != 0 {
   754  		errorexit()
   755  	}
   756  
   757  	// Write object data to disk.
   758  	timings.Start("be", "dumpobj")
   759  	dumpdata()
   760  	Ctxt.NumberSyms(false)
   761  	dumpobj()
   762  	if asmhdr != "" {
   763  		dumpasmhdr()
   764  	}
   765  
   766  	// Check whether any of the functions we have compiled have gigantic stack frames.
   767  	sort.Slice(largeStackFrames, func(i, j int) bool {
   768  		return largeStackFrames[i].pos.Before(largeStackFrames[j].pos)
   769  	})
   770  	for _, large := range largeStackFrames {
   771  		if large.callee != 0 {
   772  			yyerrorl(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)
   773  		} else {
   774  			yyerrorl(large.pos, "stack frame too large (>1GB): %d MB locals + %d MB args", large.locals>>20, large.args>>20)
   775  		}
   776  	}
   777  
   778  	if len(compilequeue) != 0 {
   779  		Fatalf("%d uncompiled functions", len(compilequeue))
   780  	}
   781  
   782  	logopt.FlushLoggedOpts(Ctxt, myimportpath)
   783  
   784  	if nerrors+nsavederrors != 0 {
   785  		errorexit()
   786  	}
   787  
   788  	flusherrors()
   789  	timings.Stop()
   790  
   791  	if benchfile != "" {
   792  		if err := writebench(benchfile); err != nil {
   793  			log.Fatalf("cannot write benchmark data: %v", err)
   794  		}
   795  	}
   796  }
   797  
   798  func writebench(filename string) error {
   799  	f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
   800  	if err != nil {
   801  		return err
   802  	}
   803  
   804  	var buf bytes.Buffer
   805  	fmt.Fprintln(&buf, "commit:", objabi.Version)
   806  	fmt.Fprintln(&buf, "goos:", runtime.GOOS)
   807  	fmt.Fprintln(&buf, "goarch:", runtime.GOARCH)
   808  	timings.Write(&buf, "BenchmarkCompile:"+myimportpath+":")
   809  
   810  	n, err := f.Write(buf.Bytes())
   811  	if err != nil {
   812  		return err
   813  	}
   814  	if n != buf.Len() {
   815  		panic("bad writer")
   816  	}
   817  
   818  	return f.Close()
   819  }
   820  
   821  var (
   822  	importMap   = map[string]string{}
   823  	packageFile map[string]string // nil means not in use
   824  )
   825  
   826  func addImportMap(s string) {
   827  	if strings.Count(s, "=") != 1 {
   828  		log.Fatal("-importmap argument must be of the form source=actual")
   829  	}
   830  	i := strings.Index(s, "=")
   831  	source, actual := s[:i], s[i+1:]
   832  	if source == "" || actual == "" {
   833  		log.Fatal("-importmap argument must be of the form source=actual; source and actual must be non-empty")
   834  	}
   835  	importMap[source] = actual
   836  }
   837  
   838  func readImportCfg(file string) {
   839  	packageFile = map[string]string{}
   840  	data, err := ioutil.ReadFile(file)
   841  	if err != nil {
   842  		log.Fatalf("-importcfg: %v", err)
   843  	}
   844  
   845  	for lineNum, line := range strings.Split(string(data), "\n") {
   846  		lineNum++ // 1-based
   847  		line = strings.TrimSpace(line)
   848  		if line == "" || strings.HasPrefix(line, "#") {
   849  			continue
   850  		}
   851  
   852  		var verb, args string
   853  		if i := strings.Index(line, " "); i < 0 {
   854  			verb = line
   855  		} else {
   856  			verb, args = line[:i], strings.TrimSpace(line[i+1:])
   857  		}
   858  		var before, after string
   859  		if i := strings.Index(args, "="); i >= 0 {
   860  			before, after = args[:i], args[i+1:]
   861  		}
   862  		switch verb {
   863  		default:
   864  			log.Fatalf("%s:%d: unknown directive %q", file, lineNum, verb)
   865  		case "importmap":
   866  			if before == "" || after == "" {
   867  				log.Fatalf(`%s:%d: invalid importmap: syntax is "importmap old=new"`, file, lineNum)
   868  			}
   869  			importMap[before] = after
   870  		case "packagefile":
   871  			if before == "" || after == "" {
   872  				log.Fatalf(`%s:%d: invalid packagefile: syntax is "packagefile path=filename"`, file, lineNum)
   873  			}
   874  			packageFile[before] = after
   875  		}
   876  	}
   877  }
   878  
   879  // symabiDefs and symabiRefs record the defined and referenced ABIs of
   880  // symbols required by non-Go code. These are keyed by link symbol
   881  // name, where the local package prefix is always `"".`
   882  var symabiDefs, symabiRefs map[string]obj.ABI
   883  
   884  // readSymABIs reads a symabis file that specifies definitions and
   885  // references of text symbols by ABI.
   886  //
   887  // The symabis format is a set of lines, where each line is a sequence
   888  // of whitespace-separated fields. The first field is a verb and is
   889  // either "def" for defining a symbol ABI or "ref" for referencing a
   890  // symbol using an ABI. For both "def" and "ref", the second field is
   891  // the symbol name and the third field is the ABI name, as one of the
   892  // named cmd/internal/obj.ABI constants.
   893  func readSymABIs(file, myimportpath string) {
   894  	data, err := ioutil.ReadFile(file)
   895  	if err != nil {
   896  		log.Fatalf("-symabis: %v", err)
   897  	}
   898  
   899  	symabiDefs = make(map[string]obj.ABI)
   900  	symabiRefs = make(map[string]obj.ABI)
   901  
   902  	localPrefix := ""
   903  	if myimportpath != "" {
   904  		// Symbols in this package may be written either as
   905  		// "".X or with the package's import path already in
   906  		// the symbol.
   907  		localPrefix = objabi.PathToPrefix(myimportpath) + "."
   908  	}
   909  
   910  	for lineNum, line := range strings.Split(string(data), "\n") {
   911  		lineNum++ // 1-based
   912  		line = strings.TrimSpace(line)
   913  		if line == "" || strings.HasPrefix(line, "#") {
   914  			continue
   915  		}
   916  
   917  		parts := strings.Fields(line)
   918  		switch parts[0] {
   919  		case "def", "ref":
   920  			// Parse line.
   921  			if len(parts) != 3 {
   922  				log.Fatalf(`%s:%d: invalid symabi: syntax is "%s sym abi"`, file, lineNum, parts[0])
   923  			}
   924  			sym, abi := parts[1], parts[2]
   925  			if abi != "ABI0" { // Only supported external ABI right now
   926  				log.Fatalf(`%s:%d: invalid symabi: unknown abi "%s"`, file, lineNum, abi)
   927  			}
   928  
   929  			// If the symbol is already prefixed with
   930  			// myimportpath, rewrite it to start with ""
   931  			// so it matches the compiler's internal
   932  			// symbol names.
   933  			if localPrefix != "" && strings.HasPrefix(sym, localPrefix) {
   934  				sym = `"".` + sym[len(localPrefix):]
   935  			}
   936  
   937  			// Record for later.
   938  			if parts[0] == "def" {
   939  				symabiDefs[sym] = obj.ABI0
   940  			} else {
   941  				symabiRefs[sym] = obj.ABI0
   942  			}
   943  		default:
   944  			log.Fatalf(`%s:%d: invalid symabi type "%s"`, file, lineNum, parts[0])
   945  		}
   946  	}
   947  }
   948  
   949  func saveerrors() {
   950  	nsavederrors += nerrors
   951  	nerrors = 0
   952  }
   953  
   954  func arsize(b *bufio.Reader, name string) int {
   955  	var buf [ArhdrSize]byte
   956  	if _, err := io.ReadFull(b, buf[:]); err != nil {
   957  		return -1
   958  	}
   959  	aname := strings.Trim(string(buf[0:16]), " ")
   960  	if !strings.HasPrefix(aname, name) {
   961  		return -1
   962  	}
   963  	asize := strings.Trim(string(buf[48:58]), " ")
   964  	i, _ := strconv.Atoi(asize)
   965  	return i
   966  }
   967  
   968  var idirs []string
   969  
   970  func addidir(dir string) {
   971  	if dir != "" {
   972  		idirs = append(idirs, dir)
   973  	}
   974  }
   975  
   976  func isDriveLetter(b byte) bool {
   977  	return 'a' <= b && b <= 'z' || 'A' <= b && b <= 'Z'
   978  }
   979  
   980  // is this path a local name? begins with ./ or ../ or /
   981  func islocalname(name string) bool {
   982  	return strings.HasPrefix(name, "/") ||
   983  		runtime.GOOS == "windows" && len(name) >= 3 && isDriveLetter(name[0]) && name[1] == ':' && name[2] == '/' ||
   984  		strings.HasPrefix(name, "./") || name == "." ||
   985  		strings.HasPrefix(name, "../") || name == ".."
   986  }
   987  
   988  func findpkg(name string) (file string, ok bool) {
   989  	if islocalname(name) {
   990  		if nolocalimports {
   991  			return "", false
   992  		}
   993  
   994  		if packageFile != nil {
   995  			file, ok = packageFile[name]
   996  			return file, ok
   997  		}
   998  
   999  		// try .a before .6.  important for building libraries:
  1000  		// if there is an array.6 in the array.a library,
  1001  		// want to find all of array.a, not just array.6.
  1002  		file = fmt.Sprintf("%s.a", name)
  1003  		if _, err := os.Stat(file); err == nil {
  1004  			return file, true
  1005  		}
  1006  		file = fmt.Sprintf("%s.o", name)
  1007  		if _, err := os.Stat(file); err == nil {
  1008  			return file, true
  1009  		}
  1010  		return "", false
  1011  	}
  1012  
  1013  	// local imports should be canonicalized already.
  1014  	// don't want to see "encoding/../encoding/base64"
  1015  	// as different from "encoding/base64".
  1016  	if q := path.Clean(name); q != name {
  1017  		yyerror("non-canonical import path %q (should be %q)", name, q)
  1018  		return "", false
  1019  	}
  1020  
  1021  	if packageFile != nil {
  1022  		file, ok = packageFile[name]
  1023  		return file, ok
  1024  	}
  1025  
  1026  	for _, dir := range idirs {
  1027  		file = fmt.Sprintf("%s/%s.a", dir, name)
  1028  		if _, err := os.Stat(file); err == nil {
  1029  			return file, true
  1030  		}
  1031  		file = fmt.Sprintf("%s/%s.o", dir, name)
  1032  		if _, err := os.Stat(file); err == nil {
  1033  			return file, true
  1034  		}
  1035  	}
  1036  
  1037  	if objabi.GOROOT != "" {
  1038  		suffix := ""
  1039  		suffixsep := ""
  1040  		if flag_installsuffix != "" {
  1041  			suffixsep = "_"
  1042  			suffix = flag_installsuffix
  1043  		} else if flag_race {
  1044  			suffixsep = "_"
  1045  			suffix = "race"
  1046  		} else if flag_msan {
  1047  			suffixsep = "_"
  1048  			suffix = "msan"
  1049  		}
  1050  
  1051  		file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.a", objabi.GOROOT, objabi.GOOS, objabi.GOARCH, suffixsep, suffix, name)
  1052  		if _, err := os.Stat(file); err == nil {
  1053  			return file, true
  1054  		}
  1055  		file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.o", objabi.GOROOT, objabi.GOOS, objabi.GOARCH, suffixsep, suffix, name)
  1056  		if _, err := os.Stat(file); err == nil {
  1057  			return file, true
  1058  		}
  1059  	}
  1060  
  1061  	return "", false
  1062  }
  1063  
  1064  // loadsys loads the definitions for the low-level runtime functions,
  1065  // so that the compiler can generate calls to them,
  1066  // but does not make them visible to user code.
  1067  func loadsys() {
  1068  	types.Block = 1
  1069  
  1070  	inimport = true
  1071  	typecheckok = true
  1072  
  1073  	typs := runtimeTypes()
  1074  	for _, d := range runtimeDecls {
  1075  		sym := Runtimepkg.Lookup(d.name)
  1076  		typ := typs[d.typ]
  1077  		switch d.tag {
  1078  		case funcTag:
  1079  			importfunc(Runtimepkg, src.NoXPos, sym, typ)
  1080  		case varTag:
  1081  			importvar(Runtimepkg, src.NoXPos, sym, typ)
  1082  		default:
  1083  			Fatalf("unhandled declaration tag %v", d.tag)
  1084  		}
  1085  	}
  1086  
  1087  	typecheckok = false
  1088  	inimport = false
  1089  }
  1090  
  1091  // myheight tracks the local package's height based on packages
  1092  // imported so far.
  1093  var myheight int
  1094  
  1095  func importfile(f *Val) *types.Pkg {
  1096  	path_, ok := f.U.(string)
  1097  	if !ok {
  1098  		yyerror("import path must be a string")
  1099  		return nil
  1100  	}
  1101  
  1102  	if len(path_) == 0 {
  1103  		yyerror("import path is empty")
  1104  		return nil
  1105  	}
  1106  
  1107  	if isbadimport(path_, false) {
  1108  		return nil
  1109  	}
  1110  
  1111  	// The package name main is no longer reserved,
  1112  	// but we reserve the import path "main" to identify
  1113  	// the main package, just as we reserve the import
  1114  	// path "math" to identify the standard math package.
  1115  	if path_ == "main" {
  1116  		yyerror("cannot import \"main\"")
  1117  		errorexit()
  1118  	}
  1119  
  1120  	if myimportpath != "" && path_ == myimportpath {
  1121  		yyerror("import %q while compiling that package (import cycle)", path_)
  1122  		errorexit()
  1123  	}
  1124  
  1125  	if mapped, ok := importMap[path_]; ok {
  1126  		path_ = mapped
  1127  	}
  1128  
  1129  	if path_ == "unsafe" {
  1130  		imported_unsafe = true
  1131  		return unsafepkg
  1132  	}
  1133  
  1134  	if islocalname(path_) {
  1135  		if path_[0] == '/' {
  1136  			yyerror("import path cannot be absolute path")
  1137  			return nil
  1138  		}
  1139  
  1140  		prefix := Ctxt.Pathname
  1141  		if localimport != "" {
  1142  			prefix = localimport
  1143  		}
  1144  		path_ = path.Join(prefix, path_)
  1145  
  1146  		if isbadimport(path_, true) {
  1147  			return nil
  1148  		}
  1149  	}
  1150  
  1151  	file, found := findpkg(path_)
  1152  	if !found {
  1153  		yyerror("can't find import: %q", path_)
  1154  		errorexit()
  1155  	}
  1156  
  1157  	importpkg := types.NewPkg(path_, "")
  1158  	if importpkg.Imported {
  1159  		return importpkg
  1160  	}
  1161  
  1162  	importpkg.Imported = true
  1163  
  1164  	imp, err := bio.Open(file)
  1165  	if err != nil {
  1166  		yyerror("can't open import: %q: %v", path_, err)
  1167  		errorexit()
  1168  	}
  1169  	defer imp.Close()
  1170  
  1171  	// check object header
  1172  	p, err := imp.ReadString('\n')
  1173  	if err != nil {
  1174  		yyerror("import %s: reading input: %v", file, err)
  1175  		errorexit()
  1176  	}
  1177  
  1178  	if p == "!<arch>\n" { // package archive
  1179  		// package export block should be first
  1180  		sz := arsize(imp.Reader, "__.PKGDEF")
  1181  		if sz <= 0 {
  1182  			yyerror("import %s: not a package file", file)
  1183  			errorexit()
  1184  		}
  1185  		p, err = imp.ReadString('\n')
  1186  		if err != nil {
  1187  			yyerror("import %s: reading input: %v", file, err)
  1188  			errorexit()
  1189  		}
  1190  	}
  1191  
  1192  	if !strings.HasPrefix(p, "go object ") {
  1193  		yyerror("import %s: not a go object file: %s", file, p)
  1194  		errorexit()
  1195  	}
  1196  	q := fmt.Sprintf("%s %s %s %s\n", objabi.GOOS, objabi.GOARCH, objabi.Version, objabi.Expstring())
  1197  	if p[10:] != q {
  1198  		yyerror("import %s: object is [%s] expected [%s]", file, p[10:], q)
  1199  		errorexit()
  1200  	}
  1201  
  1202  	// process header lines
  1203  	for {
  1204  		p, err = imp.ReadString('\n')
  1205  		if err != nil {
  1206  			yyerror("import %s: reading input: %v", file, err)
  1207  			errorexit()
  1208  		}
  1209  		if p == "\n" {
  1210  			break // header ends with blank line
  1211  		}
  1212  	}
  1213  
  1214  	// assume files move (get installed) so don't record the full path
  1215  	if packageFile != nil {
  1216  		// If using a packageFile map, assume path_ can be recorded directly.
  1217  		Ctxt.AddImport(path_)
  1218  	} else {
  1219  		// For file "/Users/foo/go/pkg/darwin_amd64/math.a" record "math.a".
  1220  		Ctxt.AddImport(file[len(file)-len(path_)-len(".a"):])
  1221  	}
  1222  
  1223  	// In the importfile, if we find:
  1224  	// $$\n  (textual format): not supported anymore
  1225  	// $$B\n (binary format) : import directly, then feed the lexer a dummy statement
  1226  
  1227  	// look for $$
  1228  	var c byte
  1229  	for {
  1230  		c, err = imp.ReadByte()
  1231  		if err != nil {
  1232  			break
  1233  		}
  1234  		if c == '$' {
  1235  			c, err = imp.ReadByte()
  1236  			if c == '$' || err != nil {
  1237  				break
  1238  			}
  1239  		}
  1240  	}
  1241  
  1242  	// get character after $$
  1243  	if err == nil {
  1244  		c, _ = imp.ReadByte()
  1245  	}
  1246  
  1247  	switch c {
  1248  	case '\n':
  1249  		yyerror("cannot import %s: old export format no longer supported (recompile library)", path_)
  1250  		return nil
  1251  
  1252  	case 'B':
  1253  		if Debug_export != 0 {
  1254  			fmt.Printf("importing %s (%s)\n", path_, file)
  1255  		}
  1256  		imp.ReadByte() // skip \n after $$B
  1257  
  1258  		c, err = imp.ReadByte()
  1259  		if err != nil {
  1260  			yyerror("import %s: reading input: %v", file, err)
  1261  			errorexit()
  1262  		}
  1263  
  1264  		// Indexed format is distinguished by an 'i' byte,
  1265  		// whereas previous export formats started with 'c', 'd', or 'v'.
  1266  		if c != 'i' {
  1267  			yyerror("import %s: unexpected package format byte: %v", file, c)
  1268  			errorexit()
  1269  		}
  1270  		iimport(importpkg, imp)
  1271  
  1272  	default:
  1273  		yyerror("no import in %q", path_)
  1274  		errorexit()
  1275  	}
  1276  
  1277  	if importpkg.Height >= myheight {
  1278  		myheight = importpkg.Height + 1
  1279  	}
  1280  
  1281  	return importpkg
  1282  }
  1283  
  1284  func pkgnotused(lineno src.XPos, path string, name string) {
  1285  	// If the package was imported with a name other than the final
  1286  	// import path element, show it explicitly in the error message.
  1287  	// Note that this handles both renamed imports and imports of
  1288  	// packages containing unconventional package declarations.
  1289  	// Note that this uses / always, even on Windows, because Go import
  1290  	// paths always use forward slashes.
  1291  	elem := path
  1292  	if i := strings.LastIndex(elem, "/"); i >= 0 {
  1293  		elem = elem[i+1:]
  1294  	}
  1295  	if name == "" || elem == name {
  1296  		yyerrorl(lineno, "imported and not used: %q", path)
  1297  	} else {
  1298  		yyerrorl(lineno, "imported and not used: %q as %s", path, name)
  1299  	}
  1300  }
  1301  
  1302  func mkpackage(pkgname string) {
  1303  	if localpkg.Name == "" {
  1304  		if pkgname == "_" {
  1305  			yyerror("invalid package name _")
  1306  		}
  1307  		localpkg.Name = pkgname
  1308  	} else {
  1309  		if pkgname != localpkg.Name {
  1310  			yyerror("package %s; expected %s", pkgname, localpkg.Name)
  1311  		}
  1312  	}
  1313  }
  1314  
  1315  func clearImports() {
  1316  	type importedPkg struct {
  1317  		pos  src.XPos
  1318  		path string
  1319  		name string
  1320  	}
  1321  	var unused []importedPkg
  1322  
  1323  	for _, s := range localpkg.Syms {
  1324  		n := asNode(s.Def)
  1325  		if n == nil {
  1326  			continue
  1327  		}
  1328  		if n.Op == OPACK {
  1329  			// throw away top-level package name left over
  1330  			// from previous file.
  1331  			// leave s->block set to cause redeclaration
  1332  			// errors if a conflicting top-level name is
  1333  			// introduced by a different file.
  1334  			if !n.Name.Used() && nsyntaxerrors == 0 {
  1335  				unused = append(unused, importedPkg{n.Pos, n.Name.Pkg.Path, s.Name})
  1336  			}
  1337  			s.Def = nil
  1338  			continue
  1339  		}
  1340  		if IsAlias(s) {
  1341  			// throw away top-level name left over
  1342  			// from previous import . "x"
  1343  			if n.Name != nil && n.Name.Pack != nil && !n.Name.Pack.Name.Used() && nsyntaxerrors == 0 {
  1344  				unused = append(unused, importedPkg{n.Name.Pack.Pos, n.Name.Pack.Name.Pkg.Path, ""})
  1345  				n.Name.Pack.Name.SetUsed(true)
  1346  			}
  1347  			s.Def = nil
  1348  			continue
  1349  		}
  1350  	}
  1351  
  1352  	sort.Slice(unused, func(i, j int) bool { return unused[i].pos.Before(unused[j].pos) })
  1353  	for _, pkg := range unused {
  1354  		pkgnotused(pkg.pos, pkg.path, pkg.name)
  1355  	}
  1356  }
  1357  
  1358  func IsAlias(sym *types.Sym) bool {
  1359  	return sym.Def != nil && asNode(sym.Def).Sym != sym
  1360  }
  1361  
  1362  // By default, assume any debug flags are incompatible with concurrent compilation.
  1363  // A few are safe and potentially in common use for normal compiles, though; mark them as such here.
  1364  var concurrentFlagOK = [256]bool{
  1365  	'B': true, // disabled bounds checking
  1366  	'C': true, // disable printing of columns in error messages
  1367  	'e': true, // no limit on errors; errors all come from non-concurrent code
  1368  	'I': true, // add `directory` to import search path
  1369  	'N': true, // disable optimizations
  1370  	'l': true, // disable inlining
  1371  	'w': true, // all printing happens before compilation
  1372  	'W': true, // all printing happens before compilation
  1373  	'S': true, // printing disassembly happens at the end (but see concurrentBackendAllowed below)
  1374  }
  1375  
  1376  func concurrentBackendAllowed() bool {
  1377  	for i, x := range Debug {
  1378  		if x != 0 && !concurrentFlagOK[i] {
  1379  			return false
  1380  		}
  1381  	}
  1382  	// Debug['S'] by itself is ok, because all printing occurs
  1383  	// while writing the object file, and that is non-concurrent.
  1384  	// Adding Debug_vlog, however, causes Debug['S'] to also print
  1385  	// while flushing the plist, which happens concurrently.
  1386  	if Debug_vlog || debugstr != "" || debuglive > 0 {
  1387  		return false
  1388  	}
  1389  	// TODO: Test and delete this condition.
  1390  	if objabi.Fieldtrack_enabled != 0 {
  1391  		return false
  1392  	}
  1393  	// TODO: fix races and enable the following flags
  1394  	if Ctxt.Flag_shared || Ctxt.Flag_dynlink || flag_race {
  1395  		return false
  1396  	}
  1397  	return true
  1398  }
  1399  
  1400  // recordFlags records the specified command-line flags to be placed
  1401  // in the DWARF info.
  1402  func recordFlags(flags ...string) {
  1403  	if myimportpath == "" {
  1404  		// We can't record the flags if we don't know what the
  1405  		// package name is.
  1406  		return
  1407  	}
  1408  
  1409  	type BoolFlag interface {
  1410  		IsBoolFlag() bool
  1411  	}
  1412  	type CountFlag interface {
  1413  		IsCountFlag() bool
  1414  	}
  1415  	var cmd bytes.Buffer
  1416  	for _, name := range flags {
  1417  		f := flag.Lookup(name)
  1418  		if f == nil {
  1419  			continue
  1420  		}
  1421  		getter := f.Value.(flag.Getter)
  1422  		if getter.String() == f.DefValue {
  1423  			// Flag has default value, so omit it.
  1424  			continue
  1425  		}
  1426  		if bf, ok := f.Value.(BoolFlag); ok && bf.IsBoolFlag() {
  1427  			val, ok := getter.Get().(bool)
  1428  			if ok && val {
  1429  				fmt.Fprintf(&cmd, " -%s", f.Name)
  1430  				continue
  1431  			}
  1432  		}
  1433  		if cf, ok := f.Value.(CountFlag); ok && cf.IsCountFlag() {
  1434  			val, ok := getter.Get().(int)
  1435  			if ok && val == 1 {
  1436  				fmt.Fprintf(&cmd, " -%s", f.Name)
  1437  				continue
  1438  			}
  1439  		}
  1440  		fmt.Fprintf(&cmd, " -%s=%v", f.Name, getter.Get())
  1441  	}
  1442  
  1443  	if cmd.Len() == 0 {
  1444  		return
  1445  	}
  1446  	s := Ctxt.Lookup(dwarf.CUInfoPrefix + "producer." + myimportpath)
  1447  	s.Type = objabi.SDWARFINFO
  1448  	// Sometimes (for example when building tests) we can link
  1449  	// together two package main archives. So allow dups.
  1450  	s.Set(obj.AttrDuplicateOK, true)
  1451  	Ctxt.Data = append(Ctxt.Data, s)
  1452  	s.P = cmd.Bytes()[1:]
  1453  }
  1454  
  1455  // recordPackageName records the name of the package being
  1456  // compiled, so that the linker can save it in the compile unit's DIE.
  1457  func recordPackageName() {
  1458  	s := Ctxt.Lookup(dwarf.CUInfoPrefix + "packagename." + myimportpath)
  1459  	s.Type = objabi.SDWARFINFO
  1460  	// Sometimes (for example when building tests) we can link
  1461  	// together two package main archives. So allow dups.
  1462  	s.Set(obj.AttrDuplicateOK, true)
  1463  	Ctxt.Data = append(Ctxt.Data, s)
  1464  	s.P = []byte(localpkg.Name)
  1465  }
  1466  
  1467  // flag_lang is the language version we are compiling for, set by the -lang flag.
  1468  var flag_lang string
  1469  
  1470  // currentLang returns the current language version.
  1471  func currentLang() string {
  1472  	return fmt.Sprintf("go1.%d", goversion.Version)
  1473  }
  1474  
  1475  // goVersionRE is a regular expression that matches the valid
  1476  // arguments to the -lang flag.
  1477  var goVersionRE = regexp.MustCompile(`^go([1-9][0-9]*)\.(0|[1-9][0-9]*)$`)
  1478  
  1479  // A lang is a language version broken into major and minor numbers.
  1480  type lang struct {
  1481  	major, minor int
  1482  }
  1483  
  1484  // langWant is the desired language version set by the -lang flag.
  1485  // If the -lang flag is not set, this is the zero value, meaning that
  1486  // any language version is supported.
  1487  var langWant lang
  1488  
  1489  // langSupported reports whether language version major.minor is
  1490  // supported in a particular package.
  1491  func langSupported(major, minor int, pkg *types.Pkg) bool {
  1492  	if pkg == nil {
  1493  		// TODO(mdempsky): Set Pkg for local types earlier.
  1494  		pkg = localpkg
  1495  	}
  1496  	if pkg != localpkg {
  1497  		// Assume imported packages passed type-checking.
  1498  		return true
  1499  	}
  1500  
  1501  	if langWant.major == 0 && langWant.minor == 0 {
  1502  		return true
  1503  	}
  1504  	return langWant.major > major || (langWant.major == major && langWant.minor >= minor)
  1505  }
  1506  
  1507  // checkLang verifies that the -lang flag holds a valid value, and
  1508  // exits if not. It initializes data used by langSupported.
  1509  func checkLang() {
  1510  	if flag_lang == "" {
  1511  		return
  1512  	}
  1513  
  1514  	var err error
  1515  	langWant, err = parseLang(flag_lang)
  1516  	if err != nil {
  1517  		log.Fatalf("invalid value %q for -lang: %v", flag_lang, err)
  1518  	}
  1519  
  1520  	if def := currentLang(); flag_lang != def {
  1521  		defVers, err := parseLang(def)
  1522  		if err != nil {
  1523  			log.Fatalf("internal error parsing default lang %q: %v", def, err)
  1524  		}
  1525  		if langWant.major > defVers.major || (langWant.major == defVers.major && langWant.minor > defVers.minor) {
  1526  			log.Fatalf("invalid value %q for -lang: max known version is %q", flag_lang, def)
  1527  		}
  1528  	}
  1529  }
  1530  
  1531  // parseLang parses a -lang option into a langVer.
  1532  func parseLang(s string) (lang, error) {
  1533  	matches := goVersionRE.FindStringSubmatch(s)
  1534  	if matches == nil {
  1535  		return lang{}, fmt.Errorf(`should be something like "go1.12"`)
  1536  	}
  1537  	major, err := strconv.Atoi(matches[1])
  1538  	if err != nil {
  1539  		return lang{}, err
  1540  	}
  1541  	minor, err := strconv.Atoi(matches[2])
  1542  	if err != nil {
  1543  		return lang{}, err
  1544  	}
  1545  	return lang{major: major, minor: minor}, nil
  1546  }