func addinitarray() (c *IMAGE_SECTION_HEADER) { // The size below was determined by the specification for array relocations, // and by observing what GCC writes here. If the initarray section grows to // contain more than one constructor entry, the size will need to be 8 * constructor_count. // However, the entire Go runtime is initialized from just one function, so it is unlikely // that this will need to grow in the future. var size int switch obj.Getgoarch() { default: fmt.Fprintf(os.Stderr, "link: unknown architecture for PE: %q\n", obj.Getgoarch()) os.Exit(2) case "386": size = 4 case "amd64": size = 8 } c = addpesection(".ctors", size, size) c.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ c.SizeOfRawData = uint32(size) Cseek(int64(c.PointerToRawData)) chksectoff(c, Cpos()) init_entry := Linklookup(Ctxt, INITENTRY, 0) addr := uint64(init_entry.Value) - init_entry.Sect.Vaddr switch obj.Getgoarch() { case "386": Lputl(uint32(addr)) case "amd64": Vputl(addr) } return c }
func main() { // disable timestamps for reproducible output log.SetFlags(0) log.SetPrefix("compile: ") switch obj.Getgoarch() { default: fmt.Fprintf(os.Stderr, "compile: unknown architecture %q\n", obj.Getgoarch()) os.Exit(2) case "386": x86.Main() case "amd64", "amd64p32": amd64.Main() case "arm": arm.Main() case "arm64": arm64.Main() case "mips64", "mips64le": mips64.Main() case "ppc64", "ppc64le": ppc64.Main() case "s390x": s390x.Main() } }
func main() { log.SetFlags(0) log.SetPrefix("asm: ") GOARCH := obj.Getgoarch() architecture := arch.Set(GOARCH) if architecture == nil { log.Fatalf("unrecognized architecture %s", GOARCH) } flags.Parse() ctxt := obj.Linknew(architecture.LinkArch) if *flags.PrintOut { ctxt.Debugasm = 1 } ctxt.LineHist.TrimPathPrefix = *flags.TrimPath ctxt.Flag_dynlink = *flags.Dynlink ctxt.Flag_shared = *flags.Shared || *flags.Dynlink ctxt.Bso = bufio.NewWriter(os.Stdout) defer ctxt.Bso.Flush() // Create object file, write header. out, err := os.Create(*flags.OutputFile) if err != nil { log.Fatal(err) } defer bio.MustClose(out) buf := bufio.NewWriter(bio.MustWriter(out)) fmt.Fprintf(buf, "go object %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion()) fmt.Fprintf(buf, "!\n") lexer := lex.NewLexer(flag.Arg(0), ctxt) parser := asm.NewParser(ctxt, architecture, lexer) diag := false ctxt.DiagFunc = func(format string, args ...interface{}) { diag = true log.Printf(format, args...) } pList := obj.Linknewplist(ctxt) var ok bool pList.Firstpc, ok = parser.Parse() if ok { // reports errors to parser.Errorf obj.Writeobjdirect(ctxt, buf) } if !ok || diag { log.Printf("assembly of %s failed", flag.Arg(0)) os.Remove(*flags.OutputFile) os.Exit(1) } buf.Flush() }
func linkarchinit() { ld.Thestring = obj.Getgoarch() ld.Thelinkarch = &ld.Linkarm64 ld.Thearch.Thechar = thechar ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize ld.Thearch.Regsize = ld.Thelinkarch.Regsize ld.Thearch.Funcalign = FuncAlign ld.Thearch.Maxalign = MaxAlign ld.Thearch.Minlc = MINLC ld.Thearch.Dwarfregsp = DWARFREGSP ld.Thearch.Dwarfreglr = DWARFREGLR ld.Thearch.Adddynrel = adddynrel ld.Thearch.Archinit = archinit ld.Thearch.Archreloc = archreloc ld.Thearch.Archrelocvariant = archrelocvariant ld.Thearch.Asmb = asmb ld.Thearch.Elfreloc1 = elfreloc1 ld.Thearch.Elfsetupplt = elfsetupplt ld.Thearch.Gentext = gentext ld.Thearch.Machoreloc1 = machoreloc1 ld.Thearch.Lput = ld.Lputl ld.Thearch.Wput = ld.Wputl ld.Thearch.Vput = ld.Vputl ld.Thearch.Linuxdynld = "/lib/ld-linux-aarch64.so.1" ld.Thearch.Freebsddynld = "XXX" ld.Thearch.Openbsddynld = "XXX" ld.Thearch.Netbsddynld = "XXX" ld.Thearch.Dragonflydynld = "XXX" ld.Thearch.Solarisdynld = "XXX" }
func assemble(file string) int { if outfile == "" { outfile = strings.TrimSuffix(filepath.Base(file), ".s") + "." + string(Thechar) } of, err := os.Create(outfile) if err != nil { Yyerror("%ca: cannot create %s", Thechar, outfile) errorexit() } obuf = *obj.Binitw(of) fmt.Fprintf(&obuf, "go object %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion()) fmt.Fprintf(&obuf, "!\n") var i int for Pass = 1; Pass <= 2; Pass++ { pinit(file) for i = 0; i < len(Dlist); i++ { dodefine(Dlist[i]) } Yyparse() Cclean() if nerrors != 0 { return nerrors } } obj.Writeobjdirect(Ctxt, &obuf) obuf.Flush() return 0 }
func Main() { gc.Thearch.LinkArch = &ppc64.Linkppc64 if obj.Getgoarch() == "ppc64le" { gc.Thearch.LinkArch = &ppc64.Linkppc64le } gc.Thearch.REGSP = ppc64.REGSP gc.Thearch.REGCTXT = ppc64.REGCTXT gc.Thearch.REGCALLX = ppc64.REG_R3 gc.Thearch.REGCALLX2 = ppc64.REG_R4 gc.Thearch.REGRETURN = ppc64.REG_R3 gc.Thearch.REGMIN = ppc64.REG_R0 gc.Thearch.REGMAX = ppc64.REG_R31 gc.Thearch.FREGMIN = ppc64.REG_F0 gc.Thearch.FREGMAX = ppc64.REG_F31 gc.Thearch.MAXWIDTH = 1 << 50 gc.Thearch.ReservedRegs = resvd gc.Thearch.Betypeinit = betypeinit gc.Thearch.Cgen_hmul = cgen_hmul gc.Thearch.Cgen_shift = cgen_shift gc.Thearch.Clearfat = clearfat gc.Thearch.Defframe = defframe gc.Thearch.Dodiv = dodiv gc.Thearch.Excise = excise gc.Thearch.Expandchecks = expandchecks gc.Thearch.Getg = getg gc.Thearch.Gins = gins gc.Thearch.Ginscmp = ginscmp gc.Thearch.Ginscon = ginscon gc.Thearch.Ginsnop = ginsnop gc.Thearch.Gmove = gmove gc.Thearch.Peep = peep gc.Thearch.Proginfo = proginfo gc.Thearch.Regtyp = regtyp gc.Thearch.Sameaddr = sameaddr gc.Thearch.Smallindir = smallindir gc.Thearch.Stackaddr = stackaddr gc.Thearch.Blockcopy = blockcopy gc.Thearch.Sudoaddable = sudoaddable gc.Thearch.Sudoclean = sudoclean gc.Thearch.Excludedregs = excludedregs gc.Thearch.RtoB = RtoB gc.Thearch.FtoB = RtoB gc.Thearch.BtoR = BtoR gc.Thearch.BtoF = BtoF gc.Thearch.Optoas = optoas gc.Thearch.Doregbits = doregbits gc.Thearch.Regnames = regnames gc.Thearch.SSARegToReg = ssaRegToReg gc.Thearch.SSAMarkMoves = ssaMarkMoves gc.Thearch.SSAGenValue = ssaGenValue gc.Thearch.SSAGenBlock = ssaGenBlock initvariants() initproginfo() gc.Main() gc.Exit(0) }
func (mode *BuildMode) Set(s string) error { goos := obj.Getgoos() goarch := obj.Getgoarch() badmode := func() error { return fmt.Errorf("buildmode %s not supported on %s/%s", s, goos, goarch) } switch s { default: return fmt.Errorf("invalid buildmode: %q", s) case "exe": *mode = BuildmodeExe case "c-archive": switch goos { case "darwin", "linux": default: return badmode() } *mode = BuildmodeCArchive case "c-shared": if goarch != "amd64" && goarch != "arm" { return badmode() } *mode = BuildmodeCShared case "shared": if goos != "linux" || goarch != "amd64" { return badmode() } *mode = BuildmodeShared } return nil }
func main() { log.SetFlags(0) log.SetPrefix("asm: ") GOARCH := obj.Getgoarch() architecture := arch.Set(GOARCH) if architecture == nil { log.Fatalf("asm: unrecognized architecture %s", GOARCH) } flags.Parse(architecture.Thechar) // Create object file, write header. fd, err := os.Create(*flags.OutputFile) if err != nil { log.Fatal(err) } ctxt := obj.Linknew(architecture.LinkArch) if *flags.PrintOut { ctxt.Debugasm = 1 } ctxt.LineHist.TrimPathPrefix = *flags.TrimPath ctxt.Flag_dynlink = *flags.Dynlink if *flags.Shared || *flags.Dynlink { ctxt.Flag_shared = 1 } ctxt.Bso = obj.Binitw(os.Stdout) defer ctxt.Bso.Flush() ctxt.Diag = log.Fatalf output := obj.Binitw(fd) fmt.Fprintf(output, "go object %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion()) fmt.Fprintf(output, "!\n") lexer := lex.NewLexer(flag.Arg(0), ctxt) parser := asm.NewParser(ctxt, architecture, lexer) pList := obj.Linknewplist(ctxt) var ok bool pList.Firstpc, ok = parser.Parse() if !ok { log.Printf("asm: assembly of %s failed", flag.Arg(0)) os.Remove(*flags.OutputFile) os.Exit(1) } obj.Writeobjdirect(ctxt, output) output.Flush() }
func Main() { gc.Thearch.LinkArch = &x86.Linkamd64 if obj.Getgoarch() == "amd64p32" { gc.Thearch.LinkArch = &x86.Linkamd64p32 } gc.Thearch.REGSP = x86.REGSP gc.Thearch.REGCTXT = x86.REGCTXT gc.Thearch.REGCALLX = x86.REG_BX gc.Thearch.REGCALLX2 = x86.REG_AX gc.Thearch.REGRETURN = x86.REG_AX gc.Thearch.REGMIN = x86.REG_AX gc.Thearch.REGMAX = x86.REG_R15 gc.Thearch.FREGMIN = x86.REG_X0 gc.Thearch.FREGMAX = x86.REG_X15 gc.Thearch.MAXWIDTH = 1 << 50 gc.Thearch.AddIndex = addindex gc.Thearch.Betypeinit = betypeinit gc.Thearch.Cgen_bmul = cgen_bmul gc.Thearch.Cgen_hmul = cgen_hmul gc.Thearch.Cgen_shift = cgen_shift gc.Thearch.Clearfat = clearfat gc.Thearch.Defframe = defframe gc.Thearch.Dodiv = dodiv gc.Thearch.Excise = excise gc.Thearch.Expandchecks = expandchecks gc.Thearch.Getg = getg gc.Thearch.Gins = gins gc.Thearch.Ginsboolval = ginsboolval gc.Thearch.Ginscmp = ginscmp gc.Thearch.Ginscon = ginscon gc.Thearch.Ginsnop = ginsnop gc.Thearch.Gmove = gmove gc.Thearch.Peep = peep gc.Thearch.Proginfo = proginfo gc.Thearch.Regtyp = regtyp gc.Thearch.Sameaddr = sameaddr gc.Thearch.Smallindir = smallindir gc.Thearch.Stackaddr = stackaddr gc.Thearch.Blockcopy = blockcopy gc.Thearch.Sudoaddable = sudoaddable gc.Thearch.Sudoclean = sudoclean gc.Thearch.Excludedregs = excludedregs gc.Thearch.RtoB = RtoB gc.Thearch.FtoB = FtoB gc.Thearch.BtoR = BtoR gc.Thearch.BtoF = BtoF gc.Thearch.Optoas = optoas gc.Thearch.Doregbits = doregbits gc.Thearch.Regnames = regnames gc.Thearch.SSARegToReg = ssaRegToReg gc.Thearch.SSAMarkMoves = ssaMarkMoves gc.Thearch.SSAGenValue = ssaGenValue gc.Thearch.SSAGenBlock = ssaGenBlock gc.Main() gc.Exit(0) }
func main() { switch obj.Getgoarch() { default: fmt.Fprintf(os.Stderr, "compile: unknown architecture %q\n", obj.Getgoarch()) os.Exit(2) case "386": x86.Main() case "amd64", "amd64p32": amd64.Main() case "arm": arm.Main() case "arm64": arm64.Main() case "ppc64", "ppc64le": ppc64.Main() } }
func linkarchinit() { if obj.Getgoarch() == "amd64p32" { thelinkarch = &x86.Linkamd64p32 gc.Thearch.Thelinkarch = thelinkarch thestring = "amd64p32" gc.Thearch.Thestring = "amd64p32" } }
func mywhatsys() { goroot = obj.Getgoroot() goos = obj.Getgoos() goarch = obj.Getgoarch() if !strings.HasPrefix(goarch, Thestring) { log.Fatalf("cannot use %cc with GOARCH=%s", Thearch.Thechar, goarch) } }
func linkarchinit() { thestring = obj.Getgoarch() gc.Thearch.Thestring = thestring if thestring == "ppc64le" { thelinkarch = &ppc64.Linkppc64le } else { thelinkarch = &ppc64.Linkppc64 } gc.Thearch.Thelinkarch = thelinkarch }
func linkarchinit() { thestring = obj.Getgoarch() gc.Thearch.Thestring = thestring if thestring == "mips64le" { thelinkarch = &mips.Linkmips64le } else { thelinkarch = &mips.Linkmips64 } gc.Thearch.Thelinkarch = thelinkarch }
func Main() { gc.Thearch.Thechar = '0' gc.Thearch.Thestring = "mips64" gc.Thearch.Thelinkarch = &mips.Linkmips64 if obj.Getgoarch() == "mips64le" { gc.Thearch.Thestring = "mips64le" gc.Thearch.Thelinkarch = &mips.Linkmips64le } gc.Thearch.REGSP = mips.REGSP gc.Thearch.REGCTXT = mips.REGCTXT gc.Thearch.REGCALLX = mips.REG_R1 gc.Thearch.REGCALLX2 = mips.REG_R2 gc.Thearch.REGRETURN = mips.REGRET gc.Thearch.REGMIN = mips.REG_R0 gc.Thearch.REGMAX = mips.REG_R31 gc.Thearch.FREGMIN = mips.REG_F0 gc.Thearch.FREGMAX = mips.REG_F31 gc.Thearch.MAXWIDTH = 1 << 50 gc.Thearch.ReservedRegs = resvd gc.Thearch.Betypeinit = betypeinit gc.Thearch.Cgen_hmul = cgen_hmul gc.Thearch.Cgen_shift = cgen_shift gc.Thearch.Clearfat = clearfat gc.Thearch.Defframe = defframe gc.Thearch.Dodiv = dodiv gc.Thearch.Excise = excise gc.Thearch.Expandchecks = expandchecks gc.Thearch.Getg = getg gc.Thearch.Gins = gins gc.Thearch.Ginscmp = ginscmp gc.Thearch.Ginscon = ginscon gc.Thearch.Ginsnop = ginsnop gc.Thearch.Gmove = gmove gc.Thearch.Peep = peep gc.Thearch.Proginfo = proginfo gc.Thearch.Regtyp = regtyp gc.Thearch.Sameaddr = sameaddr gc.Thearch.Smallindir = smallindir gc.Thearch.Stackaddr = stackaddr gc.Thearch.Blockcopy = blockcopy gc.Thearch.Sudoaddable = sudoaddable gc.Thearch.Sudoclean = sudoclean gc.Thearch.Excludedregs = excludedregs gc.Thearch.RtoB = RtoB gc.Thearch.FtoB = RtoB gc.Thearch.BtoR = BtoR gc.Thearch.BtoF = BtoF gc.Thearch.Optoas = optoas gc.Thearch.Doregbits = doregbits gc.Thearch.Regnames = regnames gc.Main() gc.Exit(0) }
func (mode *BuildMode) Set(s string) error { goos := obj.Getgoos() goarch := obj.Getgoarch() badmode := func() error { return fmt.Errorf("buildmode %s not supported on %s/%s", s, goos, goarch) } switch s { default: return fmt.Errorf("invalid buildmode: %q", s) case "exe": *mode = BuildmodeExe case "pie": switch goos { case "android", "linux": default: return badmode() } *mode = BuildmodePIE case "c-archive": switch goos { case "darwin", "linux": case "windows": switch goarch { case "amd64", "386": default: return badmode() } default: return badmode() } *mode = BuildmodeCArchive case "c-shared": switch goarch { case "386", "amd64", "arm", "arm64": default: return badmode() } *mode = BuildmodeCShared case "shared": switch goos { case "linux": switch goarch { case "386", "amd64", "arm", "arm64", "ppc64le", "s390x": default: return badmode() } default: return badmode() } *mode = BuildmodeShared } return nil }
func betypeinit() { if obj.Getgoarch() == "amd64p32" { addptr = x86.AADDL movptr = x86.AMOVL leaptr = x86.ALEAL cmpptr = x86.ACMPL } if gc.Ctxt.Flag_dynlink { gc.Thearch.ReservedRegs = append(gc.Thearch.ReservedRegs, x86.REG_R15) } }
func Main() { // Allow GOARCH=Thestring or GOARCH=Thestringsuffix, // but not other values. p := obj.Getgoarch() if !strings.HasPrefix(p, Thestring) { log.Fatalf("cannot use %cc with GOARCH=%s", Thechar, p) } if p != Thestring { Thelinkarch = Arches[p] if Thelinkarch == nil { log.Fatalf("unknown arch %s", p) } } Ctxt = obj.Linknew(Thelinkarch) Ctxt.Diag = Yyerror Ctxt.Bso = &bstdout Ctxt.Enforce_data_order = 1 bstdout = *obj.Binitw(os.Stdout) debug = [256]int{} cinit() outfile = "" setinclude(".") flag.Var(flagFn(dodef), "D", "name[=value]: add #define") flag.Var(flagFn(setinclude), "I", "dir: add dir to include path") flag.Var((*count)(&debug['S']), "S", "print assembly and machine code") flag.Var((*count)(&debug['m']), "m", "debug preprocessor macros") flag.StringVar(&outfile, "o", "", "file: set output file") flag.StringVar(&Ctxt.LineHist.TrimPathPrefix, "trimpath", "", "prefix: remove prefix from recorded source file paths") flag.Parse() Ctxt.Debugasm = int32(debug['S']) if flag.NArg() < 1 { usage() } if flag.NArg() > 1 { fmt.Printf("can't assemble multiple files\n") errorexit() } if assemble(flag.Arg(0)) != 0 { errorexit() } bstdout.Flush() if nerrors > 0 { errorexit() } }
func linkarchinit() { ld.Thestring = obj.Getgoarch() if ld.Thestring == "ppc64le" { ld.Thelinkarch = &ld.Linkppc64le } else { ld.Thelinkarch = &ld.Linkppc64 } ld.Thearch.Thechar = thechar ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize ld.Thearch.Regsize = ld.Thelinkarch.Regsize ld.Thearch.Funcalign = FuncAlign ld.Thearch.Maxalign = MaxAlign ld.Thearch.Minlc = MINLC ld.Thearch.Dwarfregsp = DWARFREGSP ld.Thearch.Dwarfreglr = DWARFREGLR ld.Thearch.Adddynrel = adddynrel ld.Thearch.Archinit = archinit ld.Thearch.Archreloc = archreloc ld.Thearch.Archrelocvariant = archrelocvariant ld.Thearch.Asmb = asmb ld.Thearch.Elfreloc1 = elfreloc1 ld.Thearch.Elfsetupplt = elfsetupplt ld.Thearch.Gentext = gentext ld.Thearch.Machoreloc1 = machoreloc1 if ld.Thelinkarch == &ld.Linkppc64le { ld.Thearch.Lput = ld.Lputl ld.Thearch.Wput = ld.Wputl ld.Thearch.Vput = ld.Vputl ld.Thearch.Append16 = ld.Append16l ld.Thearch.Append32 = ld.Append32l ld.Thearch.Append64 = ld.Append64l } else { ld.Thearch.Lput = ld.Lputb ld.Thearch.Wput = ld.Wputb ld.Thearch.Vput = ld.Vputb ld.Thearch.Append16 = ld.Append16b ld.Thearch.Append32 = ld.Append32b ld.Thearch.Append64 = ld.Append64b } // TODO(austin): ABI v1 uses /usr/lib/ld.so.1 ld.Thearch.Linuxdynld = "/lib64/ld64.so.1" ld.Thearch.Freebsddynld = "XXX" ld.Thearch.Openbsddynld = "XXX" ld.Thearch.Netbsddynld = "XXX" ld.Thearch.Dragonflydynld = "XXX" ld.Thearch.Solarisdynld = "XXX" }
func betypeinit() { if obj.Getgoarch() == "amd64p32" { addptr = x86.AADDL movptr = x86.AMOVL leaptr = x86.ALEAL cmpptr = x86.ACMPL } if gc.Ctxt.Flag_dynlink || obj.Getgoos() == "nacl" { resvd = append(resvd, x86.REG_R15) } if gc.Ctxt.Framepointer_enabled || obj.Getgoos() == "nacl" { resvd = append(resvd, x86.REG_BP) } gc.Thearch.ReservedRegs = resvd }
func linkarchinit() { if obj.Getgoarch() == "ppc64le" { ld.SysArch = sys.ArchPPC64LE } else { ld.SysArch = sys.ArchPPC64 } ld.Thearch.Funcalign = FuncAlign ld.Thearch.Maxalign = MaxAlign ld.Thearch.Minalign = MinAlign ld.Thearch.Dwarfregsp = DWARFREGSP ld.Thearch.Dwarfreglr = DWARFREGLR ld.Thearch.Adddynrel = adddynrel ld.Thearch.Archinit = archinit ld.Thearch.Archreloc = archreloc ld.Thearch.Archrelocvariant = archrelocvariant ld.Thearch.Asmb = asmb ld.Thearch.Elfreloc1 = elfreloc1 ld.Thearch.Elfsetupplt = elfsetupplt ld.Thearch.Gentext = gentext ld.Thearch.Machoreloc1 = machoreloc1 if ld.SysArch == sys.ArchPPC64LE { ld.Thearch.Lput = ld.Lputl ld.Thearch.Wput = ld.Wputl ld.Thearch.Vput = ld.Vputl ld.Thearch.Append16 = ld.Append16l ld.Thearch.Append32 = ld.Append32l ld.Thearch.Append64 = ld.Append64l } else { ld.Thearch.Lput = ld.Lputb ld.Thearch.Wput = ld.Wputb ld.Thearch.Vput = ld.Vputb ld.Thearch.Append16 = ld.Append16b ld.Thearch.Append32 = ld.Append32b ld.Thearch.Append64 = ld.Append64b } // TODO(austin): ABI v1 uses /usr/lib/ld.so.1 ld.Thearch.Linuxdynld = "/lib64/ld64.so.1" ld.Thearch.Freebsddynld = "XXX" ld.Thearch.Openbsddynld = "XXX" ld.Thearch.Netbsddynld = "XXX" ld.Thearch.Dragonflydynld = "XXX" ld.Thearch.Solarisdynld = "XXX" }
func betypeinit() { gc.Widthptr = 8 gc.Widthint = 8 gc.Widthreg = 8 if obj.Getgoarch() == "amd64p32" { gc.Widthptr = 4 gc.Widthint = 4 addptr = x86.AADDL movptr = x86.AMOVL leaptr = x86.ALEAL cmpptr = x86.ACMPL typedefs[0].Sameas = gc.TINT32 typedefs[1].Sameas = gc.TUINT32 typedefs[2].Sameas = gc.TUINT32 } }
func linkarchinit() { ld.Thestring = "amd64" ld.Thelinkarch = &ld.Linkamd64 if obj.Getgoarch() == "amd64p32" { ld.Thelinkarch = &ld.Linkamd64p32 } ld.Thearch.Thechar = thechar ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize ld.Thearch.Regsize = ld.Thelinkarch.Regsize ld.Thearch.Funcalign = FuncAlign ld.Thearch.Maxalign = MaxAlign ld.Thearch.Minalign = MinAlign ld.Thearch.Minlc = MINLC ld.Thearch.Dwarfregsp = DWARFREGSP ld.Thearch.Dwarfreglr = DWARFREGLR ld.Thearch.Adddynrel = adddynrel ld.Thearch.Archinit = archinit ld.Thearch.Archreloc = archreloc ld.Thearch.Archrelocvariant = archrelocvariant ld.Thearch.Asmb = asmb ld.Thearch.Elfreloc1 = elfreloc1 ld.Thearch.Elfsetupplt = elfsetupplt ld.Thearch.Gentext = gentext ld.Thearch.Machoreloc1 = machoreloc1 ld.Thearch.PEreloc1 = pereloc1 ld.Thearch.Lput = ld.Lputl ld.Thearch.Wput = ld.Wputl ld.Thearch.Vput = ld.Vputl ld.Thearch.Append16 = ld.Append16l ld.Thearch.Append32 = ld.Append32l ld.Thearch.Append64 = ld.Append64l ld.Thearch.Linuxdynld = "/lib64/ld-linux-x86-64.so.2" ld.Thearch.Freebsddynld = "/libexec/ld-elf.so.1" ld.Thearch.Openbsddynld = "/usr/libexec/ld.so" ld.Thearch.Netbsddynld = "/libexec/ld.elf_so" ld.Thearch.Dragonflydynld = "/usr/libexec/ld-elf.so.2" ld.Thearch.Solarisdynld = "/lib/amd64/ld.so.1" }
func betypeinit() { gc.Widthptr = 8 gc.Widthint = 8 gc.Widthreg = 8 if obj.Getgoarch() == "amd64p32" { gc.Widthptr = 4 gc.Widthint = 4 addptr = x86.AADDL movptr = x86.AMOVL leaptr = x86.ALEAL cmpptr = x86.ACMPL typedefs[0].Sameas = gc.TINT32 typedefs[1].Sameas = gc.TUINT32 typedefs[2].Sameas = gc.TUINT32 } if gc.Ctxt.Flag_dynlink { gc.Thearch.ReservedRegs = append(gc.Thearch.ReservedRegs, x86.REG_R15) } }
func linknew(arch *LinkArch) *Link { ctxt := &Link{ Hash: []map[string]*LSym{ // preallocate about 2mb for hash of // non static symbols make(map[string]*LSym, 100000), }, Allsym: make([]*LSym, 0, 100000), Arch: arch, Goroot: obj.Getgoroot(), } p := obj.Getgoarch() if p != arch.Name { log.Fatalf("invalid goarch %s (want %s)", p, arch.Name) } ctxt.Headtype = headtype(obj.Getgoos()) if ctxt.Headtype < 0 { log.Fatalf("unknown goos %s", obj.Getgoos()) } // Record thread-local storage offset. // TODO(rsc): Move tlsoffset back into the linker. switch ctxt.Headtype { default: log.Fatalf("unknown thread-local storage offset for %s", Headstr(ctxt.Headtype)) case obj.Hplan9, obj.Hwindows: break /* * ELF uses TLS offset negative from FS. * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS). * Known to low-level assembly in package runtime and runtime/cgo. */ case obj.Hlinux, obj.Hfreebsd, obj.Hnetbsd, obj.Hopenbsd, obj.Hdragonfly, obj.Hsolaris: if obj.Getgoos() == "android" { switch ctxt.Arch.Thechar { case '6': // Android/amd64 constant - offset from 0(FS) to our TLS slot. // Explained in src/runtime/cgo/gcc_android_*.c ctxt.Tlsoffset = 0x1d0 case '8': // Android/386 constant - offset from 0(GS) to our TLS slot. ctxt.Tlsoffset = 0xf8 default: ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize } } else { ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize } case obj.Hnacl: switch ctxt.Arch.Thechar { default: log.Fatalf("unknown thread-local storage offset for nacl/%s", ctxt.Arch.Name) case '5': ctxt.Tlsoffset = 0 case '6': ctxt.Tlsoffset = 0 case '8': ctxt.Tlsoffset = -8 } /* * OS X system constants - offset from 0(GS) to our TLS. * Explained in src/runtime/cgo/gcc_darwin_*.c. */ case obj.Hdarwin: switch ctxt.Arch.Thechar { default: log.Fatalf("unknown thread-local storage offset for darwin/%s", ctxt.Arch.Name) case '5': ctxt.Tlsoffset = 0 // dummy value, not needed case '6': ctxt.Tlsoffset = 0x8a0 case '7': ctxt.Tlsoffset = 0 // dummy value, not needed case '8': ctxt.Tlsoffset = 0x468 } } // On arm, record goarm. if ctxt.Arch.Thechar == '5' { ctxt.Goarm = obj.Getgoarm() } return ctxt }
func dumpobj() { var err error bout, err = obj.Bopenw(outfile) if err != nil { Flusherrors() fmt.Printf("can't create %s: %v\n", outfile, err) errorexit() } startobj := int64(0) var arhdr [ArhdrSize]byte if writearchive != 0 { obj.Bwritestring(bout, "!<arch>\n") arhdr = [ArhdrSize]byte{} bout.Write(arhdr[:]) startobj = obj.Boffset(bout) } fmt.Fprintf(bout, "go object %s %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring()) dumpexport() if writearchive != 0 { bout.Flush() size := obj.Boffset(bout) - startobj if size&1 != 0 { obj.Bputc(bout, 0) } obj.Bseek(bout, startobj-ArhdrSize, 0) formathdr(arhdr[:], "__.PKGDEF", size) bout.Write(arhdr[:]) bout.Flush() obj.Bseek(bout, startobj+size+(size&1), 0) arhdr = [ArhdrSize]byte{} bout.Write(arhdr[:]) startobj = obj.Boffset(bout) fmt.Fprintf(bout, "go object %s %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring()) } if pragcgobuf != "" { if writearchive != 0 { // write empty export section; must be before cgo section fmt.Fprintf(bout, "\n$$\n\n$$\n\n") } fmt.Fprintf(bout, "\n$$ // cgo\n") fmt.Fprintf(bout, "%s\n$$\n\n", pragcgobuf) } fmt.Fprintf(bout, "\n!\n") externs := len(externdcl) dumpglobls() dumptypestructs() // Dump extra globals. tmp := externdcl if externdcl != nil { externdcl = externdcl[externs:] } dumpglobls() externdcl = tmp dumpdata() obj.Writeobjdirect(Ctxt, bout) if writearchive != 0 { bout.Flush() size := obj.Boffset(bout) - startobj if size&1 != 0 { obj.Bputc(bout, 0) } obj.Bseek(bout, startobj-ArhdrSize, 0) formathdr(arhdr[:], "_go_.o", size) bout.Write(arhdr[:]) } obj.Bterm(bout) }
func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, whence int) { eof := obj.Boffset(f) + length start := obj.Boffset(f) c1 := obj.Bgetc(f) c2 := obj.Bgetc(f) c3 := obj.Bgetc(f) c4 := obj.Bgetc(f) obj.Bseek(f, start, 0) magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4) if magic == 0x7f454c46 { // \x7F E L F ldhostobj(ldelf, f, pkg, length, pn, file) return } if magic&^1 == 0xfeedface || magic&^0x01000000 == 0xcefaedfe { ldhostobj(ldmacho, f, pkg, length, pn, file) return } if c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86 { ldhostobj(ldpe, f, pkg, length, pn, file) return } /* check the header */ line := obj.Brdline(f, '\n') if line == "" { if obj.Blinelen(f) > 0 { Diag("%s: not an object file", pn) return } Diag("truncated object file: %s", pn) return } if !strings.HasPrefix(line, "go object ") { if strings.HasSuffix(pn, ".go") { Exitf("%cl: input %s is not .%c file (use %cg to compile .go files)", Thearch.Thechar, pn, Thearch.Thechar, Thearch.Thechar) } if line == Thestring { // old header format: just $GOOS Diag("%s: stale object file", pn) return } Diag("%s: not an object file", pn) return } // First, check that the basic goos, goarch, and version match. t := fmt.Sprintf("%s %s %s ", goos, obj.Getgoarch(), obj.Getgoversion()) line = strings.TrimRight(line, "\n") if !strings.HasPrefix(line[10:]+" ", t) && Debug['f'] == 0 { Diag("%s: object is [%s] expected [%s]", pn, line[10:], t) return } // Second, check that longer lines match each other exactly, // so that the Go compiler and write additional information // that must be the same from run to run. if len(line) >= len(t)+10 { if theline == "" { theline = line[10:] } else if theline != line[10:] { Diag("%s: object is [%s] expected [%s]", pn, line[10:], theline) return } } /* skip over exports and other info -- ends with \n!\n */ import0 := obj.Boffset(f) c1 = '\n' // the last line ended in \n c2 = obj.Bgetc(f) c3 = obj.Bgetc(f) for c1 != '\n' || c2 != '!' || c3 != '\n' { c1 = c2 c2 = c3 c3 = obj.Bgetc(f) if c3 == obj.Beof { Diag("truncated object file: %s", pn) return } } import1 := obj.Boffset(f) obj.Bseek(f, import0, 0) ldpkg(f, pkg, import1-import0-2, pn, whence) // -2 for !\n obj.Bseek(f, import1, 0) ldobjfile(Ctxt, f, pkg, eof-obj.Boffset(f), pn) }
func linknew(arch *LinkArch) *Link { ctxt := new(Link) ctxt.Hash = make(map[symVer]*LSym) ctxt.Arch = arch ctxt.Version = obj.HistVersion ctxt.Goroot = obj.Getgoroot() p := obj.Getgoarch() if p != arch.Name { log.Fatalf("invalid goarch %s (want %s)", p, arch.Name) } var buf string buf, _ = os.Getwd() if buf == "" { buf = "/???" } buf = filepath.ToSlash(buf) ctxt.Headtype = headtype(obj.Getgoos()) if ctxt.Headtype < 0 { log.Fatalf("unknown goos %s", obj.Getgoos()) } // Record thread-local storage offset. // TODO(rsc): Move tlsoffset back into the linker. switch ctxt.Headtype { default: log.Fatalf("unknown thread-local storage offset for %s", Headstr(ctxt.Headtype)) case obj.Hplan9, obj.Hwindows: break /* * ELF uses TLS offset negative from FS. * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS). * Known to low-level assembly in package runtime and runtime/cgo. */ case obj.Hlinux, obj.Hfreebsd, obj.Hnetbsd, obj.Hopenbsd, obj.Hdragonfly, obj.Hsolaris: if obj.Getgoos() == "android" && ctxt.Arch.Thechar == '6' { // Android/x86 constant - offset from 0(FS) to our // TLS slot. Explained in src/runtime/cgo/gcc_android_*.c ctxt.Tlsoffset = 0x1d0 } else { ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize } case obj.Hnacl: switch ctxt.Arch.Thechar { default: log.Fatalf("unknown thread-local storage offset for nacl/%s", ctxt.Arch.Name) case '5': ctxt.Tlsoffset = 0 case '6': ctxt.Tlsoffset = 0 case '8': ctxt.Tlsoffset = -8 } /* * OS X system constants - offset from 0(GS) to our TLS. * Explained in src/runtime/cgo/gcc_darwin_*.c. */ case obj.Hdarwin: switch ctxt.Arch.Thechar { default: log.Fatalf("unknown thread-local storage offset for darwin/%s", ctxt.Arch.Name) case '5': ctxt.Tlsoffset = 0 // dummy value, not needed case '6': ctxt.Tlsoffset = 0x8a0 case '7': ctxt.Tlsoffset = 0 // dummy value, not needed case '8': ctxt.Tlsoffset = 0x468 } } // On arm, record goarm. if ctxt.Arch.Thechar == '5' { ctxt.Goarm = obj.Getgoarm() } return ctxt }
func Main() { defer hidePanic() // Allow GOARCH=thearch.thestring or GOARCH=thearch.thestringsuffix, // but not other values. p := obj.Getgoarch() if !strings.HasPrefix(p, Thearch.Thestring) { log.Fatalf("cannot use %cg with GOARCH=%s", Thearch.Thechar, p) } goarch = p Thearch.Linkarchinit() Ctxt = obj.Linknew(Thearch.Thelinkarch) Ctxt.Diag = Yyerror Ctxt.Bso = &bstdout bstdout = *obj.Binitw(os.Stdout) localpkg = mkpkg("") localpkg.Prefix = "\"\"" // pseudo-package, for scoping builtinpkg = mkpkg("go.builtin") builtinpkg.Prefix = "go.builtin" // not go%2ebuiltin // pseudo-package, accessed by import "unsafe" unsafepkg = mkpkg("unsafe") unsafepkg.Name = "unsafe" // real package, referred to by generated runtime calls Runtimepkg = mkpkg("runtime") Runtimepkg.Name = "runtime" // pseudo-packages used in symbol tables gostringpkg = mkpkg("go.string") gostringpkg.Name = "go.string" gostringpkg.Prefix = "go.string" // not go%2estring itabpkg = mkpkg("go.itab") itabpkg.Name = "go.itab" itabpkg.Prefix = "go.itab" // not go%2eitab weaktypepkg = mkpkg("go.weak.type") weaktypepkg.Name = "go.weak.type" weaktypepkg.Prefix = "go.weak.type" // not go%2eweak%2etype typelinkpkg = mkpkg("go.typelink") typelinkpkg.Name = "go.typelink" typelinkpkg.Prefix = "go.typelink" // not go%2etypelink trackpkg = mkpkg("go.track") trackpkg.Name = "go.track" trackpkg.Prefix = "go.track" // not go%2etrack typepkg = mkpkg("type") typepkg.Name = "type" goroot = obj.Getgoroot() goos = obj.Getgoos() Nacl = goos == "nacl" if Nacl { flag_largemodel = 1 } outfile = "" obj.Flagcount("+", "compiling runtime", &compiling_runtime) obj.Flagcount("%", "debug non-static initializers", &Debug['%']) obj.Flagcount("A", "for bootstrapping, allow 'any' type", &Debug['A']) obj.Flagcount("B", "disable bounds checking", &Debug['B']) obj.Flagstr("D", "path: set relative path for local imports", &localimport) obj.Flagcount("E", "debug symbol export", &Debug['E']) obj.Flagfn1("I", "dir: add dir to import search path", addidir) obj.Flagcount("K", "debug missing line numbers", &Debug['K']) obj.Flagcount("L", "use full (long) path in error messages", &Debug['L']) obj.Flagcount("M", "debug move generation", &Debug['M']) obj.Flagcount("N", "disable optimizations", &Debug['N']) obj.Flagcount("P", "debug peephole optimizer", &Debug['P']) obj.Flagcount("R", "debug register optimizer", &Debug['R']) obj.Flagcount("S", "print assembly listing", &Debug['S']) obj.Flagfn0("V", "print compiler version", doversion) obj.Flagcount("W", "debug parse tree after type checking", &Debug['W']) obj.Flagstr("asmhdr", "file: write assembly header to named file", &asmhdr) obj.Flagcount("complete", "compiling complete package (no C or assembly)", &pure_go) obj.Flagstr("d", "list: print debug information about items in list", &debugstr) obj.Flagcount("e", "no limit on number of errors reported", &Debug['e']) obj.Flagcount("f", "debug stack frames", &Debug['f']) obj.Flagcount("g", "debug code generation", &Debug['g']) obj.Flagcount("h", "halt on error", &Debug['h']) obj.Flagcount("i", "debug line number stack", &Debug['i']) obj.Flagstr("installsuffix", "pkg directory suffix", &flag_installsuffix) obj.Flagcount("j", "debug runtime-initialized variables", &Debug['j']) obj.Flagcount("l", "disable inlining", &Debug['l']) obj.Flagcount("live", "debug liveness analysis", &debuglive) obj.Flagcount("m", "print optimization decisions", &Debug['m']) obj.Flagcount("nolocalimports", "reject local (relative) imports", &nolocalimports) obj.Flagstr("o", "obj: set output file", &outfile) obj.Flagstr("p", "path: set expected package import path", &myimportpath) obj.Flagcount("pack", "write package file instead of object file", &writearchive) obj.Flagcount("r", "debug generated wrappers", &Debug['r']) obj.Flagcount("race", "enable race detector", &flag_race) obj.Flagcount("s", "warn about composite literals that can be simplified", &Debug['s']) obj.Flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &Ctxt.Trimpath) obj.Flagcount("u", "reject unsafe code", &safemode) obj.Flagcount("v", "increase debug verbosity", &Debug['v']) obj.Flagcount("w", "debug type checking", &Debug['w']) use_writebarrier = 1 obj.Flagcount("wb", "enable write barrier", &use_writebarrier) obj.Flagcount("x", "debug lexer", &Debug['x']) obj.Flagcount("y", "debug declarations in canned imports (with -d)", &Debug['y']) var flag_shared int if Thearch.Thechar == '6' { obj.Flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel) obj.Flagcount("shared", "generate code that can be linked into a shared library", &flag_shared) } obj.Flagstr("cpuprofile", "file: write cpu profile to file", &cpuprofile) obj.Flagstr("memprofile", "file: write memory profile to file", &memprofile) obj.Flagparse(usage) Ctxt.Flag_shared = int32(flag_shared) Ctxt.Debugasm = int32(Debug['S']) Ctxt.Debugvlog = int32(Debug['v']) if flag.NArg() < 1 { usage() } startProfile() if flag_race != 0 { racepkg = mkpkg("runtime/race") racepkg.Name = "race" } // parse -d argument if debugstr != "" { var j int f := strings.Split(debugstr, ",") for i := range f { if f[i] == "" { continue } for j = 0; j < len(debugtab); j++ { if debugtab[j].name == f[i] { if debugtab[j].val != nil { *debugtab[j].val = 1 } break } } if j >= len(debugtab) { log.Fatalf("unknown debug information -d '%s'\n", f[i]) } } } // enable inlining. for now: // default: inlining on. (debug['l'] == 1) // -l: inlining off (debug['l'] == 0) // -ll, -lll: inlining on again, with extra debugging (debug['l'] > 1) if Debug['l'] <= 1 { Debug['l'] = 1 - Debug['l'] } Thearch.Betypeinit() if Widthptr == 0 { Fatal("betypeinit failed") } lexinit() typeinit() lexinit1() // TODO(rsc): Restore yytinit? blockgen = 1 dclcontext = PEXTERN nerrors = 0 lexlineno = 1 for _, infile = range flag.Args() { linehist(infile, 0, 0) curio.infile = infile var err error curio.bin, err = obj.Bopenr(infile) if err != nil { fmt.Printf("open %s: %v\n", infile, err) errorexit() } curio.peekc = 0 curio.peekc1 = 0 curio.nlsemi = 0 curio.eofnl = 0 curio.last = 0 // Skip initial BOM if present. if obj.Bgetrune(curio.bin) != obj.BOM { obj.Bungetrune(curio.bin) } block = 1 iota_ = -1000000 imported_unsafe = 0 yyparse() if nsyntaxerrors != 0 { errorexit() } linehist("<pop>", 0, 0) if curio.bin != nil { obj.Bterm(curio.bin) } } testdclstack() mkpackage(localpkg.Name) // final import not used checks lexfini() typecheckok = 1 if Debug['f'] != 0 { frame(1) } // Process top-level declarations in phases. // Phase 1: const, type, and names and types of funcs. // This will gather all the information about types // and methods but doesn't depend on any of it. defercheckwidth() for l := xtop; l != nil; l = l.Next { if l.N.Op != ODCL && l.N.Op != OAS { typecheck(&l.N, Etop) } } // Phase 2: Variable assignments. // To check interface assignments, depends on phase 1. for l := xtop; l != nil; l = l.Next { if l.N.Op == ODCL || l.N.Op == OAS { typecheck(&l.N, Etop) } } resumecheckwidth() // Phase 3: Type check function bodies. for l := xtop; l != nil; l = l.Next { if l.N.Op == ODCLFUNC || l.N.Op == OCLOSURE { Curfn = l.N decldepth = 1 saveerrors() typechecklist(l.N.Nbody, Etop) checkreturn(l.N) if nerrors != 0 { l.N.Nbody = nil // type errors; do not compile } } } // Phase 4: Decide how to capture closed variables. // This needs to run before escape analysis, // because variables captured by value do not escape. for l := xtop; l != nil; l = l.Next { if l.N.Op == ODCLFUNC && l.N.Closure != nil { Curfn = l.N capturevars(l.N) } } Curfn = nil if nsavederrors+nerrors != 0 { errorexit() } // Phase 5: Inlining if Debug['l'] > 1 { // Typecheck imported function bodies if debug['l'] > 1, // otherwise lazily when used or re-exported. for l := importlist; l != nil; l = l.Next { if l.N.Func.Inl != nil { saveerrors() typecheckinl(l.N) } } if nsavederrors+nerrors != 0 { errorexit() } } if Debug['l'] != 0 { // Find functions that can be inlined and clone them before walk expands them. visitBottomUp(xtop, func(list *NodeList, recursive bool) { for l := list; l != nil; l = l.Next { if l.N.Op == ODCLFUNC { caninl(l.N) inlcalls(l.N) } } }) } // Phase 6: Escape analysis. // Required for moving heap allocations onto stack, // which in turn is required by the closure implementation, // which stores the addresses of stack variables into the closure. // If the closure does not escape, it needs to be on the stack // or else the stack copier will not update it. escapes(xtop) // Escape analysis moved escaped values off stack. // Move large values off stack too. movelarge(xtop) // Phase 7: Transform closure bodies to properly reference captured variables. // This needs to happen before walk, because closures must be transformed // before walk reaches a call of a closure. for l := xtop; l != nil; l = l.Next { if l.N.Op == ODCLFUNC && l.N.Closure != nil { Curfn = l.N transformclosure(l.N) } } Curfn = nil // Phase 8: Compile top level functions. for l := xtop; l != nil; l = l.Next { if l.N.Op == ODCLFUNC { funccompile(l.N) } } if nsavederrors+nerrors == 0 { fninit(xtop) } // Phase 9: Check external declarations. for l := externdcl; l != nil; l = l.Next { if l.N.Op == ONAME { typecheck(&l.N, Erv) } } if nerrors+nsavederrors != 0 { errorexit() } dumpobj() if asmhdr != "" { dumpasmhdr() } if nerrors+nsavederrors != 0 { errorexit() } Flusherrors() }
func importfile(f *Val, line int) { if f.Ctype != CTSTR { Yyerror("import statement not a string") fakeimport() return } if len(f.U.Sval) == 0 { Yyerror("import path is empty") fakeimport() return } if isbadimport(f.U.Sval) { fakeimport() return } // The package name main is no longer reserved, // but we reserve the import path "main" to identify // the main package, just as we reserve the import // path "math" to identify the standard math package. if f.U.Sval == "main" { Yyerror("cannot import \"main\"") errorexit() } if myimportpath != "" && f.U.Sval == myimportpath { Yyerror("import %q while compiling that package (import cycle)", f.U.Sval) errorexit() } if f.U.Sval == "unsafe" { if safemode != 0 { Yyerror("cannot import package unsafe") errorexit() } importpkg = mkpkg(f.U.Sval) cannedimports("unsafe.6", unsafeimport) imported_unsafe = 1 return } path_ := f.U.Sval if islocalname(path_) { if path_[0] == '/' { Yyerror("import path cannot be absolute path") fakeimport() return } prefix := Ctxt.Pathname if localimport != "" { prefix = localimport } cleanbuf := prefix cleanbuf += "/" cleanbuf += path_ cleanbuf = path.Clean(cleanbuf) path_ = cleanbuf if isbadimport(path_) { fakeimport() return } } file, found := findpkg(path_) if !found { Yyerror("can't find import: %q", f.U.Sval) errorexit() } importpkg = mkpkg(path_) // If we already saw that package, feed a dummy statement // to the lexer to avoid parsing export data twice. if importpkg.Imported != 0 { tag := "" if importpkg.Safe { tag = "safe" } p := fmt.Sprintf("package %s %s\n$$\n", importpkg.Name, tag) cannedimports(file, p) return } importpkg.Imported = 1 var err error var imp *obj.Biobuf imp, err = obj.Bopenr(file) if err != nil { Yyerror("can't open import: %q: %v", f.U.Sval, err) errorexit() } if strings.HasSuffix(file, ".a") { if !skiptopkgdef(imp) { Yyerror("import %s: not a package file", file) errorexit() } } // check object header p := obj.Brdstr(imp, '\n', 1) if p != "empty archive" { if !strings.HasPrefix(p, "go object ") { Yyerror("import %s: not a go object file", file) errorexit() } q := fmt.Sprintf("%s %s %s %s", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring()) if p[10:] != q { Yyerror("import %s: object is [%s] expected [%s]", file, p[10:], q) errorexit() } } // assume files move (get installed) // so don't record the full path. linehist(file[len(file)-len(path_)-2:], -1, 1) // acts as #pragma lib /* * position the input right * after $$ and return */ pushedio = curio curio.bin = imp curio.peekc = 0 curio.peekc1 = 0 curio.infile = file curio.nlsemi = 0 typecheckok = 1 var c int32 for { c = int32(getc()) if c == EOF { break } if c != '$' { continue } c = int32(getc()) if c == EOF { break } if c != '$' { continue } return } Yyerror("no import in %q", f.U.Sval) unimportfile() }