[dev.regabi] cmd/compile: collect global compilation state

There are various global variables tracking the state of the
compilation. Collect them in a single global struct instead.
The struct definition is in package ir, but the struct itself is
still in package gc. It may eventually be threaded through the
code, but in the short term will end up in package typecheck.

Change-Id: I019db07aaedaed2c9b67dd45a4e138dc6028e54c
Reviewed-on: https://go-review.googlesource.com/c/go/+/279297
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Russ Cox 2020-12-21 01:29:02 -05:00
parent 2153a99914
commit 1a3b036b83
18 changed files with 116 additions and 96 deletions

View File

@ -394,7 +394,7 @@ func genhash(t *types.Type) *obj.LSym {
} }
fn.SetNilCheckDisabled(true) fn.SetNilCheckDisabled(true)
xtop = append(xtop, fn) Target.Decls = append(Target.Decls, fn)
// Build closure. It doesn't close over any variables, so // Build closure. It doesn't close over any variables, so
// it contains just the function pointer. // it contains just the function pointer.
@ -774,7 +774,7 @@ func geneq(t *types.Type) *obj.LSym {
// neither of which can be nil, and our comparisons // neither of which can be nil, and our comparisons
// are shallow. // are shallow.
fn.SetNilCheckDisabled(true) fn.SetNilCheckDisabled(true)
xtop = append(xtop, fn) Target.Decls = append(Target.Decls, fn)
// Generate a closure which points at the function we just generated. // Generate a closure which points at the function we just generated.
dsymptr(closure, 0, sym.Linksym(), 0) dsymptr(closure, 0, sym.Linksym(), 0)

View File

@ -18,7 +18,7 @@ func (p *exporter) markObject(n ir.Node) {
if n.Op() == ir.ONAME { if n.Op() == ir.ONAME {
n := n.(*ir.Name) n := n.(*ir.Name)
if n.Class() == ir.PFUNC { if n.Class() == ir.PFUNC {
inlFlood(n) inlFlood(n, exportsym)
} }
} }

View File

@ -89,7 +89,7 @@ func typecheckclosure(clo ir.Node, top int) {
fn.SetClosureCalled(top&ctxCallee != 0) fn.SetClosureCalled(top&ctxCallee != 0)
// Do not typecheck fn twice, otherwise, we will end up pushing // Do not typecheck fn twice, otherwise, we will end up pushing
// fn to xtop multiple times, causing initLSym called twice. // fn to Target.Decls multiple times, causing initLSym called twice.
// See #30709 // See #30709
if fn.Typecheck() == 1 { if fn.Typecheck() == 1 {
return return
@ -118,7 +118,7 @@ func typecheckclosure(clo ir.Node, top int) {
// Type check the body now, but only if we're inside a function. // Type check the body now, but only if we're inside a function.
// At top level (in a variable initialization: curfn==nil) we're not // At top level (in a variable initialization: curfn==nil) we're not
// ready to type check code yet; we'll check it later, because the // ready to type check code yet; we'll check it later, because the
// underlying closure function we create is added to xtop. // underlying closure function we create is added to Target.Decls.
if Curfn != nil && clo.Type() != nil { if Curfn != nil && clo.Type() != nil {
oldfn := Curfn oldfn := Curfn
Curfn = fn Curfn = fn
@ -129,7 +129,7 @@ func typecheckclosure(clo ir.Node, top int) {
Curfn = oldfn Curfn = oldfn
} }
xtop = append(xtop, fn) Target.Decls = append(Target.Decls, fn)
} }
// globClosgen is like Func.Closgen, but for the global scope. // globClosgen is like Func.Closgen, but for the global scope.
@ -499,7 +499,7 @@ func makepartialcall(dot *ir.SelectorExpr, t0 *types.Type, meth *types.Sym) *ir.
Curfn = fn Curfn = fn
typecheckslice(fn.Body().Slice(), ctxStmt) typecheckslice(fn.Body().Slice(), ctxStmt)
sym.Def = fn sym.Def = fn
xtop = append(xtop, fn) Target.Decls = append(Target.Decls, fn)
Curfn = savecurfn Curfn = savecurfn
base.Pos = saveLineNo base.Pos = saveLineNo

View File

@ -17,8 +17,6 @@ import (
// Declaration stack & operations // Declaration stack & operations
var externdcl []ir.Node
func testdclstack() { func testdclstack() {
if !types.IsDclstackValid() { if !types.IsDclstackValid() {
base.Fatalf("mark left on the dclstack") base.Fatalf("mark left on the dclstack")
@ -75,7 +73,7 @@ func declare(n *ir.Name, ctxt ir.Class) {
if s.Name == "main" && s.Pkg.Name == "main" { if s.Name == "main" && s.Pkg.Name == "main" {
base.ErrorfAt(n.Pos(), "cannot declare main - must be func") base.ErrorfAt(n.Pos(), "cannot declare main - must be func")
} }
externdcl = append(externdcl, n) Target.Externs = append(Target.Externs, n)
} else { } else {
if Curfn == nil && ctxt == ir.PAUTO { if Curfn == nil && ctxt == ir.PAUTO {
base.Pos = n.Pos() base.Pos = n.Pos()
@ -850,7 +848,7 @@ func newNowritebarrierrecChecker() *nowritebarrierrecChecker {
// important to handle it for this check, so we model it // important to handle it for this check, so we model it
// directly. This has to happen before transformclosure since // directly. This has to happen before transformclosure since
// it's a lot harder to work out the argument after. // it's a lot harder to work out the argument after.
for _, n := range xtop { for _, n := range Target.Decls {
if n.Op() != ir.ODCLFUNC { if n.Op() != ir.ODCLFUNC {
continue continue
} }
@ -925,7 +923,7 @@ func (c *nowritebarrierrecChecker) check() {
// q is the queue of ODCLFUNC Nodes to visit in BFS order. // q is the queue of ODCLFUNC Nodes to visit in BFS order.
var q ir.NameQueue var q ir.NameQueue
for _, n := range xtop { for _, n := range Target.Decls {
if n.Op() != ir.ODCLFUNC { if n.Op() != ir.ODCLFUNC {
continue continue
} }

View File

@ -17,8 +17,6 @@ import (
"strings" "strings"
) )
var embedlist []ir.Node
const ( const (
embedUnknown = iota embedUnknown = iota
embedBytes embedBytes
@ -117,12 +115,12 @@ func varEmbed(p *noder, names []ir.Node, typ ir.Ntype, exprs []ir.Node, embeds [
v.Sym().Def = v v.Sym().Def = v
v.Name().Ntype = typ v.Name().Ntype = typ
v.SetClass(ir.PEXTERN) v.SetClass(ir.PEXTERN)
externdcl = append(externdcl, v) Target.Externs = append(Target.Externs, v)
exprs = []ir.Node{v} exprs = []ir.Node{v}
} }
v.Name().SetEmbedFiles(list) v.Name().SetEmbedFiles(list)
embedlist = append(embedlist, v) Target.Embeds = append(Target.Embeds, v)
return exprs return exprs
} }
@ -187,7 +185,7 @@ func embedFileLess(x, y string) bool {
} }
func dumpembeds() { func dumpembeds() {
for _, v := range embedlist { for _, v := range Target.Embeds {
initEmbed(v) initEmbed(v)
} }
} }

View File

@ -21,8 +21,6 @@ func exportf(bout *bio.Writer, format string, args ...interface{}) {
} }
} }
var asmlist []ir.Node
// exportsym marks n for export (or reexport). // exportsym marks n for export (or reexport).
func exportsym(n *ir.Name) { func exportsym(n *ir.Name) {
if n.Sym().OnExportList() { if n.Sym().OnExportList() {
@ -34,7 +32,7 @@ func exportsym(n *ir.Name) {
fmt.Printf("export symbol %v\n", n.Sym()) fmt.Printf("export symbol %v\n", n.Sym())
} }
exportlist = append(exportlist, n) Target.Exports = append(Target.Exports, n)
} }
func initname(s string) bool { func initname(s string) bool {
@ -57,7 +55,7 @@ func autoexport(n *ir.Name, ctxt ir.Class) {
} }
if base.Flag.AsmHdr != "" && !n.Sym().Asm() { if base.Flag.AsmHdr != "" && !n.Sym().Asm() {
n.Sym().SetAsm(true) n.Sym().SetAsm(true)
asmlist = append(asmlist, n) Target.Asms = append(Target.Asms, n)
} }
} }
@ -202,7 +200,7 @@ func dumpasmhdr() {
base.Fatalf("%v", err) base.Fatalf("%v", err)
} }
fmt.Fprintf(b, "// generated by compile -asmhdr from package %s\n\n", types.LocalPkg.Name) fmt.Fprintf(b, "// generated by compile -asmhdr from package %s\n\n", types.LocalPkg.Name)
for _, n := range asmlist { for _, n := range Target.Asms {
if n.Sym().IsBlank() { if n.Sym().IsBlank() {
continue continue
} }

View File

@ -128,10 +128,6 @@ var (
iscmp [ir.OEND]bool iscmp [ir.OEND]bool
) )
var xtop []ir.Node
var exportlist []*ir.Name
var importlist []*ir.Func // imported functions and methods with inlinable bodies var importlist []*ir.Func // imported functions and methods with inlinable bodies
var ( var (

View File

@ -251,7 +251,7 @@ func iexport(out *bufio.Writer) {
{ {
// TODO(mdempsky): Separate from bexport logic. // TODO(mdempsky): Separate from bexport logic.
p := &exporter{marked: make(map[*types.Type]bool)} p := &exporter{marked: make(map[*types.Type]bool)}
for _, n := range exportlist { for _, n := range Target.Exports {
p.markObject(n) p.markObject(n)
} }
} }
@ -272,7 +272,7 @@ func iexport(out *bufio.Writer) {
} }
// Initialize work queue with exported declarations. // Initialize work queue with exported declarations.
for _, n := range exportlist { for _, n := range Target.Exports {
p.pushDecl(n) p.pushDecl(n)
} }

View File

@ -1111,7 +1111,7 @@ func (r *importReader) exprsOrNil() (a, b ir.Node) {
} }
func builtinCall(pos src.XPos, op ir.Op) *ir.CallExpr { func builtinCall(pos src.XPos, op ir.Op) *ir.CallExpr {
return ir.NewCallExpr(pos, ir.OCALL, mkname(types.BuiltinPkg.Lookup(ir.OpNames[op])), nil) return ir.NewCallExpr(pos, ir.OCALL, ir.NewIdent(base.Pos, types.BuiltinPkg.Lookup(ir.OpNames[op])), nil)
} }
func npos(pos src.XPos, n ir.Node) ir.Node { func npos(pos src.XPos, n ir.Node) ir.Node {

View File

@ -27,9 +27,6 @@ func renameinit() *types.Sym {
return s return s
} }
// List of imported packages, in source code order. See #31636.
var sourceOrderImports []*types.Pkg
// fninit makes an initialization record for the package. // fninit makes an initialization record for the package.
// See runtime/proc.go:initTask for its layout. // See runtime/proc.go:initTask for its layout.
// The 3 tasks for initialization are: // The 3 tasks for initialization are:
@ -43,7 +40,7 @@ func fninit(n []ir.Node) {
var fns []*obj.LSym // functions to call for package initialization var fns []*obj.LSym // functions to call for package initialization
// Find imported packages with init tasks. // Find imported packages with init tasks.
for _, pkg := range sourceOrderImports { for _, pkg := range Target.Imports {
n := resolve(oldname(pkg.Lookup(".inittask"))) n := resolve(oldname(pkg.Lookup(".inittask")))
if n.Op() == ir.ONONAME { if n.Op() == ir.ONONAME {
continue continue
@ -72,7 +69,7 @@ func fninit(n []ir.Node) {
Curfn = fn Curfn = fn
typecheckslice(nf, ctxStmt) typecheckslice(nf, ctxStmt)
Curfn = nil Curfn = nil
xtop = append(xtop, fn) Target.Decls = append(Target.Decls, fn)
fns = append(fns, initializers.Linksym()) fns = append(fns, initializers.Linksym())
} }
if initTodo.Dcl != nil { if initTodo.Dcl != nil {
@ -84,16 +81,14 @@ func fninit(n []ir.Node) {
initTodo = nil initTodo = nil
// Record user init functions. // Record user init functions.
for i := 0; i < renameinitgen; i++ { for _, fn := range Target.Inits {
s := lookupN("init.", i)
fn := ir.AsNode(s.Def).Name().Defn.(*ir.Func)
// Skip init functions with empty bodies. // Skip init functions with empty bodies.
if fn.Body().Len() == 1 { if fn.Body().Len() == 1 {
if stmt := fn.Body().First(); stmt.Op() == ir.OBLOCK && stmt.(*ir.BlockStmt).List().Len() == 0 { if stmt := fn.Body().First(); stmt.Op() == ir.OBLOCK && stmt.(*ir.BlockStmt).List().Len() == 0 {
continue continue
} }
} }
fns = append(fns, s.Linksym()) fns = append(fns, fn.Nname.Sym().Linksym())
} }
if len(deps) == 0 && len(fns) == 0 && types.LocalPkg.Name != "main" && types.LocalPkg.Name != "runtime" { if len(deps) == 0 && len(fns) == 0 && types.LocalPkg.Name != "main" && types.LocalPkg.Name != "runtime" {

View File

@ -230,7 +230,7 @@ func caninl(fn *ir.Func) {
// inlFlood marks n's inline body for export and recursively ensures // inlFlood marks n's inline body for export and recursively ensures
// all called functions are marked too. // all called functions are marked too.
func inlFlood(n *ir.Name) { func inlFlood(n *ir.Name, exportsym func(*ir.Name)) {
if n == nil { if n == nil {
return return
} }
@ -258,13 +258,13 @@ func inlFlood(n *ir.Name) {
ir.VisitList(ir.AsNodes(fn.Inl.Body), func(n ir.Node) { ir.VisitList(ir.AsNodes(fn.Inl.Body), func(n ir.Node) {
switch n.Op() { switch n.Op() {
case ir.OMETHEXPR, ir.ODOTMETH: case ir.OMETHEXPR, ir.ODOTMETH:
inlFlood(methodExprName(n)) inlFlood(methodExprName(n), exportsym)
case ir.ONAME: case ir.ONAME:
n := n.(*ir.Name) n := n.(*ir.Name)
switch n.Class() { switch n.Class() {
case ir.PFUNC: case ir.PFUNC:
inlFlood(n) inlFlood(n, exportsym)
exportsym(n) exportsym(n)
case ir.PEXTERN: case ir.PEXTERN:
exportsym(n) exportsym(n)

View File

@ -51,6 +51,9 @@ func hidePanic() {
} }
} }
// Target is the package being compiled.
var Target *ir.Package
// timing data for compiler phases // timing data for compiler phases
var timings Timings var timings Timings
@ -207,6 +210,8 @@ func Main(archInit func(*Arch)) {
Widthptr = thearch.LinkArch.PtrSize Widthptr = thearch.LinkArch.PtrSize
Widthreg = thearch.LinkArch.RegSize Widthreg = thearch.LinkArch.RegSize
Target = new(ir.Package)
// initialize types package // initialize types package
// (we need to do this to break dependencies that otherwise // (we need to do this to break dependencies that otherwise
// would lead to import cycles) // would lead to import cycles)
@ -240,33 +245,33 @@ func Main(archInit func(*Arch)) {
// to avoid cycles like #18640. // to avoid cycles like #18640.
// TODO(gri) Remove this again once we have a fix for #25838. // TODO(gri) Remove this again once we have a fix for #25838.
// Don't use range--typecheck can add closures to xtop. // Don't use range--typecheck can add closures to Target.Decls.
timings.Start("fe", "typecheck", "top1") timings.Start("fe", "typecheck", "top1")
for i := 0; i < len(xtop); i++ { for i := 0; i < len(Target.Decls); i++ {
n := xtop[i] n := Target.Decls[i]
if op := n.Op(); op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.(*ir.Decl).Left().Name().Alias()) { if op := n.Op(); op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.(*ir.Decl).Left().Name().Alias()) {
xtop[i] = typecheck(n, ctxStmt) Target.Decls[i] = typecheck(n, ctxStmt)
} }
} }
// Phase 2: Variable assignments. // Phase 2: Variable assignments.
// To check interface assignments, depends on phase 1. // To check interface assignments, depends on phase 1.
// Don't use range--typecheck can add closures to xtop. // Don't use range--typecheck can add closures to Target.Decls.
timings.Start("fe", "typecheck", "top2") timings.Start("fe", "typecheck", "top2")
for i := 0; i < len(xtop); i++ { for i := 0; i < len(Target.Decls); i++ {
n := xtop[i] n := Target.Decls[i]
if op := n.Op(); op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.(*ir.Decl).Left().Name().Alias() { if op := n.Op(); op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.(*ir.Decl).Left().Name().Alias() {
xtop[i] = typecheck(n, ctxStmt) Target.Decls[i] = typecheck(n, ctxStmt)
} }
} }
// Phase 3: Type check function bodies. // Phase 3: Type check function bodies.
// Don't use range--typecheck can add closures to xtop. // Don't use range--typecheck can add closures to Target.Decls.
timings.Start("fe", "typecheck", "func") timings.Start("fe", "typecheck", "func")
var fcount int64 var fcount int64
for i := 0; i < len(xtop); i++ { for i := 0; i < len(Target.Decls); i++ {
n := xtop[i] n := Target.Decls[i]
if n.Op() == ir.ODCLFUNC { if n.Op() == ir.ODCLFUNC {
Curfn = n.(*ir.Func) Curfn = n.(*ir.Func)
decldepth = 1 decldepth = 1
@ -287,9 +292,9 @@ func Main(archInit func(*Arch)) {
// TODO(mdempsky): This should be handled when type checking their // TODO(mdempsky): This should be handled when type checking their
// corresponding ODCL nodes. // corresponding ODCL nodes.
timings.Start("fe", "typecheck", "externdcls") timings.Start("fe", "typecheck", "externdcls")
for i, n := range externdcl { for i, n := range Target.Externs {
if n.Op() == ir.ONAME { if n.Op() == ir.ONAME {
externdcl[i] = typecheck(externdcl[i], ctxExpr) Target.Externs[i] = typecheck(Target.Externs[i], ctxExpr)
} }
} }
@ -301,13 +306,13 @@ func Main(archInit func(*Arch)) {
timings.AddEvent(fcount, "funcs") timings.AddEvent(fcount, "funcs")
fninit(xtop) fninit(Target.Decls)
// Phase 4: Decide how to capture closed variables. // Phase 4: Decide how to capture closed variables.
// This needs to run before escape analysis, // This needs to run before escape analysis,
// because variables captured by value do not escape. // because variables captured by value do not escape.
timings.Start("fe", "capturevars") timings.Start("fe", "capturevars")
for _, n := range xtop { for _, n := range Target.Decls {
if n.Op() == ir.ODCLFUNC && n.Func().OClosure != nil { if n.Op() == ir.ODCLFUNC && n.Func().OClosure != nil {
Curfn = n.(*ir.Func) Curfn = n.(*ir.Func)
capturevars(Curfn) capturevars(Curfn)
@ -332,7 +337,7 @@ func Main(archInit func(*Arch)) {
if base.Flag.LowerL != 0 { if base.Flag.LowerL != 0 {
// Find functions that can be inlined and clone them before walk expands them. // Find functions that can be inlined and clone them before walk expands them.
visitBottomUp(xtop, func(list []*ir.Func, recursive bool) { visitBottomUp(Target.Decls, func(list []*ir.Func, recursive bool) {
numfns := numNonClosures(list) numfns := numNonClosures(list)
for _, n := range list { for _, n := range list {
if !recursive || numfns > 1 { if !recursive || numfns > 1 {
@ -350,7 +355,7 @@ func Main(archInit func(*Arch)) {
}) })
} }
for _, n := range xtop { for _, n := range Target.Decls {
if n.Op() == ir.ODCLFUNC { if n.Op() == ir.ODCLFUNC {
devirtualize(n.(*ir.Func)) devirtualize(n.(*ir.Func))
} }
@ -366,7 +371,7 @@ func Main(archInit func(*Arch)) {
// Large values are also moved off stack in escape analysis; // Large values are also moved off stack in escape analysis;
// because large values may contain pointers, it must happen early. // because large values may contain pointers, it must happen early.
timings.Start("fe", "escapes") timings.Start("fe", "escapes")
escapes(xtop) escapes(Target.Decls)
// Collect information for go:nowritebarrierrec // Collect information for go:nowritebarrierrec
// checking. This must happen before transformclosure. // checking. This must happen before transformclosure.
@ -380,7 +385,7 @@ func Main(archInit func(*Arch)) {
// This needs to happen before walk, because closures must be transformed // This needs to happen before walk, because closures must be transformed
// before walk reaches a call of a closure. // before walk reaches a call of a closure.
timings.Start("fe", "xclosures") timings.Start("fe", "xclosures")
for _, n := range xtop { for _, n := range Target.Decls {
if n.Op() == ir.ODCLFUNC && n.Func().OClosure != nil { if n.Op() == ir.ODCLFUNC && n.Func().OClosure != nil {
Curfn = n.(*ir.Func) Curfn = n.(*ir.Func)
transformclosure(Curfn) transformclosure(Curfn)
@ -399,11 +404,11 @@ func Main(archInit func(*Arch)) {
peekitabs() peekitabs()
// Phase 8: Compile top level functions. // Phase 8: Compile top level functions.
// Don't use range--walk can add functions to xtop. // Don't use range--walk can add functions to Target.Decls.
timings.Start("be", "compilefuncs") timings.Start("be", "compilefuncs")
fcount = 0 fcount = 0
for i := 0; i < len(xtop); i++ { for i := 0; i < len(Target.Decls); i++ {
n := xtop[i] n := Target.Decls[i]
if n.Op() == ir.ODCLFUNC { if n.Op() == ir.ODCLFUNC {
funccompile(n.(*ir.Func)) funccompile(n.(*ir.Func))
fcount++ fcount++

View File

@ -27,7 +27,7 @@ import (
// parseFiles concurrently parses files into *syntax.File structures. // parseFiles concurrently parses files into *syntax.File structures.
// Each declaration in every *syntax.File is converted to a syntax tree // Each declaration in every *syntax.File is converted to a syntax tree
// and its root represented by *Node is appended to xtop. // and its root represented by *Node is appended to Target.Decls.
// Returns the total count of parsed lines. // Returns the total count of parsed lines.
func parseFiles(filenames []string) uint { func parseFiles(filenames []string) uint {
noders := make([]*noder, 0, len(filenames)) noders := make([]*noder, 0, len(filenames))
@ -260,7 +260,7 @@ func (p *noder) node() {
p.checkUnused(pragma) p.checkUnused(pragma)
} }
xtop = append(xtop, p.decls(p.file.DeclList)...) Target.Decls = append(Target.Decls, p.decls(p.file.DeclList)...)
base.Pos = src.NoXPos base.Pos = src.NoXPos
clearImports() clearImports()
@ -297,7 +297,7 @@ func (p *noder) processPragmas() {
} }
} }
pragcgobuf = append(pragcgobuf, p.pragcgobuf...) Target.CgoPragmas = append(Target.CgoPragmas, p.pragcgobuf...)
} }
func (p *noder) decls(decls []syntax.Decl) (l []ir.Node) { func (p *noder) decls(decls []syntax.Decl) (l []ir.Node) {
@ -354,7 +354,7 @@ func (p *noder) importDecl(imp *syntax.ImportDecl) {
} }
if !ipkg.Direct { if !ipkg.Direct {
sourceOrderImports = append(sourceOrderImports, ipkg) Target.Imports = append(Target.Imports, ipkg)
} }
ipkg.Direct = true ipkg.Direct = true
@ -530,6 +530,7 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node {
if len(t.Params) > 0 || len(t.Results) > 0 { if len(t.Params) > 0 || len(t.Results) > 0 {
base.ErrorfAt(f.Pos(), "func init must have no arguments and no return values") base.ErrorfAt(f.Pos(), "func init must have no arguments and no return values")
} }
Target.Inits = append(Target.Inits, f)
} }
if types.LocalPkg.Name == "main" && name.Name == "main" { if types.LocalPkg.Name == "main" && name.Name == "main" {

View File

@ -117,13 +117,14 @@ func dumpCompilerObj(bout *bio.Writer) {
} }
func dumpdata() { func dumpdata() {
externs := len(externdcl) numExterns := len(Target.Externs)
xtops := len(xtop) numDecls := len(Target.Decls)
dumpglobls() dumpglobls(Target.Externs)
dumpfuncsyms()
addptabs() addptabs()
exportlistLen := len(exportlist) numExports := len(Target.Exports)
addsignats(externdcl) addsignats(Target.Externs)
dumpsignats() dumpsignats()
dumptabs() dumptabs()
ptabsLen := len(ptabs) ptabsLen := len(ptabs)
@ -140,28 +141,22 @@ func dumpdata() {
// In the typical case, we loop 0 or 1 times. // In the typical case, we loop 0 or 1 times.
// It was not until issue 24761 that we found any code that required a loop at all. // It was not until issue 24761 that we found any code that required a loop at all.
for { for {
for i := xtops; i < len(xtop); i++ { for i := numDecls; i < len(Target.Decls); i++ {
n := xtop[i] n := Target.Decls[i]
if n.Op() == ir.ODCLFUNC { if n.Op() == ir.ODCLFUNC {
funccompile(n.(*ir.Func)) funccompile(n.(*ir.Func))
} }
} }
xtops = len(xtop) numDecls = len(Target.Decls)
compileFunctions() compileFunctions()
dumpsignats() dumpsignats()
if xtops == len(xtop) { if numDecls == len(Target.Decls) {
break break
} }
} }
// Dump extra globals. // Dump extra globals.
tmp := externdcl dumpglobls(Target.Externs[numExterns:])
if externdcl != nil {
externdcl = externdcl[externs:]
}
dumpglobls()
externdcl = tmp
if zerosize > 0 { if zerosize > 0 {
zero := mappkg.Lookup("zero") zero := mappkg.Lookup("zero")
@ -170,8 +165,8 @@ func dumpdata() {
addGCLocals() addGCLocals()
if exportlistLen != len(exportlist) { if numExports != len(Target.Exports) {
base.Fatalf("exportlist changed after compile functions loop") base.Fatalf("Target.Exports changed after compile functions loop")
} }
if ptabsLen != len(ptabs) { if ptabsLen != len(ptabs) {
base.Fatalf("ptabs changed after compile functions loop") base.Fatalf("ptabs changed after compile functions loop")
@ -184,11 +179,11 @@ func dumpdata() {
func dumpLinkerObj(bout *bio.Writer) { func dumpLinkerObj(bout *bio.Writer) {
printObjHeader(bout) printObjHeader(bout)
if len(pragcgobuf) != 0 { if len(Target.CgoPragmas) != 0 {
// write empty export section; must be before cgo section // write empty export section; must be before cgo section
fmt.Fprintf(bout, "\n$$\n\n$$\n\n") fmt.Fprintf(bout, "\n$$\n\n$$\n\n")
fmt.Fprintf(bout, "\n$$ // cgo\n") fmt.Fprintf(bout, "\n$$ // cgo\n")
if err := json.NewEncoder(bout).Encode(pragcgobuf); err != nil { if err := json.NewEncoder(bout).Encode(Target.CgoPragmas); err != nil {
base.Fatalf("serializing pragcgobuf: %v", err) base.Fatalf("serializing pragcgobuf: %v", err)
} }
fmt.Fprintf(bout, "\n$$\n\n") fmt.Fprintf(bout, "\n$$\n\n")
@ -203,7 +198,7 @@ func addptabs() {
if !base.Ctxt.Flag_dynlink || types.LocalPkg.Name != "main" { if !base.Ctxt.Flag_dynlink || types.LocalPkg.Name != "main" {
return return
} }
for _, exportn := range exportlist { for _, exportn := range Target.Exports {
s := exportn.Sym() s := exportn.Sym()
nn := ir.AsNode(s.Def) nn := ir.AsNode(s.Def)
if nn == nil { if nn == nil {
@ -267,9 +262,9 @@ func dumpGlobalConst(n ir.Node) {
base.Ctxt.DwarfIntConst(base.Ctxt.Pkgpath, n.Sym().Name, typesymname(t), ir.IntVal(t, v)) base.Ctxt.DwarfIntConst(base.Ctxt.Pkgpath, n.Sym().Name, typesymname(t), ir.IntVal(t, v))
} }
func dumpglobls() { func dumpglobls(externs []ir.Node) {
// add globals // add globals
for _, n := range externdcl { for _, n := range externs {
switch n.Op() { switch n.Op() {
case ir.ONAME: case ir.ONAME:
dumpGlobal(n.(*ir.Name)) dumpGlobal(n.(*ir.Name))
@ -277,7 +272,9 @@ func dumpglobls() {
dumpGlobalConst(n) dumpGlobalConst(n)
} }
} }
}
func dumpfuncsyms() {
sort.Slice(funcsyms, func(i, j int) bool { sort.Slice(funcsyms, func(i, j int) bool {
return funcsyms[i].LinksymName() < funcsyms[j].LinksymName() return funcsyms[i].LinksymName() < funcsyms[j].LinksymName()
}) })
@ -286,9 +283,6 @@ func dumpglobls() {
dsymptr(sf, 0, s.Linksym(), 0) dsymptr(sf, 0, s.Linksym(), 0)
ggloblsym(sf, int32(Widthptr), obj.DUPOK|obj.RODATA) ggloblsym(sf, int32(Widthptr), obj.DUPOK|obj.RODATA)
} }
// Do not reprocess funcsyms on next dumpglobls call.
funcsyms = nil
} }
// addGCLocals adds gcargs, gclocals, gcregs, and stack object symbols to Ctxt.Data. // addGCLocals adds gcargs, gclocals, gcregs, and stack object symbols to Ctxt.Data.

View File

@ -287,7 +287,7 @@ func compilenow(fn *ir.Func) bool {
// candidate AND was not inlined (yet), put it onto the compile // candidate AND was not inlined (yet), put it onto the compile
// queue instead of compiling it immediately. This is in case we // queue instead of compiling it immediately. This is in case we
// wind up inlining it into a method wrapper that is generated by // wind up inlining it into a method wrapper that is generated by
// compiling a function later on in the xtop list. // compiling a function later on in the Target.Decls list.
if ir.IsMethod(fn) && isInlinableButNotInlined(fn) { if ir.IsMethod(fn) && isInlinableButNotInlined(fn) {
return false return false
} }

View File

@ -1275,7 +1275,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
escapeFuncs([]*ir.Func{fn}, false) escapeFuncs([]*ir.Func{fn}, false)
Curfn = nil Curfn = nil
xtop = append(xtop, fn) Target.Decls = append(Target.Decls, fn)
} }
func paramNnames(ft *types.Type) []ir.Node { func paramNnames(ft *types.Type) []ir.Node {

View File

@ -3942,7 +3942,7 @@ func wrapCall(n *ir.CallExpr, init *ir.Nodes) ir.Node {
typecheckFunc(fn) typecheckFunc(fn)
typecheckslice(fn.Body().Slice(), ctxStmt) typecheckslice(fn.Body().Slice(), ctxStmt)
xtop = append(xtop, fn) Target.Decls = append(Target.Decls, fn)
call = ir.NewCallExpr(base.Pos, ir.OCALL, fn.Nname, n.List().Slice()) call = ir.NewCallExpr(base.Pos, ir.OCALL, fn.Nname, n.List().Slice())
return walkexpr(typecheck(call, ctxStmt), init) return walkexpr(typecheck(call, ctxStmt), init)

View File

@ -0,0 +1,35 @@
// Copyright 2020 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.
package ir
import "cmd/compile/internal/types"
// A Package holds information about the package being compiled.
type Package struct {
// Imports, listed in source order.
// See golang.org/issue/31636.
Imports []*types.Pkg
// Init functions, listed in source order.
Inits []*Func
// Top-level declarations.
Decls []Node
// Extern (package global) declarations.
Externs []Node
// Assembly function declarations.
Asms []*Name
// Cgo directives.
CgoPragmas [][]string
// Variables with //go:embed lines.
Embeds []*Name
// Exported (or re-exported) symbols.
Exports []*Name
}