Example #1
0
File: main.go Project: achanda/go
func Main() {
	timings.Start("fe", "init")

	defer hidePanic()

	Ctxt = obj.Linknew(Thearch.LinkArch)
	Ctxt.DiagFunc = yyerror
	Ctxt.Bso = bufio.NewWriter(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
	itabpkg = mkpkg("go.itab")
	itabpkg.Name = "go.itab"
	itabpkg.Prefix = "go.itab" // not go%2eitab

	itablinkpkg = mkpkg("go.itablink")
	itablinkpkg.Name = "go.itablink"
	itablinkpkg.Prefix = "go.itablink" // not go%2eitablink

	trackpkg = mkpkg("go.track")
	trackpkg.Name = "go.track"
	trackpkg.Prefix = "go.track" // not go%2etrack

	typepkg = mkpkg("type")
	typepkg.Name = "type"

	// pseudo-package used for map zero values
	mappkg = mkpkg("go.map")
	mappkg.Name = "go.map"
	mappkg.Prefix = "go.map"

	Nacl = obj.GOOS == "nacl"
	if Nacl {
		flag_largemodel = true
	}

	flag.BoolVar(&compiling_runtime, "+", false, "compiling runtime")
	obj.Flagcount("%", "debug non-static initializers", &Debug['%'])
	obj.Flagcount("B", "disable bounds checking", &Debug['B'])
	flag.StringVar(&localimport, "D", "", "set relative `path` for local imports")
	obj.Flagcount("E", "debug symbol export", &Debug['E'])
	obj.Flagfn1("I", "add `directory` to import search path", addidir)
	obj.Flagcount("K", "debug missing line numbers", &Debug['K'])
	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'])
	flag.StringVar(&asmhdr, "asmhdr", "", "write assembly header to `file`")
	flag.StringVar(&buildid, "buildid", "", "record `id` as the build id in the export metadata")
	flag.BoolVar(&pure_go, "complete", false, "compiling complete package (no C or assembly)")
	flag.StringVar(&debugstr, "d", "", "print debug information about items in `list`")
	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.Flagfn1("importmap", "add `definition` of the form source=actual to import map", addImportMap)
	flag.StringVar(&flag_installsuffix, "installsuffix", "", "set pkg directory `suffix`")
	obj.Flagcount("j", "debug runtime-initialized variables", &Debug['j'])
	obj.Flagcount("l", "disable inlining", &Debug['l'])
	flag.StringVar(&linkobj, "linkobj", "", "write linker-specific object to `file`")
	obj.Flagcount("live", "debug liveness analysis", &debuglive)
	obj.Flagcount("m", "print optimization decisions", &Debug['m'])
	flag.BoolVar(&flag_msan, "msan", false, "build code compatible with C/C++ memory sanitizer")
	flag.BoolVar(&nolocalimports, "nolocalimports", false, "reject local (relative) imports")
	flag.StringVar(&outfile, "o", "", "write output to `file`")
	flag.StringVar(&myimportpath, "p", "", "set expected package import `path`")
	flag.BoolVar(&writearchive, "pack", false, "write package file instead of object file")
	obj.Flagcount("r", "debug generated wrappers", &Debug['r'])
	flag.BoolVar(&flag_race, "race", false, "enable race detector")
	obj.Flagcount("s", "warn about composite literals that can be simplified", &Debug['s'])
	flag.StringVar(&Ctxt.LineHist.TrimPathPrefix, "trimpath", "", "remove `prefix` from recorded source file paths")
	flag.BoolVar(&safemode, "u", false, "reject unsafe code")
	obj.Flagcount("v", "increase debug verbosity", &Debug['v'])
	obj.Flagcount("w", "debug type checking", &Debug['w'])
	flag.BoolVar(&use_writebarrier, "wb", true, "enable write barrier")
	obj.Flagcount("x", "debug lexer", &Debug['x'])
	var flag_shared bool
	var flag_dynlink bool
	if supportsDynlink(Thearch.LinkArch.Arch) {
		flag.BoolVar(&flag_shared, "shared", false, "generate code that can be linked into a shared library")
		flag.BoolVar(&flag_dynlink, "dynlink", false, "support references to Go symbols defined in other shared libraries")
	}
	if Thearch.LinkArch.Family == sys.AMD64 {
		flag.BoolVar(&flag_largemodel, "largemodel", false, "generate code that assumes a large memory model")
	}
	flag.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to `file`")
	flag.StringVar(&memprofile, "memprofile", "", "write memory profile to `file`")
	flag.Int64Var(&memprofilerate, "memprofilerate", 0, "set runtime.MemProfileRate to `rate`")
	flag.StringVar(&traceprofile, "traceprofile", "", "write an execution trace to `file`")
	flag.StringVar(&benchfile, "bench", "", "append benchmark times to `file`")
	obj.Flagparse(usage)

	Ctxt.Flag_shared = flag_dynlink || flag_shared
	Ctxt.Flag_dynlink = flag_dynlink
	Ctxt.Flag_optimize = Debug['N'] == 0

	Ctxt.Debugasm = int32(Debug['S'])
	Ctxt.Debugvlog = int32(Debug['v'])

	if flag.NArg() < 1 {
		usage()
	}

	startProfile()

	if flag_race {
		racepkg = mkpkg("runtime/race")
		racepkg.Name = "race"
	}
	if flag_msan {
		msanpkg = mkpkg("runtime/msan")
		msanpkg.Name = "msan"
	}
	if flag_race && flag_msan {
		log.Fatal("cannot use both -race and -msan")
	} else if flag_race || flag_msan {
		instrumenting = true
	}

	// parse -d argument
	if debugstr != "" {
	Split:
		for _, name := range strings.Split(debugstr, ",") {
			if name == "" {
				continue
			}
			val := 1
			valstring := ""
			if i := strings.Index(name, "="); i >= 0 {
				var err error
				val, err = strconv.Atoi(name[i+1:])
				if err != nil {
					log.Fatalf("invalid debug value %v", name)
				}
				name = name[:i]
			} else if i := strings.Index(name, ":"); i >= 0 {
				valstring = name[i+1:]
				name = name[:i]
			}
			for _, t := range debugtab {
				if t.name == name {
					if t.val != nil {
						*t.val = val
						continue Split
					}
				}
			}
			// special case for ssa for now
			if strings.HasPrefix(name, "ssa/") {
				// expect form ssa/phase/flag
				// e.g. -d=ssa/generic_cse/time
				// _ in phase name also matches space
				phase := name[4:]
				flag := "debug" // default flag is debug
				if i := strings.Index(phase, "/"); i >= 0 {
					flag = phase[i+1:]
					phase = phase[:i]
				}
				err := ssa.PhaseOption(phase, flag, val, valstring)
				if err != "" {
					log.Fatalf(err)
				}
				continue Split
			}
			log.Fatalf("unknown debug key -d %s\n", name)
		}
	}

	// 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']
	}

	Widthint = Thearch.LinkArch.IntSize
	Widthptr = Thearch.LinkArch.PtrSize
	Widthreg = Thearch.LinkArch.RegSize

	initUniverse()

	blockgen = 1
	dclcontext = PEXTERN
	nerrors = 0
	lexlineno = 1

	timings.Start("fe", "loadsys")
	loadsys()

	timings.Start("fe", "parse")
	lexlineno0 := lexlineno
	for _, infile = range flag.Args() {
		if trace && Debug['x'] != 0 {
			fmt.Printf("--- %s ---\n", infile)
		}

		linehistpush(infile)
		block = 1
		iota_ = -1000000
		imported_unsafe = false
		parseFile(infile)
		if nsyntaxerrors != 0 {
			errorexit()
		}

		// Instead of converting EOF into '\n' in getc and count it as an extra line
		// for the line history to work, and which then has to be corrected elsewhere,
		// just add a line here.
		lexlineno++
		linehistpop()
	}
	timings.Stop()
	timings.AddEvent(int64(lexlineno-lexlineno0), "lines")

	testdclstack()
	mkpackage(localpkg.Name) // final import not used checks
	finishUniverse()

	typecheckok = true
	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()

	// Don't use range--typecheck can add closures to xtop.
	timings.Start("fe", "typecheck", "top1")
	for i := 0; i < len(xtop); i++ {
		if xtop[i].Op != ODCL && xtop[i].Op != OAS && xtop[i].Op != OAS2 {
			xtop[i] = typecheck(xtop[i], Etop)
		}
	}

	// Phase 2: Variable assignments.
	//   To check interface assignments, depends on phase 1.

	// Don't use range--typecheck can add closures to xtop.
	timings.Start("fe", "typecheck", "top2")
	for i := 0; i < len(xtop); i++ {
		if xtop[i].Op == ODCL || xtop[i].Op == OAS || xtop[i].Op == OAS2 {
			xtop[i] = typecheck(xtop[i], Etop)
		}
	}
	resumecheckwidth()

	// Phase 3: Type check function bodies.
	// Don't use range--typecheck can add closures to xtop.
	timings.Start("fe", "typecheck", "func")
	var fcount int64
	for i := 0; i < len(xtop); i++ {
		if xtop[i].Op == ODCLFUNC || xtop[i].Op == OCLOSURE {
			Curfn = xtop[i]
			decldepth = 1
			saveerrors()
			typecheckslice(Curfn.Nbody.Slice(), Etop)
			checkreturn(Curfn)
			if nerrors != 0 {
				Curfn.Nbody.Set(nil) // type errors; do not compile
			}
			fcount++
		}
	}
	timings.AddEvent(fcount, "funcs")

	// Phase 4: Decide how to capture closed variables.
	// This needs to run before escape analysis,
	// because variables captured by value do not escape.
	timings.Start("fe", "capturevars")
	for _, n := range xtop {
		if n.Op == ODCLFUNC && n.Func.Closure != nil {
			Curfn = n
			capturevars(n)
		}
	}

	Curfn = nil

	if nsavederrors+nerrors != 0 {
		errorexit()
	}

	// Phase 5: Inlining
	timings.Start("fe", "inlining")
	if Debug['l'] > 1 {
		// Typecheck imported function bodies if debug['l'] > 1,
		// otherwise lazily when used or re-exported.
		for _, n := range importlist {
			if n.Func.Inl.Len() != 0 {
				saveerrors()
				typecheckinl(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 []*Node, recursive bool) {
			for _, n := range list {
				if !recursive {
					caninl(n)
				} else {
					if Debug['m'] > 1 {
						fmt.Printf("%v: cannot inline %v: recursive\n", n.Line(), n.Func.Nname)
					}
				}
				inlcalls(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.
	// Large values are also moved off stack in escape analysis;
	// because large values may contain pointers, it must happen early.
	timings.Start("fe", "escapes")
	escapes(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.
	timings.Start("fe", "xclosures")
	for _, n := range xtop {
		if n.Op == ODCLFUNC && n.Func.Closure != nil {
			Curfn = n
			transformclosure(n)
		}
	}

	Curfn = nil

	// Phase 8: Compile top level functions.
	// Don't use range--walk can add functions to xtop.
	timings.Start("be", "compilefuncs")
	fcount = 0
	for i := 0; i < len(xtop); i++ {
		if xtop[i].Op == ODCLFUNC {
			funccompile(xtop[i])
			fcount++
		}
	}
	timings.AddEvent(fcount, "funcs")

	if nsavederrors+nerrors == 0 {
		fninit(xtop)
	}

	if compiling_runtime {
		checknowritebarrierrec()
	}

	// Phase 9: Check external declarations.
	timings.Start("be", "externaldcls")
	for i, n := range externdcl {
		if n.Op == ONAME {
			externdcl[i] = typecheck(externdcl[i], Erv)
		}
	}

	if nerrors+nsavederrors != 0 {
		errorexit()
	}

	timings.Start("be", "dumpobj")
	dumpobj()
	if asmhdr != "" {
		dumpasmhdr()
	}

	if nerrors+nsavederrors != 0 {
		errorexit()
	}

	flusherrors()
	timings.Stop()

	if benchfile != "" {
		if err := writebench(benchfile); err != nil {
			log.Fatalf("cannot write benchmark data: %v", err)
		}
	}
}
Example #2
0
File: main.go Project: achanda/go
// Main is the main entry point for the linker code.
func Main() {
	ctxt := linknew(SysArch)
	ctxt.Bso = bufio.NewWriter(os.Stdout)

	// For testing behavior of go command when tools crash silently.
	// Undocumented, not in standard flag parser to avoid
	// exposing in usage message.
	for _, arg := range os.Args {
		if arg == "-crash_for_testing" {
			os.Exit(2)
		}
	}

	// TODO(matloob): define these above and then check flag values here
	if SysArch.Family == sys.AMD64 && obj.GOOS == "plan9" {
		flag.BoolVar(&Flag8, "8", false, "use 64-bit addresses in symbol table")
	}
	obj.Flagfn1("B", "add an ELF NT_GNU_BUILD_ID `note` when using ELF", addbuildinfo)
	obj.Flagfn1("L", "add specified `directory` to library path", func(a string) { Lflag(ctxt, a) })
	obj.Flagfn0("V", "print version and exit", doversion)
	obj.Flagfn1("X", "add string value `definition` of the form importpath.name=value", func(s string) { addstrdata1(ctxt, s) })
	obj.Flagcount("v", "print link trace", &ctxt.Debugvlog)

	obj.Flagparse(usage)

	startProfile()
	if Buildmode == BuildmodeUnset {
		Buildmode = BuildmodeExe
	}

	if Buildmode != BuildmodeShared && flag.NArg() != 1 {
		usage()
	}

	if *flagOutfile == "" {
		*flagOutfile = "a.out"
		if Headtype == obj.Hwindows || Headtype == obj.Hwindowsgui {
			*flagOutfile += ".exe"
		}
	}

	interpreter = *flagInterpreter

	libinit(ctxt) // creates outfile

	if Headtype == obj.Hunknown {
		Headtype.Set(obj.GOOS)
	}

	ctxt.computeTLSOffset()
	Thearch.Archinit(ctxt)

	if *FlagLinkshared && !Iself {
		Exitf("-linkshared can only be used on elf systems")
	}

	if ctxt.Debugvlog != 0 {
		ctxt.Logf("HEADER = -H%d -T0x%x -D0x%x -R0x%x\n", Headtype, uint64(*FlagTextAddr), uint64(*FlagDataAddr), uint32(*FlagRound))
	}

	switch Buildmode {
	case BuildmodeShared:
		for i := 0; i < flag.NArg(); i++ {
			arg := flag.Arg(i)
			parts := strings.SplitN(arg, "=", 2)
			var pkgpath, file string
			if len(parts) == 1 {
				pkgpath, file = "main", arg
			} else {
				pkgpath, file = parts[0], parts[1]
			}
			pkglistfornote = append(pkglistfornote, pkgpath...)
			pkglistfornote = append(pkglistfornote, '\n')
			addlibpath(ctxt, "command line", "command line", file, pkgpath, "")
		}
	case BuildmodePlugin:
		pluginName := strings.TrimSuffix(filepath.Base(flag.Arg(0)), ".a")
		addlibpath(ctxt, "command line", "command line", flag.Arg(0), pluginName, "")
	default:
		addlibpath(ctxt, "command line", "command line", flag.Arg(0), "main", "")
	}
	ctxt.loadlib()

	ctxt.checkstrdata()
	deadcode(ctxt)
	fieldtrack(ctxt)
	ctxt.callgraph()

	ctxt.doelf()
	if Headtype == obj.Hdarwin {
		ctxt.domacho()
	}
	ctxt.dostkcheck()
	if Headtype == obj.Hwindows || Headtype == obj.Hwindowsgui {
		ctxt.dope()
	}
	ctxt.addexport()
	Thearch.Gentext(ctxt) // trampolines, call stubs, etc.
	ctxt.textbuildid()
	ctxt.textaddress()
	ctxt.pclntab()
	ctxt.findfunctab()
	ctxt.typelink()
	ctxt.symtab()
	ctxt.dodata()
	ctxt.address()
	ctxt.reloc()
	Thearch.Asmb(ctxt)
	ctxt.undef()
	ctxt.hostlink()
	ctxt.archive()
	if ctxt.Debugvlog != 0 {
		ctxt.Logf("%5.2f cpu time\n", obj.Cputime())
		ctxt.Logf("%d symbols\n", len(ctxt.Syms.Allsym))
		ctxt.Logf("%d liveness data\n", liveness)
	}

	ctxt.Bso.Flush()

	errorexit()
}
Example #3
0
File: lex.go Project: tidatida/go
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()
}
Example #4
0
File: pobj.go Project: korli/go
func Ldmain() {
	Ctxt = linknew(Thelinkarch)
	Ctxt.Thechar = int32(Thearch.Thechar)
	Ctxt.Thestring = Thestring
	Ctxt.Diag = Diag
	Ctxt.Bso = &Bso

	Bso = *obj.Binitw(os.Stdout)
	Debug = [128]int{}
	nerrors = 0
	outfile = ""
	HEADTYPE = -1
	INITTEXT = -1
	INITDAT = -1
	INITRND = -1
	INITENTRY = ""
	Linkmode = LinkAuto

	// For testing behavior of go command when tools crash silently.
	// Undocumented, not in standard flag parser to avoid
	// exposing in usage message.
	for _, arg := range os.Args {
		if arg == "-crash_for_testing" {
			os.Exit(2)
		}
	}

	if Thearch.Thechar == '6' && obj.Getgoos() == "plan9" {
		obj.Flagcount("8", "use 64-bit addresses in symbol table", &Debug['8'])
	}
	obj.Flagfn1("B", "add an ELF NT_GNU_BUILD_ID `note` when using ELF", addbuildinfo)
	obj.Flagcount("C", "check Go calls to C code", &Debug['C'])
	obj.Flagint64("D", "set data segment `address`", &INITDAT)
	obj.Flagstr("E", "set `entry` symbol name", &INITENTRY)
	obj.Flagfn1("I", "use `linker` as ELF dynamic linker", setinterp)
	obj.Flagfn1("L", "add specified `directory` to library path", Lflag)
	obj.Flagfn1("H", "set header `type`", setheadtype)
	obj.Flagint32("R", "set address rounding `quantum`", &INITRND)
	obj.Flagint64("T", "set text segment `address`", &INITTEXT)
	obj.Flagfn0("V", "print version and exit", doversion)
	obj.Flagcount("W", "disassemble input", &Debug['W'])
	obj.Flagfn1("X", "add string value `definition` of the form importpath.name=value", addstrdata1)
	obj.Flagcount("a", "disassemble output", &Debug['a'])
	obj.Flagstr("buildid", "record `id` as Go toolchain build id", &buildid)
	flag.Var(&Buildmode, "buildmode", "set build `mode`")
	obj.Flagcount("c", "dump call graph", &Debug['c'])
	obj.Flagcount("d", "disable dynamic executable", &Debug['d'])
	obj.Flagstr("extld", "use `linker` when linking in external mode", &extld)
	obj.Flagstr("extldflags", "pass `flags` to external linker", &extldflags)
	obj.Flagcount("f", "ignore version mismatch", &Debug['f'])
	obj.Flagcount("g", "disable go package data checks", &Debug['g'])
	obj.Flagcount("h", "halt on error", &Debug['h'])
	obj.Flagstr("installsuffix", "set package directory `suffix`", &flag_installsuffix)
	obj.Flagstr("k", "set field tracking `symbol`", &tracksym)
	obj.Flagfn1("linkmode", "set link `mode` (internal, external, auto)", setlinkmode)
	flag.BoolVar(&Linkshared, "linkshared", false, "link against installed Go shared libraries")
	obj.Flagcount("n", "dump symbol table", &Debug['n'])
	obj.Flagstr("o", "write output to `file`", &outfile)
	flag.Var(&rpath, "r", "set the ELF dynamic linker search `path` to dir1:dir2:...")
	obj.Flagcount("race", "enable race detector", &flag_race)
	obj.Flagcount("s", "disable symbol table", &Debug['s'])
	var flagShared int
	if Thearch.Thechar == '5' || Thearch.Thechar == '6' {
		obj.Flagcount("shared", "generate shared object (implies -linkmode external)", &flagShared)
	}
	obj.Flagstr("tmpdir", "use `directory` for temporary files", &tmpdir)
	obj.Flagcount("u", "reject unsafe packages", &Debug['u'])
	obj.Flagcount("v", "print link trace", &Debug['v'])
	obj.Flagcount("w", "disable DWARF generation", &Debug['w'])

	obj.Flagstr("cpuprofile", "write cpu profile to `file`", &cpuprofile)
	obj.Flagstr("memprofile", "write memory profile to `file`", &memprofile)
	obj.Flagint64("memprofilerate", "set runtime.MemProfileRate to `rate`", &memprofilerate)

	// Clumsy hack to preserve old two-argument -X name val syntax for old scripts.
	// Rewrite that syntax into new syntax -X name=val.
	// TODO(rsc): Delete this hack in Go 1.6 or later.
	var args []string
	for i := 0; i < len(os.Args); i++ {
		arg := os.Args[i]
		if (arg == "-X" || arg == "--X") && i+2 < len(os.Args) && !strings.Contains(os.Args[i+1], "=") {
			fmt.Fprintf(os.Stderr, "link: warning: option %s %s %s may not work in future releases; use %s %s=%s\n",
				arg, os.Args[i+1], os.Args[i+2],
				arg, os.Args[i+1], os.Args[i+2])
			args = append(args, arg)
			args = append(args, os.Args[i+1]+"="+os.Args[i+2])
			i += 2
			continue
		}
		if (strings.HasPrefix(arg, "-X=") || strings.HasPrefix(arg, "--X=")) && i+1 < len(os.Args) && strings.Count(arg, "=") == 1 {
			fmt.Fprintf(os.Stderr, "link: warning: option %s %s may not work in future releases; use %s=%s\n",
				arg, os.Args[i+1],
				arg, os.Args[i+1])
			args = append(args, arg+"="+os.Args[i+1])
			i++
			continue
		}
		args = append(args, arg)
	}
	os.Args = args

	obj.Flagparse(usage)

	startProfile()
	Ctxt.Bso = &Bso
	Ctxt.Debugvlog = int32(Debug['v'])
	if flagShared != 0 {
		if Buildmode == BuildmodeUnset {
			Buildmode = BuildmodeCShared
		} else if Buildmode != BuildmodeCShared {
			Exitf("-shared and -buildmode=%s are incompatible", Buildmode.String())
		}
	}
	if Buildmode == BuildmodeUnset {
		Buildmode = BuildmodeExe
	}

	if Buildmode != BuildmodeShared && flag.NArg() != 1 {
		usage()
	}

	if outfile == "" {
		outfile = "a.out"
		if HEADTYPE == obj.Hwindows {
			outfile += ".exe"
		}
	}

	libinit() // creates outfile

	if HEADTYPE == -1 {
		HEADTYPE = int32(headtype(goos))
	}
	Ctxt.Headtype = int(HEADTYPE)
	if headstring == "" {
		headstring = Headstr(int(HEADTYPE))
	}
	if HEADTYPE == obj.Hhaiku {
		Linkmode = LinkExternal
	}

	Thearch.Archinit()

	if Linkshared && !Iself {
		Exitf("-linkshared can only be used on elf systems")
	}

	if Debug['v'] != 0 {
		fmt.Fprintf(&Bso, "HEADER = -H%d -T0x%x -D0x%x -R0x%x\n", HEADTYPE, uint64(INITTEXT), uint64(INITDAT), uint32(INITRND))
	}
	Bso.Flush()

	if Buildmode == BuildmodeShared {
		for i := 0; i < flag.NArg(); i++ {
			arg := flag.Arg(i)
			parts := strings.SplitN(arg, "=", 2)
			var pkgpath, file string
			if len(parts) == 1 {
				pkgpath, file = "main", arg
			} else {
				pkgpath, file = parts[0], parts[1]
			}
			pkglistfornote = append(pkglistfornote, pkgpath...)
			pkglistfornote = append(pkglistfornote, '\n')
			addlibpath(Ctxt, "command line", "command line", file, pkgpath, "")
		}
	} else {
		addlibpath(Ctxt, "command line", "command line", flag.Arg(0), "main", "")
	}
	loadlib()

	if Thearch.Thechar == '5' {
		// mark some functions that are only referenced after linker code editing
		if Ctxt.Goarm == 5 {
			mark(Linkrlookup(Ctxt, "_sfloat", 0))
		}
		mark(Linklookup(Ctxt, "runtime.read_tls_fallback", 0))
	}

	checkgo()
	checkstrdata()
	deadcode()
	callgraph()

	doelf()
	if HEADTYPE == obj.Hdarwin {
		domacho()
	}
	dostkcheck()
	if HEADTYPE == obj.Hwindows {
		dope()
	}
	addexport()
	Thearch.Gentext() // trampolines, call stubs, etc.
	textbuildid()
	textaddress()
	pclntab()
	findfunctab()
	symtab()
	dodata()
	address()
	doweak()
	reloc()
	Thearch.Asmb()
	undef()
	hostlink()
	archive()
	if Debug['v'] != 0 {
		fmt.Fprintf(&Bso, "%5.2f cpu time\n", obj.Cputime())
		fmt.Fprintf(&Bso, "%d symbols\n", Ctxt.Nsymbol)
		fmt.Fprintf(&Bso, "%d liveness data\n", liveness)
	}

	Bso.Flush()

	errorexit()
}
Example #5
0
File: main.go Project: hurkgu/go
// Main is the main entry point for the linker code.
func Main() {
	ctxt := linknew(SysArch)
	ctxt.Bso = bufio.NewWriter(os.Stdout)

	nerrors = 0
	HEADTYPE = -1
	Linkmode = LinkAuto

	// For testing behavior of go command when tools crash silently.
	// Undocumented, not in standard flag parser to avoid
	// exposing in usage message.
	for _, arg := range os.Args {
		if arg == "-crash_for_testing" {
			os.Exit(2)
		}
	}

	// TODO(matloob): define these above and then check flag values here
	if SysArch.Family == sys.AMD64 && obj.Getgoos() == "plan9" {
		flag.BoolVar(&Flag8, "8", false, "use 64-bit addresses in symbol table")
	}
	obj.Flagfn1("B", "add an ELF NT_GNU_BUILD_ID `note` when using ELF", addbuildinfo)
	obj.Flagfn1("L", "add specified `directory` to library path", func(a string) { Lflag(ctxt, a) })
	obj.Flagfn1("H", "set header `type`", setheadtype)
	obj.Flagfn0("V", "print version and exit", doversion)
	obj.Flagfn1("X", "add string value `definition` of the form importpath.name=value", func(s string) { addstrdata1(ctxt, s) })
	obj.Flagcount("v", "print link trace", &ctxt.Debugvlog)
	obj.Flagfn1("linkmode", "set link `mode` (internal, external, auto)", setlinkmode)
	var flagShared bool
	if SysArch.InFamily(sys.ARM, sys.AMD64) {
		flag.BoolVar(&flagShared, "shared", false, "generate shared object (implies -linkmode external)")
	}

	obj.Flagparse(usage)

	startProfile()
	if flagShared {
		if Buildmode == BuildmodeUnset {
			Buildmode = BuildmodeCShared
		} else if Buildmode != BuildmodeCShared {
			Exitf("-shared and -buildmode=%s are incompatible", Buildmode.String())
		}
	}
	if Buildmode == BuildmodeUnset {
		Buildmode = BuildmodeExe
	}

	if Buildmode != BuildmodeShared && flag.NArg() != 1 {
		usage()
	}

	if *flagOutfile == "" {
		*flagOutfile = "a.out"
		if HEADTYPE == obj.Hwindows {
			*flagOutfile += ".exe"
		}
	}

	interpreter = *flagInterpreter

	libinit(ctxt) // creates outfile

	if HEADTYPE == -1 {
		HEADTYPE = int32(headtype(goos))
	}
	ctxt.Headtype = int(HEADTYPE)
	if headstring == "" {
		headstring = Headstr(int(HEADTYPE))
	}

	Thearch.Archinit(ctxt)

	if *FlagLinkshared && !Iself {
		Exitf("-linkshared can only be used on elf systems")
	}

	if ctxt.Debugvlog != 0 {
		ctxt.Logf("HEADER = -H%d -T0x%x -D0x%x -R0x%x\n", HEADTYPE, uint64(*FlagTextAddr), uint64(*FlagDataAddr), uint32(*FlagRound))
	}

	if Buildmode == BuildmodeShared {
		for i := 0; i < flag.NArg(); i++ {
			arg := flag.Arg(i)
			parts := strings.SplitN(arg, "=", 2)
			var pkgpath, file string
			if len(parts) == 1 {
				pkgpath, file = "main", arg
			} else {
				pkgpath, file = parts[0], parts[1]
			}
			pkglistfornote = append(pkglistfornote, pkgpath...)
			pkglistfornote = append(pkglistfornote, '\n')
			addlibpath(ctxt, "command line", "command line", file, pkgpath, "")
		}
	} else {
		addlibpath(ctxt, "command line", "command line", flag.Arg(0), "main", "")
	}
	ctxt.loadlib()

	ctxt.checkstrdata()
	deadcode(ctxt)
	fieldtrack(ctxt)
	ctxt.callgraph()

	ctxt.doelf()
	if HEADTYPE == obj.Hdarwin {
		ctxt.domacho()
	}
	ctxt.dostkcheck()
	if HEADTYPE == obj.Hwindows {
		ctxt.dope()
	}
	ctxt.addexport()
	Thearch.Gentext(ctxt) // trampolines, call stubs, etc.
	ctxt.textbuildid()
	ctxt.textaddress()
	ctxt.pclntab()
	ctxt.findfunctab()
	ctxt.symtab()
	ctxt.dodata()
	ctxt.address()
	ctxt.reloc()
	Thearch.Asmb(ctxt)
	ctxt.undef()
	ctxt.hostlink()
	ctxt.archive()
	if ctxt.Debugvlog != 0 {
		ctxt.Logf("%5.2f cpu time\n", obj.Cputime())
		ctxt.Logf("%d symbols\n", len(ctxt.Allsym))
		ctxt.Logf("%d liveness data\n", liveness)
	}

	ctxt.Bso.Flush()

	errorexit()
}
Example #6
0
File: lex.go Project: ckeyer/gosrc
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.DiagFunc = 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", "set relative `path` for local imports", &localimport)
	obj.Flagcount("E", "debug symbol export", &Debug['E'])
	obj.Flagfn1("I", "add `directory` 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", "write assembly header to `file`", &asmhdr)
	obj.Flagstr("buildid", "record `id` as the build id in the export metadata", &buildid)
	obj.Flagcount("complete", "compiling complete package (no C or assembly)", &pure_go)
	obj.Flagstr("d", "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.Flagfn1("importmap", "add `definition` of the form source=actual to import map", addImportMap)
	obj.Flagstr("installsuffix", "set 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("msan", "build code compatible with C/C++ memory sanitizer", &flag_msan)
	obj.Flagcount("newexport", "use new export format", &newexport) // TODO(gri) remove eventually (issue 13241)
	obj.Flagcount("nolocalimports", "reject local (relative) imports", &nolocalimports)
	obj.Flagstr("o", "write output to `file`", &outfile)
	obj.Flagstr("p", "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", "remove `prefix` from recorded source file paths", &Ctxt.LineHist.TrimPathPrefix)
	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
	var flag_dynlink bool
	switch Thearch.Thechar {
	case '5', '6', '7', '8', '9':
		obj.Flagcount("shared", "generate code that can be linked into a shared library", &flag_shared)
	}
	if Thearch.Thechar == '6' {
		obj.Flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel)
	}
	switch Thearch.Thechar {
	case '5', '6', '7', '8', '9':
		flag.BoolVar(&flag_dynlink, "dynlink", false, "support references to Go symbols defined in other shared libraries")
	}
	obj.Flagstr("cpuprofile", "write cpu profile to `file`", &cpuprofile)
	obj.Flagstr("memprofile", "write memory profile to `file`", &memprofile)
	obj.Flagint64("memprofilerate", "set runtime.MemProfileRate to `rate`", &memprofilerate)
	obj.Flagparse(usage)

	if flag_dynlink {
		flag_shared = 1
	}
	Ctxt.Flag_shared = int32(flag_shared)
	Ctxt.Flag_dynlink = flag_dynlink

	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"
	}
	if flag_msan != 0 {
		msanpkg = mkpkg("runtime/msan")
		msanpkg.Name = "msan"
	}
	if flag_race != 0 && flag_msan != 0 {
		log.Fatal("can not use both -race and -msan")
	} else if flag_race != 0 || flag_msan != 0 {
		instrumenting = true
	}

	// parse -d argument
	if debugstr != "" {
	Split:
		for _, name := range strings.Split(debugstr, ",") {
			if name == "" {
				continue
			}
			val := 1
			if i := strings.Index(name, "="); i >= 0 {
				var err error
				val, err = strconv.Atoi(name[i+1:])
				if err != nil {
					log.Fatalf("invalid debug value %v", name)
				}
				name = name[:i]
			}
			for _, t := range debugtab {
				if t.name == name {
					if t.val != nil {
						*t.val = val
						continue Split
					}
				}
			}
			log.Fatalf("unknown debug key -d %s\n", name)
		}
	}

	// 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 {
		Fatalf("betypeinit failed")
	}

	lexinit()
	typeinit()
	lexinit1()

	blockgen = 1
	dclcontext = PEXTERN
	nerrors = 0
	lexlineno = 1
	const BOM = 0xFEFF

	for _, infile = range flag.Args() {
		if trace && Debug['x'] != 0 {
			fmt.Printf("--- %s ---\n", infile)
		}

		linehistpush(infile)

		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 = false
		curio.eofnl = false
		curio.last = 0

		// Skip initial BOM if present.
		if obj.Bgetrune(curio.bin) != BOM {
			obj.Bungetrune(curio.bin)
		}

		block = 1
		iota_ = -1000000

		imported_unsafe = false

		parse_file()
		if nsyntaxerrors != 0 {
			errorexit()
		}

		linehistpop()
		if curio.bin != nil {
			obj.Bterm(curio.bin)
		}
	}

	testdclstack()
	mkpackage(localpkg.Name) // final import not used checks
	lexfini()

	typecheckok = true
	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 && l.N.Op != OAS2 {
			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 || l.N.Op == OAS2 {
			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.Func.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 _, n := range importlist {
			if n.Func.Inl != nil {
				saveerrors()
				typecheckinl(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 []*Node, recursive bool) {
			// TODO: use a range statement here if the order does not matter
			for i := len(list) - 1; i >= 0; i-- {
				n := list[i]
				if n.Op == ODCLFUNC {
					caninl(n)
					inlcalls(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.
	// Large values are also moved off stack in escape analysis;
	// because large values may contain pointers, it must happen early.
	escapes(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.Func.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)
	}

	if compiling_runtime != 0 {
		checknowritebarrierrec()
	}

	// Phase 9: Check external declarations.
	for i, n := range externdcl {
		if n.Op == ONAME {
			typecheck(&externdcl[i], Erv)
		}
	}

	if nerrors+nsavederrors != 0 {
		errorexit()
	}

	dumpobj()

	if asmhdr != "" {
		dumpasmhdr()
	}

	if nerrors+nsavederrors != 0 {
		errorexit()
	}

	Flusherrors()
}
Example #7
0
func Ldmain() {
	Ctxt = linknew(Thelinkarch)
	Ctxt.Thechar = int32(Thearch.Thechar)
	Ctxt.Thestring = Thestring
	Ctxt.Diag = Diag
	Ctxt.Bso = &Bso

	Bso = *Binitw(os.Stdout)
	Debug = [128]int{}
	nerrors = 0
	outfile = ""
	HEADTYPE = -1
	INITTEXT = -1
	INITDAT = -1
	INITRND = -1
	INITENTRY = ""
	Linkmode = LinkAuto

	// For testing behavior of go command when tools crash.
	// Undocumented, not in standard flag parser to avoid
	// exposing in usage message.
	for _, arg := range os.Args {
		if arg == "-crash_for_testing" {
			*(*int)(nil) = 0
		}
	}

	if Thearch.Thechar == '5' && Ctxt.Goarm == 5 {
		Debug['F'] = 1
	}

	obj.Flagcount("1", "use alternate profiling code", &Debug['1'])
	if Thearch.Thechar == '6' {
		obj.Flagcount("8", "assume 64-bit addresses", &Debug['8'])
	}
	obj.Flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo)
	obj.Flagcount("C", "check Go calls to C code", &Debug['C'])
	obj.Flagint64("D", "addr: data address", &INITDAT)
	obj.Flagstr("E", "sym: entry symbol", &INITENTRY)
	if Thearch.Thechar == '5' {
		obj.Flagcount("G", "debug pseudo-ops", &Debug['G'])
	}
	obj.Flagfn1("I", "interp: set ELF interp", setinterp)
	obj.Flagfn1("L", "dir: add dir to library path", Lflag)
	obj.Flagfn1("H", "head: header type", setheadtype)
	obj.Flagcount("K", "add stack underflow checks", &Debug['K'])
	if Thearch.Thechar == '5' {
		obj.Flagcount("M", "disable software div/mod", &Debug['M'])
	}
	obj.Flagcount("O", "print pc-line tables", &Debug['O'])
	obj.Flagcount("Q", "debug byte-register code gen", &Debug['Q'])
	if Thearch.Thechar == '5' {
		obj.Flagcount("P", "debug code generation", &Debug['P'])
	}
	obj.Flagint32("R", "rnd: address rounding", &INITRND)
	obj.Flagcount("nil", "check type signatures", &Debug['S'])
	obj.Flagint64("T", "addr: text address", &INITTEXT)
	obj.Flagfn0("V", "print version and exit", doversion)
	obj.Flagcount("W", "disassemble input", &Debug['W'])
	obj.Flagfn1("X", "name value: define string data", addstrdata1)
	obj.Flagcount("Z", "clear stack frame on entry", &Debug['Z'])
	obj.Flagcount("a", "disassemble output", &Debug['a'])
	obj.Flagcount("c", "dump call graph", &Debug['c'])
	obj.Flagcount("d", "disable dynamic executable", &Debug['d'])
	obj.Flagstr("extld", "ld: linker to run in external mode", &extld)
	obj.Flagstr("extldflags", "ldflags: flags for external linker", &extldflags)
	obj.Flagcount("f", "ignore version mismatch", &Debug['f'])
	obj.Flagcount("g", "disable go package data checks", &Debug['g'])
	obj.Flagstr("installsuffix", "suffix: pkg directory suffix", &flag_installsuffix)
	obj.Flagstr("k", "sym: set field tracking symbol", &tracksym)
	obj.Flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode)
	obj.Flagcount("n", "dump symbol table", &Debug['n'])
	obj.Flagstr("o", "outfile: set output file", &outfile)
	obj.Flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath)
	obj.Flagcount("race", "enable race detector", &flag_race)
	obj.Flagcount("s", "disable symbol table", &Debug['s'])
	if Thearch.Thechar == '5' || Thearch.Thechar == '6' {
		obj.Flagcount("shared", "generate shared object (implies -linkmode external)", &Flag_shared)
	}
	obj.Flagstr("tmpdir", "dir: leave temporary files in this directory", &tmpdir)
	obj.Flagcount("u", "reject unsafe packages", &Debug['u'])
	obj.Flagcount("v", "print link trace", &Debug['v'])
	obj.Flagcount("w", "disable DWARF generation", &Debug['w'])

	// Clumsy hack to preserve old behavior of -X taking two arguments.
	for i := 0; i < len(os.Args); i++ {
		arg := os.Args[i]
		if (arg == "--X" || arg == "-X") && i+2 < len(os.Args) {
			os.Args[i+2] = "-X=VALUE:" + os.Args[i+2]
			i += 2
		} else if (strings.HasPrefix(arg, "--X=") || strings.HasPrefix(arg, "-X=")) && i+1 < len(os.Args) {
			os.Args[i+1] = "-X=VALUE:" + os.Args[i+1]
			i++
		}
	}
	obj.Flagstr("cpuprofile", "file: write cpu profile to file", &cpuprofile)
	obj.Flagstr("memprofile", "file: write memory profile to file", &memprofile)
	obj.Flagparse(usage)
	startProfile()
	Ctxt.Bso = &Bso
	Ctxt.Debugvlog = int32(Debug['v'])

	if flag.NArg() != 1 {
		usage()
	}

	if outfile == "" {
		if HEADTYPE == Hwindows {
			outfile = fmt.Sprintf("%c.out.exe", Thearch.Thechar)
		} else {
			outfile = fmt.Sprintf("%c.out", Thearch.Thechar)
		}
	}

	libinit() // creates outfile

	if HEADTYPE == -1 {
		HEADTYPE = int32(headtype(goos))
	}
	Ctxt.Headtype = int(HEADTYPE)
	if headstring == "" {
		headstring = Headstr(int(HEADTYPE))
	}

	Thearch.Archinit()

	if Debug['v'] != 0 {
		fmt.Fprintf(&Bso, "HEADER = -H%d -T0x%x -D0x%x -R0x%x\n", HEADTYPE, uint64(INITTEXT), uint64(INITDAT), uint32(INITRND))
	}
	Bflush(&Bso)

	addlibpath(Ctxt, "command line", "command line", flag.Arg(0), "main")
	loadlib()

	if Thearch.Thechar == '5' {
		// mark some functions that are only referenced after linker code editing
		if Debug['F'] != 0 {
			mark(Linkrlookup(Ctxt, "_sfloat", 0))
		}
		mark(Linklookup(Ctxt, "runtime.read_tls_fallback", 0))
	}

	checkgo()
	deadcode()
	callgraph()

	doelf()
	if HEADTYPE == Hdarwin {
		domacho()
	}
	dostkcheck()
	if HEADTYPE == Hwindows {
		dope()
	}
	addexport()
	Thearch.Gentext() // trampolines, call stubs, etc.
	textaddress()
	pclntab()
	findfunctab()
	symtab()
	dodata()
	address()
	doweak()
	reloc()
	Thearch.Asmb()
	undef()
	hostlink()
	if Debug['v'] != 0 {
		fmt.Fprintf(&Bso, "%5.2f cpu time\n", obj.Cputime())
		fmt.Fprintf(&Bso, "%d symbols\n", Ctxt.Nsymbol)
		fmt.Fprintf(&Bso, "%d liveness data\n", liveness)
	}

	Bflush(&Bso)

	Errorexit()
}
Example #8
0
func Ldmain() {
	Ctxt = linknew(Thelinkarch)
	Ctxt.Thechar = int32(Thearch.Thechar)
	Ctxt.Thestring = Thestring
	Ctxt.Diag = Diag
	Ctxt.Bso = &Bso

	Bso = *obj.Binitw(os.Stdout)
	Debug = [128]int{}
	nerrors = 0
	outfile = ""
	HEADTYPE = -1
	INITTEXT = -1
	INITDAT = -1
	INITRND = -1
	INITENTRY = ""
	Linkmode = LinkAuto

	// For testing behavior of go command when tools crash.
	// Undocumented, not in standard flag parser to avoid
	// exposing in usage message.
	for _, arg := range os.Args {
		if arg == "-crash_for_testing" {
			*(*int)(nil) = 0
		}
	}

	if Thearch.Thechar == '5' && Ctxt.Goarm == 5 {
		Debug['F'] = 1
	}

	obj.Flagcount("1", "use alternate profiling code", &Debug['1'])
	if Thearch.Thechar == '6' {
		obj.Flagcount("8", "assume 64-bit addresses", &Debug['8'])
	}
	obj.Flagfn1("B", "add an ELF NT_GNU_BUILD_ID `note` when using ELF", addbuildinfo)
	obj.Flagcount("C", "check Go calls to C code", &Debug['C'])
	obj.Flagint64("D", "set data segment `address`", &INITDAT)
	obj.Flagstr("E", "set `entry` symbol name", &INITENTRY)
	if Thearch.Thechar == '5' {
		obj.Flagcount("G", "debug pseudo-ops", &Debug['G'])
	}
	obj.Flagfn1("I", "use `linker` as ELF dynamic linker", setinterp)
	obj.Flagfn1("L", "add specified `directory` to library path", Lflag)
	obj.Flagfn1("H", "set header `type`", setheadtype)
	obj.Flagcount("K", "add stack underflow checks", &Debug['K'])
	if Thearch.Thechar == '5' {
		obj.Flagcount("M", "disable software div/mod", &Debug['M'])
	}
	obj.Flagcount("O", "print pc-line tables", &Debug['O'])
	obj.Flagcount("Q", "debug byte-register code gen", &Debug['Q'])
	if Thearch.Thechar == '5' {
		obj.Flagcount("P", "debug code generation", &Debug['P'])
	}
	obj.Flagint32("R", "set address rounding `quantum`", &INITRND)
	obj.Flagcount("nil", "check type signatures", &Debug['S'])
	obj.Flagint64("T", "set text segment `address`", &INITTEXT)
	obj.Flagfn0("V", "print version and exit", doversion)
	obj.Flagcount("W", "disassemble input", &Debug['W'])
	obj.Flagfn1("X", "set the value of a string variable; the next two arguments are its name and value", addstrdata1)
	obj.Flagcount("Z", "clear stack frame on entry", &Debug['Z'])
	obj.Flagcount("a", "disassemble output", &Debug['a'])
	flag.Var(&Buildmode, "buildmode", "set build `mode`")
	obj.Flagcount("c", "dump call graph", &Debug['c'])
	obj.Flagcount("d", "disable dynamic executable", &Debug['d'])
	obj.Flagstr("extld", "use `linker` when linking in external mode", &extld)
	obj.Flagstr("extldflags", "pass `flags` to external linker", &extldflags)
	obj.Flagcount("f", "ignore version mismatch", &Debug['f'])
	obj.Flagcount("g", "disable go package data checks", &Debug['g'])
	obj.Flagstr("installsuffix", "set package directory `suffix`", &flag_installsuffix)
	obj.Flagstr("k", "set field tracking `symbol`", &tracksym)
	obj.Flagfn1("linkmode", "set link `mode` (internal, external, auto)", setlinkmode)
	flag.BoolVar(&Linkshared, "linkshared", false, "link against installed Go shared libraries")
	obj.Flagcount("n", "dump symbol table", &Debug['n'])
	obj.Flagstr("o", "write output to `file`", &outfile)
	flag.Var(&rpath, "r", "set the ELF dynamic linker search `path` to dir1:dir2:...")
	obj.Flagcount("race", "enable race detector", &flag_race)
	obj.Flagcount("s", "disable symbol table", &Debug['s'])
	var flagShared int
	if Thearch.Thechar == '5' || Thearch.Thechar == '6' {
		obj.Flagcount("shared", "generate shared object (implies -linkmode external)", &flagShared)
	}
	obj.Flagstr("tmpdir", "use `directory` for temporary files", &tmpdir)
	obj.Flagcount("u", "reject unsafe packages", &Debug['u'])
	obj.Flagcount("v", "print link trace", &Debug['v'])
	obj.Flagcount("w", "disable DWARF generation", &Debug['w'])

	// Clumsy hack to preserve old behavior of -X taking two arguments.
	for i := 0; i < len(os.Args); i++ {
		arg := os.Args[i]
		if (arg == "--X" || arg == "-X") && i+2 < len(os.Args) {
			os.Args[i+2] = "-X=VALUE:" + os.Args[i+2]
			i += 2
		} else if (strings.HasPrefix(arg, "--X=") || strings.HasPrefix(arg, "-X=")) && i+1 < len(os.Args) {
			os.Args[i+1] = "-X=VALUE:" + os.Args[i+1]
			i++
		}
	}
	obj.Flagstr("cpuprofile", "write cpu profile to `file`", &cpuprofile)
	obj.Flagstr("memprofile", "write memory profile to `file`", &memprofile)
	obj.Flagint64("memprofilerate", "set runtime.MemProfileRate to `rate`", &memprofilerate)
	obj.Flagparse(usage)
	startProfile()
	Ctxt.Bso = &Bso
	Ctxt.Debugvlog = int32(Debug['v'])
	if flagShared != 0 {
		if Buildmode == BuildmodeExe {
			Buildmode = BuildmodeCShared
		} else if Buildmode != BuildmodeCShared {
			Exitf("-shared and -buildmode=%s are incompatible", Buildmode.String())
		}
	}

	if Buildmode != BuildmodeShared && flag.NArg() != 1 {
		usage()
	}

	if outfile == "" {
		if HEADTYPE == obj.Hwindows {
			outfile = fmt.Sprintf("%c.out.exe", Thearch.Thechar)
		} else {
			outfile = fmt.Sprintf("%c.out", Thearch.Thechar)
		}
	}

	libinit() // creates outfile

	if HEADTYPE == -1 {
		HEADTYPE = int32(headtype(goos))
	}
	Ctxt.Headtype = int(HEADTYPE)
	if headstring == "" {
		headstring = Headstr(int(HEADTYPE))
	}

	Thearch.Archinit()

	if Linkshared && !Iself {
		Exitf("-linkshared can only be used on elf systems")
	}

	if Debug['v'] != 0 {
		fmt.Fprintf(&Bso, "HEADER = -H%d -T0x%x -D0x%x -R0x%x\n", HEADTYPE, uint64(INITTEXT), uint64(INITDAT), uint32(INITRND))
	}
	Bso.Flush()

	if Buildmode == BuildmodeShared {
		for i := 0; i < flag.NArg(); i++ {
			arg := flag.Arg(i)
			parts := strings.SplitN(arg, "=", 2)
			var pkgpath, file string
			if len(parts) == 1 {
				pkgpath, file = "main", arg
			} else {
				pkgpath, file = parts[0], parts[1]
			}
			pkglistfornote = append(pkglistfornote, pkgpath...)
			pkglistfornote = append(pkglistfornote, '\n')
			addlibpath(Ctxt, "command line", "command line", file, pkgpath, "")
		}
	} else {
		addlibpath(Ctxt, "command line", "command line", flag.Arg(0), "main", "")
	}
	loadlib()

	if Thearch.Thechar == '5' {
		// mark some functions that are only referenced after linker code editing
		if Debug['F'] != 0 {
			mark(Linkrlookup(Ctxt, "_sfloat", 0))
		}
		mark(Linklookup(Ctxt, "runtime.read_tls_fallback", 0))
	}

	checkgo()
	deadcode()
	callgraph()

	doelf()
	if HEADTYPE == obj.Hdarwin {
		domacho()
	}
	dostkcheck()
	if HEADTYPE == obj.Hwindows {
		dope()
	}
	addexport()
	Thearch.Gentext() // trampolines, call stubs, etc.
	textaddress()
	pclntab()
	findfunctab()
	symtab()
	dodata()
	address()
	doweak()
	reloc()
	Thearch.Asmb()
	undef()
	hostlink()
	archive()
	if Debug['v'] != 0 {
		fmt.Fprintf(&Bso, "%5.2f cpu time\n", obj.Cputime())
		fmt.Fprintf(&Bso, "%d symbols\n", Ctxt.Nsymbol)
		fmt.Fprintf(&Bso, "%d liveness data\n", liveness)
	}

	Bso.Flush()

	errorexit()
}
Example #9
0
File: pobj.go Project: 2thetop/go
func Ldmain() {
	Bso = bufio.NewWriter(os.Stdout)

	Ctxt = linknew(SysArch)
	Ctxt.Diag = Diag
	Ctxt.Bso = Bso

	Debug = [128]int{}
	nerrors = 0
	outfile = ""
	HEADTYPE = -1
	INITTEXT = -1
	INITDAT = -1
	INITRND = -1
	INITENTRY = ""
	Linkmode = LinkAuto

	// For testing behavior of go command when tools crash silently.
	// Undocumented, not in standard flag parser to avoid
	// exposing in usage message.
	for _, arg := range os.Args {
		if arg == "-crash_for_testing" {
			os.Exit(2)
		}
	}

	if SysArch.Family == sys.AMD64 && obj.Getgoos() == "plan9" {
		obj.Flagcount("8", "use 64-bit addresses in symbol table", &Debug['8'])
	}
	obj.Flagfn1("B", "add an ELF NT_GNU_BUILD_ID `note` when using ELF", addbuildinfo)
	obj.Flagcount("C", "check Go calls to C code", &Debug['C'])
	obj.Flagint64("D", "set data segment `address`", &INITDAT)
	obj.Flagstr("E", "set `entry` symbol name", &INITENTRY)
	obj.Flagfn1("I", "use `linker` as ELF dynamic linker", setinterp)
	obj.Flagfn1("L", "add specified `directory` to library path", Lflag)
	obj.Flagfn1("H", "set header `type`", setheadtype)
	obj.Flagint32("R", "set address rounding `quantum`", &INITRND)
	obj.Flagint64("T", "set text segment `address`", &INITTEXT)
	obj.Flagfn0("V", "print version and exit", doversion)
	obj.Flagfn1("X", "add string value `definition` of the form importpath.name=value", addstrdata1)
	obj.Flagcount("a", "disassemble output", &Debug['a'])
	obj.Flagstr("buildid", "record `id` as Go toolchain build id", &buildid)
	flag.Var(&Buildmode, "buildmode", "set build `mode`")
	obj.Flagcount("c", "dump call graph", &Debug['c'])
	obj.Flagcount("d", "disable dynamic executable", &Debug['d'])
	flag.BoolVar(&flag_dumpdep, "dumpdep", false, "dump symbol dependency graph")
	obj.Flagstr("extar", "archive program for buildmode=c-archive", &extar)
	obj.Flagstr("extld", "use `linker` when linking in external mode", &extld)
	obj.Flagstr("extldflags", "pass `flags` to external linker", &extldflags)
	obj.Flagcount("f", "ignore version mismatch", &Debug['f'])
	obj.Flagcount("g", "disable go package data checks", &Debug['g'])
	obj.Flagcount("h", "halt on error", &Debug['h'])
	obj.Flagstr("installsuffix", "set package directory `suffix`", &flag_installsuffix)
	obj.Flagstr("k", "set field tracking `symbol`", &tracksym)
	obj.Flagstr("libgcc", "compiler support lib for internal linking; use \"none\" to disable", &libgccfile)
	obj.Flagfn1("linkmode", "set link `mode` (internal, external, auto)", setlinkmode)
	flag.BoolVar(&Linkshared, "linkshared", false, "link against installed Go shared libraries")
	obj.Flagcount("msan", "enable MSan interface", &flag_msan)
	obj.Flagcount("n", "dump symbol table", &Debug['n'])
	obj.Flagstr("o", "write output to `file`", &outfile)
	flag.Var(&rpath, "r", "set the ELF dynamic linker search `path` to dir1:dir2:...")
	obj.Flagcount("race", "enable race detector", &flag_race)
	obj.Flagcount("s", "disable symbol table", &Debug['s'])
	var flagShared int
	if SysArch.InFamily(sys.ARM, sys.AMD64) {
		obj.Flagcount("shared", "generate shared object (implies -linkmode external)", &flagShared)
	}
	obj.Flagstr("tmpdir", "use `directory` for temporary files", &tmpdir)
	obj.Flagcount("u", "reject unsafe packages", &Debug['u'])
	obj.Flagcount("v", "print link trace", &Debug['v'])
	obj.Flagcount("w", "disable DWARF generation", &Debug['w'])

	obj.Flagstr("cpuprofile", "write cpu profile to `file`", &cpuprofile)
	obj.Flagstr("memprofile", "write memory profile to `file`", &memprofile)
	obj.Flagint64("memprofilerate", "set runtime.MemProfileRate to `rate`", &memprofilerate)

	obj.Flagparse(usage)

	startProfile()
	Ctxt.Bso = Bso
	Ctxt.Debugvlog = int32(Debug['v'])
	if flagShared != 0 {
		if Buildmode == BuildmodeUnset {
			Buildmode = BuildmodeCShared
		} else if Buildmode != BuildmodeCShared {
			Exitf("-shared and -buildmode=%s are incompatible", Buildmode.String())
		}
	}
	if Buildmode == BuildmodeUnset {
		Buildmode = BuildmodeExe
	}

	if Buildmode != BuildmodeShared && flag.NArg() != 1 {
		usage()
	}

	if outfile == "" {
		outfile = "a.out"
		if HEADTYPE == obj.Hwindows {
			outfile += ".exe"
		}
	}

	libinit() // creates outfile

	if HEADTYPE == -1 {
		HEADTYPE = int32(headtype(goos))
	}
	Ctxt.Headtype = int(HEADTYPE)
	if headstring == "" {
		headstring = Headstr(int(HEADTYPE))
	}

	Thearch.Archinit()

	if Linkshared && !Iself {
		Exitf("-linkshared can only be used on elf systems")
	}

	if Debug['v'] != 0 {
		fmt.Fprintf(Bso, "HEADER = -H%d -T0x%x -D0x%x -R0x%x\n", HEADTYPE, uint64(INITTEXT), uint64(INITDAT), uint32(INITRND))
	}
	Bso.Flush()

	if Buildmode == BuildmodeShared {
		for i := 0; i < flag.NArg(); i++ {
			arg := flag.Arg(i)
			parts := strings.SplitN(arg, "=", 2)
			var pkgpath, file string
			if len(parts) == 1 {
				pkgpath, file = "main", arg
			} else {
				pkgpath, file = parts[0], parts[1]
			}
			pkglistfornote = append(pkglistfornote, pkgpath...)
			pkglistfornote = append(pkglistfornote, '\n')
			addlibpath(Ctxt, "command line", "command line", file, pkgpath, "")
		}
	} else {
		addlibpath(Ctxt, "command line", "command line", flag.Arg(0), "main", "")
	}
	loadlib()

	checkstrdata()
	deadcode(Ctxt)
	fieldtrack(Ctxt)
	callgraph()

	doelf()
	if HEADTYPE == obj.Hdarwin {
		domacho()
	}
	dostkcheck()
	if HEADTYPE == obj.Hwindows {
		dope()
	}
	addexport()
	Thearch.Gentext() // trampolines, call stubs, etc.
	textbuildid()
	textaddress()
	pclntab()
	findfunctab()
	symtab()
	dodata()
	address()
	reloc()
	Thearch.Asmb()
	undef()
	hostlink()
	archive()
	if Debug['v'] != 0 {
		fmt.Fprintf(Bso, "%5.2f cpu time\n", obj.Cputime())
		fmt.Fprintf(Bso, "%d symbols\n", len(Ctxt.Allsym))
		fmt.Fprintf(Bso, "%d liveness data\n", liveness)
	}

	Bso.Flush()

	errorexit()
}