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