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