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