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