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