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