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