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.
5 //go:generate go run mkbuiltin.go
12 "cmd/compile/internal/logopt"
13 "cmd/compile/internal/ssa"
14 "cmd/compile/internal/types"
37 var imported_unsafe bool
49 Debug_compilelater int
57 Debug_locationlist int
58 Debug_typecheckinl int
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 {
72 val interface{} // must be *int or *string
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},
96 const debugHelpHeader = `usage: -d arg[,arg]* and arg is <key>[=<value>]
102 const debugHelpFooter = `
103 <value> is key-specific.
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
110 Key "pctab" supports values:
111 "pctospadj", "pctofile", "pctoline", "pctoinline", "pctopcdata"
115 fmt.Fprintf(os.Stderr, "usage: compile [options] file.go...\n")
116 objabi.Flagprint(os.Stderr)
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 {
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)
138 // timing data for compiler phases
142 var nowritebarrierrecCheck *nowritebarrierrecChecker
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")
154 Ctxt = obj.Linknew(thearch.LinkArch)
155 Ctxt.DiagFunc = yyerror
156 Ctxt.DiagFlush = flusherrors
157 Ctxt.Bso = bufio.NewWriter(os.Stdout)
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
165 localpkg = types.NewPkg("", "")
166 localpkg.Prefix = "\"\""
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
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
177 // pseudo-package, accessed by import "unsafe"
178 unsafepkg = types.NewPkg("unsafe", "unsafe")
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
185 Runtimepkg = types.NewPkg("go.runtime", "runtime")
186 Runtimepkg.Prefix = "runtime"
188 // pseudo-packages used in symbol tables
189 itabpkg = types.NewPkg("go.itab", "go.itab")
190 itabpkg.Prefix = "go.itab" // not go%2eitab
192 itablinkpkg = types.NewPkg("go.itablink", "go.itablink")
193 itablinkpkg.Prefix = "go.itablink" // not go%2eitablink
195 trackpkg = types.NewPkg("go.track", "go.track")
196 trackpkg.Prefix = "go.track" // not go%2etrack
198 // pseudo-package used for map zero values
199 mappkg = types.NewPkg("go.map", "go.map")
200 mappkg.Prefix = "go.map"
202 // pseudo-package used for methods with anonymous receivers
203 gopkg = types.NewPkg("go", "")
205 Wasm := objabi.GOARCH == "wasm"
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.
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")
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)
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")
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")
259 flag.StringVar(&spectre, "spectre", spectre, "enable spectre mitigations in `list` (all, index, ret)")
261 flag.BoolVar(&trace, "t", false, "trace type-checking")
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")
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")
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`")
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")
288 objabi.Flagparse(usage)
290 Ctxt.Pkgpath = myimportpath
292 for _, f := range strings.Split(spectre, ",") {
293 f = strings.TrimSpace(f)
296 log.Fatalf("unknown setting -spectre=%s", f)
301 Ctxt.Retpoline = true
305 Ctxt.Retpoline = true
310 switch objabi.GOARCH {
314 log.Fatalf("GOARCH=%s does not support -spectre=index", objabi.GOARCH)
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")
324 maxStackVarSize = 128 * 1024
325 maxImplicitStackVarSize = 16 * 1024
328 Ctxt.Flag_shared = flag_dynlink || flag_shared
329 Ctxt.Flag_dynlink = flag_dynlink
330 Ctxt.Flag_optimize = Debug.N == 0
332 Ctxt.Debugasm = Debug.S
333 Ctxt.Debugvlog = Debug_vlog
335 Ctxt.DebugInfo = debuginfo
336 Ctxt.GenAbstractFunc = genAbstractFunc
337 Ctxt.DwFixups = obj.NewDwarfFixupTable(Ctxt)
339 // turn off inline generation if no dwarf at all
341 Ctxt.Flag_locationlists = false
344 if flag.NArg() < 1 && debugstr != "help" && debugstr != "ssa/help" {
348 if goversion != "" && goversion != runtime.Version() {
349 fmt.Printf("compile: version %q does not match go tool version %q\n", runtime.Version(), goversion)
355 if symabisPath != "" {
356 readSymABIs(symabisPath, myimportpath)
359 thearch.LinkArch.Init(Ctxt)
363 if i := strings.LastIndex(p, "/"); i >= 0 {
366 if runtime.GOOS == "windows" {
367 if i := strings.LastIndex(p, `\`); i >= 0 {
371 if i := strings.LastIndex(p, "."); i >= 0 {
383 if flag_race && flag_msan {
384 log.Fatal("cannot use both -race and -msan")
386 if flag_race || flag_msan {
387 // -race and -msan imply -d=checkptr for now.
390 if ispkgin(omit_pkgs) {
395 racepkg = types.NewPkg("runtime/race", "")
398 msanpkg = types.NewPkg("runtime/msan", "")
400 if flag_race || flag_msan {
404 if compiling_runtime && Debug.N != 0 {
405 log.Fatal("cannot disable optimizations while compiling runtime")
407 if nBackendWorkers < 1 {
408 log.Fatalf("-c must be at least 1, got %d", nBackendWorkers)
410 if nBackendWorkers > 1 && !concurrentBackendAllowed() {
411 log.Fatalf("cannot use concurrent backend compilation with provided flags; invoked as %v", os.Args)
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)
420 for _, name := range strings.Split(debugstr, ",") {
424 // display help about the -d option itself and quit
426 fmt.Print(debugHelpHeader)
427 maxLen := len("ssa/help")
428 for _, t := range debugtab {
429 if len(t.name) > maxLen {
433 for _, t := range debugtab {
434 fmt.Printf("\t%-*s\t%s\n", maxLen, t.name, t.help)
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)
441 val, valstring, haveInt := 1, "", true
442 if i := strings.IndexAny(name, "=:"); i >= 0 {
444 name, valstring = name[:i], name[i+1:]
445 val, err = strconv.Atoi(valstring)
447 val, haveInt = 1, false
450 for _, t := range debugtab {
454 switch vp := t.val.(type) {
461 log.Fatalf("invalid debug value %v", name)
465 panic("bad debugtab type")
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
475 flag := "debug" // default flag is debug
476 if i := strings.Index(phase, "/"); i >= 0 {
480 err := ssa.PhaseOption(phase, flag, val, valstring)
486 log.Fatalf("unknown debug key -d %s\n", name)
490 if compiling_runtime {
491 // Runtime can't use -d=checkptr, at least not yet.
494 // Fuzzing the runtime isn't interesting either.
499 Ctxt.Debugpcln = Debug_pctab
501 dwarf.EnableLogging(Debug_gendwarfinl != 0)
504 if Debug_softfloat != 0 {
505 thearch.SoftFloat = true
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)
513 Debug.l = 1 - Debug.l
516 if jsonLogOpt != "" { // parse version,destination from json logging optimization.
517 logopt.LogJsonOption(jsonLogOpt)
520 ssaDump = os.Getenv("GOSSAFUNC")
521 ssaDir = os.Getenv("GOSSADIR")
523 if strings.HasSuffix(ssaDump, "+") {
524 ssaDump = ssaDump[:len(ssaDump)-1]
527 spl := strings.Split(ssaDump, ":")
534 trackScopes = flagDWARF
536 Widthptr = thearch.LinkArch.PtrSize
537 Widthreg = thearch.LinkArch.RegSize
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))
548 types.Tconv = func(t *types.Type, flag, mode int) string {
549 return tconv(t, FmtFlag(flag), fmtMode(mode))
551 types.FormatSym = func(sym *types.Sym, s fmt.State, verb rune, mode int) {
552 symFormat(sym, s, verb, fmtMode(mode))
554 types.FormatType = func(t *types.Type, s fmt.State, verb rune, mode int) {
555 typeFormat(t, s, verb, fmtMode(mode))
557 types.TypeLinkSym = func(t *types.Type) *obj.LSym {
558 return typenamesym(t).Linksym()
560 types.FmtLeft = int(FmtLeft)
561 types.FmtUnsigned = int(FmtUnsigned)
562 types.FErr = int(FErr)
570 autogeneratedPos = makePos(src.NewFileBase("<autogenerated>", "<autogenerated>"), 1, 0)
572 timings.Start("fe", "loadsys")
575 timings.Start("fe", "parse")
576 lines := parseFiles(flag.Args())
578 timings.AddEvent(int64(lines), "lines")
586 // Process top-level declarations in phases.
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.
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.
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++ {
600 if op := n.Op; op != ODCL && op != OAS && op != OAS2 && (op != ODCLTYPE || !n.Left.Name.Param.Alias) {
601 xtop[i] = typecheck(n, ctxStmt)
605 // Phase 2: Variable assignments.
606 // To check interface assignments, depends on phase 1.
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++ {
612 if op := n.Op; op == ODCL || op == OAS || op == OAS2 || op == ODCLTYPE && n.Left.Name.Param.Alias {
613 xtop[i] = typecheck(n, ctxStmt)
617 // Phase 3: Type check function bodies.
618 // Don't use range--typecheck can add closures to xtop.
619 timings.Start("fe", "typecheck", "func")
621 for i := 0; i < len(xtop); i++ {
623 if n.Op == ODCLFUNC {
627 typecheckslice(Curfn.Nbody.Slice(), ctxStmt)
630 Curfn.Nbody.Set(nil) // type errors; do not compile
632 // Now that we've checked whether n terminates,
633 // we can eliminate some obviously dead code.
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.
642 timings.AddEvent(fcount, "funcs")
644 if nsavederrors+nerrors != 0 {
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 {
660 capturevarscomplete = true
664 if nsavederrors+nerrors != 0 {
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 {
680 if nsavederrors+nerrors != 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.
697 fmt.Printf("%v: cannot inline %v: recursive\n", n.Line(), n.Func.Nname)
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")
716 // Collect information for go:nowritebarrierrec
717 // checking. This must happen before transformclosure.
718 // We'll do the final check after write barriers are
720 if compiling_runtime {
721 nowritebarrierrecCheck = newNowritebarrierrecChecker()
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 {
735 // Prepare for SSA compilation.
736 // This must be before peekitabs, because peekitabs
737 // can trigger function compilation.
740 // Just before compilation, compile itabs found on
741 // the right side of OCONVIFACE so that methods
742 // can be de-virtualized during compilation.
746 // Phase 8: Compile top level functions.
747 // Don't use range--walk can add functions to xtop.
748 timings.Start("be", "compilefuncs")
750 for i := 0; i < len(xtop); i++ {
752 if n.Op == ODCLFUNC {
757 timings.AddEvent(fcount, "funcs")
761 if nowritebarrierrecCheck != nil {
762 // Write barriers are now known. Check the
764 nowritebarrierrecCheck.check()
765 nowritebarrierrecCheck = nil
768 // Finalize DWARF inline routine DIEs, then explicitly turn off
769 // DWARF inlining gen so as to avoid problems with generated
771 if Ctxt.DwFixups != nil {
772 Ctxt.DwFixups.Finalize(myimportpath, Debug_gendwarfinl != 0)
777 // Phase 9: Check external declarations.
778 timings.Start("be", "externaldcls")
779 for i, n := range externdcl {
781 externdcl[i] = typecheck(externdcl[i], ctxExpr)
784 // Check the map keys again, since we typechecked the external
788 if nerrors+nsavederrors != 0 {
792 // Write object data to disk.
793 timings.Start("be", "dumpobj")
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)
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)
809 yyerrorl(large.pos, "stack frame too large (>1GB): %d MB locals + %d MB args", large.locals>>20, large.args>>20)
813 if len(funcStack) != 0 {
814 Fatalf("funcStack is non-empty: %v", len(funcStack))
816 if len(compilequeue) != 0 {
817 Fatalf("%d uncompiled functions", len(compilequeue))
820 logopt.FlushLoggedOpts(Ctxt, myimportpath)
822 if nerrors+nsavederrors != 0 {
830 if err := writebench(benchfile); err != nil {
831 log.Fatalf("cannot write benchmark data: %v", err)
836 // numNonClosures returns the number of functions in list which are not closures.
837 func numNonClosures(list []*Node) int {
839 for _, n := range list {
840 if n.Func.Closure == nil {
847 func writebench(filename string) error {
848 f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
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+":")
859 n, err := f.Write(buf.Bytes())
871 importMap = map[string]string{}
872 packageFile map[string]string // nil means not in use
875 func addImportMap(s string) {
876 if strings.Count(s, "=") != 1 {
877 log.Fatal("-importmap argument must be of the form source=actual")
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")
884 importMap[source] = actual
887 func readImportCfg(file string) {
888 packageFile = map[string]string{}
889 data, err := ioutil.ReadFile(file)
891 log.Fatalf("-importcfg: %v", err)
894 for lineNum, line := range strings.Split(string(data), "\n") {
896 line = strings.TrimSpace(line)
897 if line == "" || strings.HasPrefix(line, "#") {
901 var verb, args string
902 if i := strings.Index(line, " "); i < 0 {
905 verb, args = line[:i], strings.TrimSpace(line[i+1:])
907 var before, after string
908 if i := strings.Index(args, "="); i >= 0 {
909 before, after = args[:i], args[i+1:]
913 log.Fatalf("%s:%d: unknown directive %q", file, lineNum, verb)
915 if before == "" || after == "" {
916 log.Fatalf(`%s:%d: invalid importmap: syntax is "importmap old=new"`, file, lineNum)
918 importMap[before] = after
920 if before == "" || after == "" {
921 log.Fatalf(`%s:%d: invalid packagefile: syntax is "packagefile path=filename"`, file, lineNum)
923 packageFile[before] = after
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
933 // readSymABIs reads a symabis file that specifies definitions and
934 // references of text symbols by ABI.
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)
945 log.Fatalf("-symabis: %v", err)
948 symabiDefs = make(map[string]obj.ABI)
949 symabiRefs = make(map[string]obj.ABI)
952 if myimportpath != "" {
953 // Symbols in this package may be written either as
954 // "".X or with the package's import path already in
956 localPrefix = objabi.PathToPrefix(myimportpath) + "."
959 for lineNum, line := range strings.Split(string(data), "\n") {
961 line = strings.TrimSpace(line)
962 if line == "" || strings.HasPrefix(line, "#") {
966 parts := strings.Fields(line)
971 log.Fatalf(`%s:%d: invalid symabi: syntax is "%s sym abi"`, file, lineNum, parts[0])
973 sym, abistr := parts[1], parts[2]
974 abi, valid := obj.ParseABI(abistr)
976 log.Fatalf(`%s:%d: invalid symabi: unknown abi "%s"`, file, lineNum, abistr)
979 // If the symbol is already prefixed with
980 // myimportpath, rewrite it to start with ""
981 // so it matches the compiler's internal
983 if localPrefix != "" && strings.HasPrefix(sym, localPrefix) {
984 sym = `"".` + sym[len(localPrefix):]
988 if parts[0] == "def" {
989 symabiDefs[sym] = abi
991 symabiRefs[sym] = abi
994 log.Fatalf(`%s:%d: invalid symabi type "%s"`, file, lineNum, parts[0])
1000 nsavederrors += nerrors
1004 func arsize(b *bufio.Reader, name string) int {
1005 var buf [ArhdrSize]byte
1006 if _, err := io.ReadFull(b, buf[:]); err != nil {
1009 aname := strings.Trim(string(buf[0:16]), " ")
1010 if !strings.HasPrefix(aname, name) {
1013 asize := strings.Trim(string(buf[48:58]), " ")
1014 i, _ := strconv.Atoi(asize)
1020 func addidir(dir string) {
1022 idirs = append(idirs, dir)
1026 func isDriveLetter(b byte) bool {
1027 return 'a' <= b && b <= 'z' || 'A' <= b && b <= 'Z'
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 == ".."
1038 func findpkg(name string) (file string, ok bool) {
1039 if islocalname(name) {
1044 if packageFile != nil {
1045 file, ok = packageFile[name]
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 {
1056 file = fmt.Sprintf("%s.o", name)
1057 if _, err := os.Stat(file); err == nil {
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)
1071 if packageFile != nil {
1072 file, ok = packageFile[name]
1076 for _, dir := range idirs {
1077 file = fmt.Sprintf("%s/%s.a", dir, name)
1078 if _, err := os.Stat(file); err == nil {
1081 file = fmt.Sprintf("%s/%s.o", dir, name)
1082 if _, err := os.Stat(file); err == nil {
1087 if objabi.GOROOT != "" {
1090 if flag_installsuffix != "" {
1092 suffix = flag_installsuffix
1093 } else if flag_race {
1096 } else if flag_msan {
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 {
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 {
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.
1123 typs := runtimeTypes()
1124 for _, d := range &runtimeDecls {
1125 sym := Runtimepkg.Lookup(d.name)
1129 importfunc(Runtimepkg, src.NoXPos, sym, typ)
1131 importvar(Runtimepkg, src.NoXPos, sym, typ)
1133 Fatalf("unhandled declaration tag %v", d.tag)
1141 // myheight tracks the local package's height based on packages
1145 func importfile(f *Val) *types.Pkg {
1146 path_, ok := f.U.(string)
1148 yyerror("import path must be a string")
1152 if len(path_) == 0 {
1153 yyerror("import path is empty")
1157 if isbadimport(path_, false) {
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\"")
1170 if myimportpath != "" && path_ == myimportpath {
1171 yyerror("import %q while compiling that package (import cycle)", path_)
1175 if mapped, ok := importMap[path_]; ok {
1179 if path_ == "unsafe" {
1180 imported_unsafe = true
1184 if islocalname(path_) {
1185 if path_[0] == '/' {
1186 yyerror("import path cannot be absolute path")
1190 prefix := Ctxt.Pathname
1191 if localimport != "" {
1192 prefix = localimport
1194 path_ = path.Join(prefix, path_)
1196 if isbadimport(path_, true) {
1201 file, found := findpkg(path_)
1203 yyerror("can't find import: %q", path_)
1207 importpkg := types.NewPkg(path_, "")
1208 if importpkg.Imported {
1212 importpkg.Imported = true
1214 imp, err := bio.Open(file)
1216 yyerror("can't open import: %q: %v", path_, err)
1221 // check object header
1222 p, err := imp.ReadString('\n')
1224 yyerror("import %s: reading input: %v", file, err)
1228 if p == "!<arch>\n" { // package archive
1229 // package export block should be first
1230 sz := arsize(imp.Reader, "__.PKGDEF")
1232 yyerror("import %s: not a package file", file)
1235 p, err = imp.ReadString('\n')
1237 yyerror("import %s: reading input: %v", file, err)
1242 if !strings.HasPrefix(p, "go object ") {
1243 yyerror("import %s: not a go object file: %s", file, p)
1246 q := fmt.Sprintf("%s %s %s %s\n", objabi.GOOS, objabi.GOARCH, objabi.Version, objabi.Expstring())
1248 yyerror("import %s: object is [%s] expected [%s]", file, p[10:], q)
1252 // process header lines
1254 p, err = imp.ReadString('\n')
1256 yyerror("import %s: reading input: %v", file, err)
1260 break // header ends with blank line
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
1271 c, err = imp.ReadByte()
1276 c, err = imp.ReadByte()
1277 if c == '$' || err != nil {
1283 // get character after $$
1285 c, _ = imp.ReadByte()
1288 var fingerprint goobj.FingerprintType
1291 yyerror("cannot import %s: old export format no longer supported (recompile library)", path_)
1295 if Debug_export != 0 {
1296 fmt.Printf("importing %s (%s)\n", path_, file)
1298 imp.ReadByte() // skip \n after $$B
1300 c, err = imp.ReadByte()
1302 yyerror("import %s: reading input: %v", file, err)
1306 // Indexed format is distinguished by an 'i' byte,
1307 // whereas previous export formats started with 'c', 'd', or 'v'.
1309 yyerror("import %s: unexpected package format byte: %v", file, c)
1312 fingerprint = iimport(importpkg, imp)
1315 yyerror("no import in %q", path_)
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)
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)
1328 if importpkg.Height >= myheight {
1329 myheight = importpkg.Height + 1
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.
1343 if i := strings.LastIndex(elem, "/"); i >= 0 {
1346 if name == "" || elem == name {
1347 yyerrorl(lineno, "imported and not used: %q", path)
1349 yyerrorl(lineno, "imported and not used: %q as %s", path, name)
1353 func mkpackage(pkgname string) {
1354 if localpkg.Name == "" {
1356 yyerror("invalid package name _")
1358 localpkg.Name = pkgname
1360 if pkgname != localpkg.Name {
1361 yyerror("package %s; expected %s", pkgname, localpkg.Name)
1366 func clearImports() {
1367 type importedPkg struct {
1372 var unused []importedPkg
1374 for _, s := range localpkg.Syms {
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})
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)
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)
1409 func IsAlias(sym *types.Sym) bool {
1410 return sym.Def != nil && asNode(sym.Def).Sym != sym
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.
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)
1430 return d == DebugFlags{}
1433 func concurrentBackendAllowed() bool {
1434 if !concurrentFlagOk() {
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 {
1445 // TODO: Test and delete this condition.
1446 if objabi.Fieldtrack_enabled != 0 {
1449 // TODO: fix races and enable the following flags
1450 if Ctxt.Flag_shared || Ctxt.Flag_dynlink || flag_race {
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
1465 type BoolFlag interface {
1468 type CountFlag interface {
1471 var cmd bytes.Buffer
1472 for _, name := range flags {
1473 f := flag.Lookup(name)
1477 getter := f.Value.(flag.Getter)
1478 if getter.String() == f.DefValue {
1479 // Flag has default value, so omit it.
1482 if bf, ok := f.Value.(BoolFlag); ok && bf.IsBoolFlag() {
1483 val, ok := getter.Get().(bool)
1485 fmt.Fprintf(&cmd, " -%s", f.Name)
1489 if cf, ok := f.Value.(CountFlag); ok && cf.IsCountFlag() {
1490 val, ok := getter.Get().(int)
1492 fmt.Fprintf(&cmd, " -%s", f.Name)
1496 fmt.Fprintf(&cmd, " -%s=%v", f.Name, getter.Get())
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:]
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)
1523 // flag_lang is the language version we are compiling for, set by the -lang flag.
1524 var flag_lang string
1526 // currentLang returns the current language version.
1527 func currentLang() string {
1528 return fmt.Sprintf("go1.%d", goversion.Version)
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]*)$`)
1535 // A lang is a language version broken into major and minor numbers.
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.
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 {
1549 // TODO(mdempsky): Set Pkg for local types earlier.
1552 if pkg != localpkg {
1553 // Assume imported packages passed type-checking.
1557 if langWant.major == 0 && langWant.minor == 0 {
1560 return langWant.major > major || (langWant.major == major && langWant.minor >= minor)
1563 // checkLang verifies that the -lang flag holds a valid value, and
1564 // exits if not. It initializes data used by langSupported.
1566 if flag_lang == "" {
1571 langWant, err = parseLang(flag_lang)
1573 log.Fatalf("invalid value %q for -lang: %v", flag_lang, err)
1576 if def := currentLang(); flag_lang != def {
1577 defVers, err := parseLang(def)
1579 log.Fatalf("internal error parsing default lang %q: %v", def, err)
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)
1587 // parseLang parses a -lang option into a langVer.
1588 func parseLang(s string) (lang, error) {
1589 matches := goVersionRE.FindStringSubmatch(s)
1591 return lang{}, fmt.Errorf(`should be something like "go1.12"`)
1593 major, err := strconv.Atoi(matches[1])
1597 minor, err := strconv.Atoi(matches[2])
1601 return lang{major: major, minor: minor}, nil