Commit 07544c7e authored by Austin Clements's avatar Austin Clements

cmd/go, cmd/dist: collect known cross-package uses of runtime symbols

This extends cmd/go's symabis support to collect known cross-package
uses of runtime symbols from other "basically runtime" packages in
std. This avoids having to declare a large number of ABI0 symbols in
the runtime for a small number of known cross-package references.

For cmd/dist, we use a simpler but less efficient approach and tell
the compiler to generate ABI wrappers for everything.

Change-Id: Ifaed94efdcff42e7345ab11b4d2fb880fb1a24e8
Reviewed-on: https://go-review.googlesource.com/c/147257
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 0f5dfbcf
......@@ -844,6 +844,13 @@ func runInstall(dir string, ch chan struct{}) {
if symabis != "" {
compile = append(compile, "-symabis", symabis)
}
if dir == "runtime" || dir == "runtime/internal/atomic" {
// These packages define symbols referenced by
// assembly in other packages. In cmd/go, we work out
// the exact details. For bootstrapping, just tell the
// compiler to generate ABI wrappers for everything.
compile = append(compile, "-allabis")
}
compile = append(compile, gofiles...)
var wg sync.WaitGroup
......
......@@ -1618,6 +1618,25 @@ func (b *Builder) writeFile(file string, text []byte) error {
return ioutil.WriteFile(file, text, 0666)
}
// appendFile appends the text to file.
func (b *Builder) appendFile(file string, text []byte) error {
if cfg.BuildN || cfg.BuildX {
b.Showcmd("", "cat >>%s << 'EOF' # internal\n%sEOF", file, text)
}
if cfg.BuildN {
return nil
}
f, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
return err
}
defer f.Close()
if _, err = f.Write(text); err != nil {
return err
}
return f.Close()
}
// Install the cgo export header file, if there is one.
func (b *Builder) installHeader(a *Action) error {
src := a.Objdir + "_cgo_install.h"
......
......@@ -263,15 +263,13 @@ func (gcToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error)
}
func (gcToolchain) symabis(b *Builder, a *Action, sfiles []string) (string, error) {
if len(sfiles) == 0 {
return "", nil
}
p := a.Package
symabis := a.Objdir + "symabis"
mkSymabis := func(p *load.Package, sfiles []string, path string) error {
args := asmArgs(a, p)
args = append(args, "-symabis", "-o", symabis)
args = append(args, "-symabis", "-o", path)
for _, sfile := range sfiles {
if p.ImportPath == "runtime/cgo" && strings.HasPrefix(sfile, "gcc_") {
continue
}
args = append(args, mkAbs(p.Dir, sfile))
}
......@@ -279,12 +277,64 @@ func (gcToolchain) symabis(b *Builder, a *Action, sfiles []string) (string, erro
// -symabis parsing is lax enough that we don't need the
// actual definitions that would appear in go_asm.h.
if err := b.writeFile(a.Objdir+"go_asm.h", nil); err != nil {
return err
}
return b.run(a, p.Dir, p.ImportPath, nil, args...)
}
var symabis string // Only set if we actually create the file
p := a.Package
if len(sfiles) != 0 {
symabis = a.Objdir + "symabis"
if err := mkSymabis(p, sfiles, symabis); err != nil {
return "", err
}
}
if err := b.run(a, p.Dir, p.ImportPath, nil, args...); err != nil {
// Gather known cross-package references from assembly code.
var otherPkgs []string
if p.ImportPath == "runtime" {
// Assembly in syscall and runtime/cgo references
// symbols in runtime.
otherPkgs = []string{"syscall", "runtime/cgo"}
} else if p.ImportPath == "runtime/internal/atomic" {
// sync/atomic is an assembly wrapper around
// runtime/internal/atomic.
otherPkgs = []string{"sync/atomic"}
}
for _, p2name := range otherPkgs {
p2 := load.LoadPackage(p2name, &load.ImportStack{})
if len(p2.SFiles) == 0 {
continue
}
symabis2 := a.Objdir + "symabis2"
if err := mkSymabis(p2, p2.SFiles, symabis2); err != nil {
return "", err
}
// Filter out just the symbol refs and append them to
// the symabis file.
abis2, err := ioutil.ReadFile(symabis2)
if err != nil {
return "", err
}
var refs bytes.Buffer
for _, line := range strings.Split(string(abis2), "\n") {
fs := strings.Fields(line)
if len(fs) >= 2 && fs[0] == "ref" && !strings.HasPrefix(fs[1], `"".`) {
fmt.Fprintf(&refs, "%s\n", line)
}
}
if refs.Len() != 0 {
symabis = a.Objdir + "symabis"
if err := b.appendFile(symabis, refs.Bytes()); err != nil {
return "", err
}
}
}
return symabis, nil
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment