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