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