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