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