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