go/src/cmd/compile/internal/gc/main.go
Russ Cox d99dd17827 [dev.typeparams] all: merge dev.regabi (37f138d) into dev.typeparams
Conflicts:

* src/cmd/compile/fmtmap_test.go
* src/cmd/compile/internal/gc/go.go
* src/cmd/compile/internal/gc/main.go
* src/cmd/compile/internal/noder/noder.go

Merge List:

* 2020-12-23 37f138df6b [dev.regabi] cmd/compile: split out package test [generated]
* 2020-12-23 3d8a3cb06b [dev.regabi] cmd/compile: split out package pkginit [generated]
* 2020-12-23 3f04d964ab [dev.regabi] cmd/compile: split up walkexpr1, walkstmt [generated]
* 2020-12-23 e4895ab4c0 [dev.regabi] cmd/compile: split out package walk [generated]
* 2020-12-23 01fd2d05c8 [dev.regabi] cmd/compile: split out package dwarfgen [generated]
* 2020-12-23 6c34d2f420 [dev.regabi] cmd/compile: split out package ssagen [generated]
* 2020-12-23 de65151e50 [dev.regabi] cmd/compile: split out package reflectdata [generated]
* 2020-12-23 4dfb5d91a8 [dev.regabi] cmd/compile: split out package staticdata [generated]
* 2020-12-23 fbc82f03b1 [dev.regabi] cmd/compile: split out package noder [generated]
* 2020-12-23 de454eef5f [dev.regabi] cmd/compile: split out package escape [generated]
* 2020-12-23 071ab0a14c [dev.regabi] cmd/compile: split out package liveness [generated]
* 2020-12-23 0ced54062e [dev.regabi] cmd/compile: split out package objw [generated]
* 2020-12-23 575fd6ff0a [dev.regabi] cmd/compile: split out package inline [generated]
* 2020-12-23 0256ba99a8 [dev.regabi] cmd/compile: split up typecheck1 [generated]
* 2020-12-23 b9693d7627 [dev.regabi] cmd/compile: split out package typecheck [generated]
* 2020-12-23 dac0de3748 [dev.regabi] cmd/compile: move type size calculations into package types [generated]
* 2020-12-23 527a1895d6 [dev.regabi] cmd/compile: move helpers into package ir [generated]
* 2020-12-23 65c4c6dfb2 [dev.regabi] cmd/compile: group known symbols, packages, names [generated]
* 2020-12-23 9ee309255a [dev.regabi] cmd/compile: move helpers into package types [generated]
* 2020-12-23 ead4957892 [dev.regabi] cmd/compile: move helpers into package base [generated]
* 2020-12-23 440308ffd7 [dev.regabi] cmd/compile: simplify Nodes usage [generated]
* 2020-12-23 f9d373720e [dev.regabi] cmd/compile: remove Left, Right etc methods [generated]
* 2020-12-23 14d667341f [dev.regabi] cmd/compile: remove Node.Left etc [generated]
* 2020-12-23 6f27d29be0 [dev.regabi] cmd/compile: remove ir.Nod [generated]
* 2020-12-23 69cf39089f [dev.regabi] cmd/compile: do not die in early base.FlushErrors

Change-Id: Ic4686e77c6ee38b3cd7d37fc7f3e93aaa9017b7a
2020-12-23 01:43:22 -05:00

