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