378 lines
11 KiB
Go

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:generate go run mkbuiltin.go
package gc
import (
"bufio"
"bytes"
"cmd/compile/internal/base"
"cmd/compile/internal/dwarfgen"
"cmd/compile/internal/escape"
"cmd/compile/internal/inline"
"cmd/compile/internal/ir"
"cmd/compile/internal/logopt"
"cmd/compile/internal/noder"
"cmd/compile/internal/pkginit"
"cmd/compile/internal/reflectdata"
"cmd/compile/internal/ssa"
"cmd/compile/internal/ssagen"
"cmd/compile/internal/staticdata"
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
"cmd/compile/internal/walk"
"cmd/internal/dwarf"
"cmd/internal/obj"
"cmd/internal/objabi"
"cmd/internal/src"
"flag"
"fmt"
"log"
"os"
"runtime"
)
func hidePanic() {
if base.Debug.Panic == 0 && base.Errors() > 0 {
// If we've already complained about things
// in the program, don't bother complaining
// about a panic too; let the user clean up
// the code and try again.
if err := recover(); err != nil {
if err == "-h" {
panic(err)
}
base.ErrorExit()
}
}
}
// Main parses flags and Go source files specified in the command-line
// arguments, type-checks the parsed Go package, compiles functions to machine
// code, and finally writes the compiled package definition to disk.
func Main(archInit func(*ssagen.ArchInfo)) {
base.Timer.Start("fe", "init")
defer hidePanic()
archInit(&ssagen.Arch)
base.Ctxt = obj.Linknew(ssagen.Arch.LinkArch)
base.Ctxt.DiagFunc = base.Errorf
base.Ctxt.DiagFlush = base.FlushErrors
base.Ctxt.Bso = bufio.NewWriter(os.Stdout)
// UseBASEntries is preferred because it shaves about 2% off build time, but LLDB, dsymutil, and dwarfdump
// on Darwin don't support it properly, especially since macOS 10.14 (Mojave). This is exposed as a flag
// to allow testing with LLVM tools on Linux, and to help with reporting this bug to the LLVM project.
// See bugs 31188 and 21945 (CLs 170638, 98075, 72371).
base.Ctxt.UseBASEntries = base.Ctxt.Headtype != objabi.Hdarwin
types.LocalPkg = types.NewPkg("", "")
types.LocalPkg.Prefix = "\"\""
// We won't know localpkg's height until after import
// processing. In the mean time, set to MaxPkgHeight to ensure
// height comparisons at least work until then.
types.LocalPkg.Height = types.MaxPkgHeight
// pseudo-package, for scoping
types.BuiltinPkg = types.NewPkg("go.builtin", "") // TODO(gri) name this package go.builtin?
types.BuiltinPkg.Prefix = "go.builtin" // not go%2ebuiltin
// pseudo-package, accessed by import "unsafe"
ir.Pkgs.Unsafe = types.NewPkg("unsafe", "unsafe")
// Pseudo-package that contains the compiler's builtin
// declarations for package runtime. These are declared in a
// separate package to avoid conflicts with package runtime's
// actual declarations, which may differ intentionally but
// insignificantly.
ir.Pkgs.Runtime = types.NewPkg("go.runtime", "runtime")
ir.Pkgs.Runtime.Prefix = "runtime"
// pseudo-packages used in symbol tables
ir.Pkgs.Itab = types.NewPkg("go.itab", "go.itab")
ir.Pkgs.Itab.Prefix = "go.itab" // not go%2eitab
ir.Pkgs.Itablink = types.NewPkg("go.itablink", "go.itablink")
ir.Pkgs.Itablink.Prefix = "go.itablink" // not go%2eitablink
ir.Pkgs.Track = types.NewPkg("go.track", "go.track")
ir.Pkgs.Track.Prefix = "go.track" // not go%2etrack
// pseudo-package used for map zero values
ir.Pkgs.Map = types.NewPkg("go.map", "go.map")
ir.Pkgs.Map.Prefix = "go.map"
// pseudo-package used for methods with anonymous receivers
ir.Pkgs.Go = types.NewPkg("go", "")
base.DebugSSA = ssa.PhaseOption
base.ParseFlags()
// Record flags that affect the build result. (And don't
// record flags that don't, since that would cause spurious
// changes in the binary.)
dwarfgen.RecordFlags("B", "N", "l", "msan", "race", "shared", "dynlink", "dwarflocationlists", "dwarfbasentries", "smallframes", "spectre")
if !base.EnableTrace && base.Flag.LowerT {
log.Fatalf("compiler not built with support for -t")
}
// Enable inlining (after recordFlags, to avoid recording the rewritten -l). For now:
// default: inlining on. (Flag.LowerL == 1)
// -l: inlining off (Flag.LowerL == 0)
// -l=2, -l=3: inlining on again, with extra debugging (Flag.LowerL > 1)
if base.Flag.LowerL <= 1 {
base.Flag.LowerL = 1 - base.Flag.LowerL
}
if base.Flag.SmallFrames {
ir.MaxStackVarSize = 128 * 1024
ir.MaxImplicitStackVarSize = 16 * 1024
}
if base.Flag.Dwarf {
base.Ctxt.DebugInfo = dwarfgen.Info
base.Ctxt.GenAbstractFunc = dwarfgen.AbstractFunc
base.Ctxt.DwFixups = obj.NewDwarfFixupTable(base.Ctxt)
} else {
// turn off inline generation if no dwarf at all
base.Flag.GenDwarfInl = 0
base.Ctxt.Flag_locationlists = false
}
if base.Ctxt.Flag_locationlists && len(base.Ctxt.Arch.DWARFRegisters) == 0 {
log.Fatalf("location lists requested but register mapping not available on %v", base.Ctxt.Arch.Name)
}
types.ParseLangFlag()
if base.Flag.SymABIs != "" {
ssagen.ReadSymABIs(base.Flag.SymABIs, base.Ctxt.Pkgpath)
}
if base.Compiling(base.NoInstrumentPkgs) {
base.Flag.Race = false
base.Flag.MSan = false
}
ssagen.Arch.LinkArch.Init(base.Ctxt)
startProfile()
if base.Flag.Race {
ir.Pkgs.Race = types.NewPkg("runtime/race", "")
}
if base.Flag.MSan {
ir.Pkgs.Msan = types.NewPkg("runtime/msan", "")
}
if base.Flag.Race || base.Flag.MSan {
base.Flag.Cfg.Instrumenting = true
}
if base.Flag.Dwarf {
dwarf.EnableLogging(base.Debug.DwarfInl != 0)
}
if base.Debug.SoftFloat != 0 {
ssagen.Arch.SoftFloat = true
}
if base.Flag.JSON != "" { // parse version,destination from json logging optimization.
logopt.LogJsonOption(base.Flag.JSON)
}
ir.EscFmt = escape.Fmt
ir.IsIntrinsicCall = ssagen.IsIntrinsicCall
inline.SSADumpInline = ssagen.DumpInline
ssagen.InitEnv()
ssagen.InitTables()
types.PtrSize = ssagen.Arch.LinkArch.PtrSize
types.RegSize = ssagen.Arch.LinkArch.RegSize
types.MaxWidth = ssagen.Arch.MAXWIDTH
types.TypeLinkSym = func(t *types.Type) *obj.LSym {
return reflectdata.TypeSym(t).Linksym()
}
typecheck.Target = new(ir.Package)
typecheck.NeedFuncSym = staticdata.NeedFuncSym
typecheck.NeedITab = func(t, iface *types.Type) { reflectdata.ITabAddr(t, iface) }
typecheck.NeedRuntimeType = reflectdata.NeedRuntimeType // TODO(rsc): typenamesym for lock?
base.AutogeneratedPos = makePos(src.NewFileBase("<autogenerated>", "<autogenerated>"), 1, 0)
types.TypeLinkSym = func(t *types.Type) *obj.LSym {
return reflectdata.TypeSym(t).Linksym()
}
typecheck.Init()
// Parse input.
base.Timer.Start("fe", "parse")
lines := noder.ParseFiles(flag.Args())
ssagen.CgoSymABIs()
base.Timer.Stop()
base.Timer.AddEvent(int64(lines), "lines")
if base.Flag.G != 0 && base.Flag.G < 3 {
// can only parse generic code for now
base.ExitIfErrors()
return
}
dwarfgen.RecordPackageName()
// Typecheck.
typecheck.Package()
// With all user code typechecked, it's now safe to verify unused dot imports.
noder.CheckDotImports()
base.ExitIfErrors()
// Build init task.
if initTask := pkginit.Task(); initTask != nil {
typecheck.Export(initTask)
}
// Inlining
base.Timer.Start("fe", "inlining")
if base.Flag.LowerL != 0 {
inline.InlinePackage()
}
// Devirtualize.
for _, n := range typecheck.Target.Decls {
if n.Op() == ir.ODCLFUNC {
inline.Devirtualize(n.(*ir.Func))
}
}
ir.CurFunc = nil
// 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.
base.Timer.Start("fe", "escapes")
escape.Funcs(typecheck.Target.Decls)
// Collect information for go:nowritebarrierrec
// checking. This must happen before transformclosure.
// We'll do the final check after write barriers are
// inserted.
if base.Flag.CompilingRuntime {
ssagen.EnableNoWriteBarrierRecCheck()
}
// 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.
base.Timer.Start("fe", "xclosures")
for _, n := range typecheck.Target.Decls {
if n.Op() == ir.ODCLFUNC {
n := n.(*ir.Func)
if n.OClosure != nil {
ir.CurFunc = n
walk.Closure(n)
}
}
}
// Prepare for SSA compilation.
// This must be before peekitabs, because peekitabs
// can trigger function compilation.
ssagen.InitConfig()
// Just before compilation, compile itabs found on
// the right side of OCONVIFACE so that methods
// can be de-virtualized during compilation.
ir.CurFunc = nil
reflectdata.CompileITabs()
// Compile top level functions.
// Don't use range--walk can add functions to Target.Decls.
base.Timer.Start("be", "compilefuncs")
fcount := int64(0)
for i := 0; i < len(typecheck.Target.Decls); i++ {
n := typecheck.Target.Decls[i]
if n.Op() == ir.ODCLFUNC {
funccompile(n.(*ir.Func))
fcount++
}
}
base.Timer.AddEvent(fcount, "funcs")
compileFunctions()
if base.Flag.CompilingRuntime {
// Write barriers are now known. Check the call graph.
ssagen.NoWriteBarrierRecCheck()
}
// Finalize DWARF inline routine DIEs, then explicitly turn off
// DWARF inlining gen so as to avoid problems with generated
// method wrappers.
if base.Ctxt.DwFixups != nil {
base.Ctxt.DwFixups.Finalize(base.Ctxt.Pkgpath, base.Debug.DwarfInl != 0)
base.Ctxt.DwFixups = nil
base.Flag.GenDwarfInl = 0
}
// Write object data to disk.
base.Timer.Start("be", "dumpobj")
dumpdata()
base.Ctxt.NumberSyms()
dumpobj()
if base.Flag.AsmHdr != "" {
dumpasmhdr()
}
ssagen.CheckLargeStacks()
typecheck.CheckFuncStack()
if len(compilequeue) != 0 {
base.Fatalf("%d uncompiled functions", len(compilequeue))
}
logopt.FlushLoggedOpts(base.Ctxt, base.Ctxt.Pkgpath)
base.ExitIfErrors()
base.FlushErrors()
base.Timer.Stop()
if base.Flag.Bench != "" {
if err := writebench(base.Flag.Bench); err != nil {
log.Fatalf("cannot write benchmark data: %v", err)
}
}
}
func writebench(filename string) error {
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
return err
}
var buf bytes.Buffer
fmt.Fprintln(&buf, "commit:", objabi.Version)
fmt.Fprintln(&buf, "goos:", runtime.GOOS)
fmt.Fprintln(&buf, "goarch:", runtime.GOARCH)
base.Timer.Write(&buf, "BenchmarkCompile:"+base.Ctxt.Pkgpath+":")
n, err := f.Write(buf.Bytes())
if err != nil {
return err
}
if n != buf.Len() {
panic("bad writer")
}
return f.Close()
}
func makePos(b *src.PosBase, line, col uint) src.XPos {
return base.Ctxt.PosTable.XPos(src.MakePos(b, line, col))
}