Commit 0f5dfbcf authored by Austin Clements's avatar Austin Clements

cmd/go, cmd/dist: plumb symabis from assembler to compiler

For #27539.

Change-Id: I0e27f142224e820205fb0e65ad03be7eba93da14
Reviewed-on: https://go-review.googlesource.com/c/146999
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 7f1dd3ae
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"encoding/json" "encoding/json"
"flag" "flag"
"fmt" "fmt"
"io/ioutil"
"log" "log"
"os" "os"
"os/exec" "os/exec"
...@@ -682,7 +683,7 @@ func runInstall(dir string, ch chan struct{}) { ...@@ -682,7 +683,7 @@ func runInstall(dir string, ch chan struct{}) {
} }
// Is the target up-to-date? // Is the target up-to-date?
var gofiles, missing []string var gofiles, sfiles, missing []string
stale := rebuildall stale := rebuildall
files = filter(files, func(p string) bool { files = filter(files, func(p string) bool {
for _, suf := range depsuffix { for _, suf := range depsuffix {
...@@ -698,6 +699,8 @@ func runInstall(dir string, ch chan struct{}) { ...@@ -698,6 +699,8 @@ func runInstall(dir string, ch chan struct{}) {
} }
if strings.HasSuffix(p, ".go") { if strings.HasSuffix(p, ".go") {
gofiles = append(gofiles, p) gofiles = append(gofiles, p)
} else if strings.HasSuffix(p, ".s") {
sfiles = append(sfiles, p)
} }
if t.After(ttarg) { if t.After(ttarg) {
stale = true stale = true
...@@ -778,10 +781,42 @@ func runInstall(dir string, ch chan struct{}) { ...@@ -778,10 +781,42 @@ func runInstall(dir string, ch chan struct{}) {
return return
} }
asmArgs := []string{
pathf("%s/asm", tooldir),
"-I", workdir,
"-I", pathf("%s/pkg/include", goroot),
"-D", "GOOS_" + goos,
"-D", "GOARCH_" + goarch,
"-D", "GOOS_GOARCH_" + goos + "_" + goarch,
}
if goarch == "mips" || goarch == "mipsle" {
// Define GOMIPS_value from gomips.
asmArgs = append(asmArgs, "-D", "GOMIPS_"+gomips)
}
if goarch == "mips64" || goarch == "mipsle64" {
// Define GOMIPS64_value from gomips64.
asmArgs = append(asmArgs, "-D", "GOMIPS64_"+gomips64)
}
goasmh := pathf("%s/go_asm.h", workdir)
// Collect symabis from assembly code.
var symabis string
if len(sfiles) > 0 {
symabis = pathf("%s/symabis", workdir)
var wg sync.WaitGroup
asmabis := append(asmArgs[:len(asmArgs):len(asmArgs)], "-symabis", "-o", symabis)
asmabis = append(asmabis, sfiles...)
if err := ioutil.WriteFile(goasmh, nil, 0666); err != nil {
fatalf("cannot write empty go_asm.h: %s", err)
}
bgrun(&wg, path, asmabis...)
bgwait(&wg)
}
var archive string var archive string
// The next loop will compile individual non-Go files. // The next loop will compile individual non-Go files.
// Hand the Go files to the compiler en masse. // Hand the Go files to the compiler en masse.
// For package runtime, this writes go_asm.h, which // For packages containing assembly, this writes go_asm.h, which
// the assembly files will need. // the assembly files will need.
pkg := dir pkg := dir
if strings.HasPrefix(dir, "cmd/") && strings.Count(dir, "/") == 1 { if strings.HasPrefix(dir, "cmd/") && strings.Count(dir, "/") == 1 {
...@@ -794,18 +829,22 @@ func runInstall(dir string, ch chan struct{}) { ...@@ -794,18 +829,22 @@ func runInstall(dir string, ch chan struct{}) {
} else { } else {
archive = b archive = b
} }
// Compile Go code.
compile := []string{pathf("%s/compile", tooldir), "-std", "-pack", "-o", b, "-p", pkg} compile := []string{pathf("%s/compile", tooldir), "-std", "-pack", "-o", b, "-p", pkg}
if gogcflags != "" { if gogcflags != "" {
compile = append(compile, strings.Fields(gogcflags)...) compile = append(compile, strings.Fields(gogcflags)...)
} }
if dir == "runtime" { if dir == "runtime" {
compile = append(compile, "-+", "-asmhdr", pathf("%s/go_asm.h", workdir)) compile = append(compile, "-+")
}
if len(sfiles) > 0 {
compile = append(compile, "-asmhdr", goasmh)
} }
if dir == "internal/bytealg" { if symabis != "" {
// TODO: why don't we generate go_asm.h for all packages compile = append(compile, "-symabis", symabis)
// that have any assembly?
compile = append(compile, "-asmhdr", pathf("%s/go_asm.h", workdir))
} }
compile = append(compile, gofiles...) compile = append(compile, gofiles...)
var wg sync.WaitGroup var wg sync.WaitGroup
// We use bgrun and immediately wait for it instead of calling run() synchronously. // We use bgrun and immediately wait for it instead of calling run() synchronously.
...@@ -815,31 +854,9 @@ func runInstall(dir string, ch chan struct{}) { ...@@ -815,31 +854,9 @@ func runInstall(dir string, ch chan struct{}) {
bgwait(&wg) bgwait(&wg)
// Compile the files. // Compile the files.
for _, p := range files { for _, p := range sfiles {
if !strings.HasSuffix(p, ".s") {
continue
}
var compile []string
// Assembly file for a Go package. // Assembly file for a Go package.
compile = []string{ compile := asmArgs[:len(asmArgs):len(asmArgs)]
pathf("%s/asm", tooldir),
"-I", workdir,
"-I", pathf("%s/pkg/include", goroot),
"-D", "GOOS_" + goos,
"-D", "GOARCH_" + goarch,
"-D", "GOOS_GOARCH_" + goos + "_" + goarch,
}
if goarch == "mips" || goarch == "mipsle" {
// Define GOMIPS_value from gomips.
compile = append(compile, "-D", "GOMIPS_"+gomips)
}
if goarch == "mips64" || goarch == "mipsle64" {
// Define GOMIPS64_value from gomips64.
compile = append(compile, "-D", "GOMIPS64_"+gomips64)
}
doclean := true doclean := true
b := pathf("%s/%s", workdir, filepath.Base(p)) b := pathf("%s/%s", workdir, filepath.Base(p))
......
...@@ -601,6 +601,12 @@ func (b *Builder) build(a *Action) (err error) { ...@@ -601,6 +601,12 @@ func (b *Builder) build(a *Action) (err error) {
return nil return nil
} }
// Collect symbol ABI requirements from assembly.
symabis, err := BuildToolchain.symabis(b, a, sfiles)
if err != nil {
return err
}
// Prepare Go import config. // Prepare Go import config.
// We start it off with a comment so it can't be empty, so icfg.Bytes() below is never nil. // We start it off with a comment so it can't be empty, so icfg.Bytes() below is never nil.
// It should never be empty anyway, but there have been bugs in the past that resulted // It should never be empty anyway, but there have been bugs in the past that resulted
...@@ -632,7 +638,7 @@ func (b *Builder) build(a *Action) (err error) { ...@@ -632,7 +638,7 @@ func (b *Builder) build(a *Action) (err error) {
// Compile Go. // Compile Go.
objpkg := objdir + "_pkg_.a" objpkg := objdir + "_pkg_.a"
ofile, out, err := BuildToolchain.gc(b, a, objpkg, icfg.Bytes(), len(sfiles) > 0, gofiles) ofile, out, err := BuildToolchain.gc(b, a, objpkg, icfg.Bytes(), symabis, len(sfiles) > 0, gofiles)
if len(out) > 0 { if len(out) > 0 {
output := b.processOutput(out) output := b.processOutput(out)
if p.Module != nil && !allowedVersion(p.Module.GoVersion) { if p.Module != nil && !allowedVersion(p.Module.GoVersion) {
...@@ -1967,13 +1973,18 @@ func mkAbs(dir, f string) string { ...@@ -1967,13 +1973,18 @@ func mkAbs(dir, f string) string {
type toolchain interface { type toolchain interface {
// gc runs the compiler in a specific directory on a set of files // gc runs the compiler in a specific directory on a set of files
// and returns the name of the generated output file. // and returns the name of the generated output file.
gc(b *Builder, a *Action, archive string, importcfg []byte, asmhdr bool, gofiles []string) (ofile string, out []byte, err error) //
// TODO: This argument list is long. Consider putting it in a struct.
gc(b *Builder, a *Action, archive string, importcfg []byte, symabis string, asmhdr bool, gofiles []string) (ofile string, out []byte, err error)
// cc runs the toolchain's C compiler in a directory on a C file // cc runs the toolchain's C compiler in a directory on a C file
// to produce an output file. // to produce an output file.
cc(b *Builder, a *Action, ofile, cfile string) error cc(b *Builder, a *Action, ofile, cfile string) error
// asm runs the assembler in a specific directory on specific files // asm runs the assembler in a specific directory on specific files
// and returns a list of named output files. // and returns a list of named output files.
asm(b *Builder, a *Action, sfiles []string) ([]string, error) asm(b *Builder, a *Action, sfiles []string) ([]string, error)
// symabis scans the symbol ABIs from sfiles and returns the
// path to the output symbol ABIs file, or "" if none.
symabis(b *Builder, a *Action, sfiles []string) (string, error)
// pack runs the archive packer in a specific directory to create // pack runs the archive packer in a specific directory to create
// an archive from a set of object files. // an archive from a set of object files.
// typically it is run in the object directory. // typically it is run in the object directory.
...@@ -2004,7 +2015,7 @@ func (noToolchain) linker() string { ...@@ -2004,7 +2015,7 @@ func (noToolchain) linker() string {
return "" return ""
} }
func (noToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, asmhdr bool, gofiles []string) (ofile string, out []byte, err error) { func (noToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, symabis string, asmhdr bool, gofiles []string) (ofile string, out []byte, err error) {
return "", nil, noCompiler() return "", nil, noCompiler()
} }
...@@ -2012,6 +2023,10 @@ func (noToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error) ...@@ -2012,6 +2023,10 @@ func (noToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error)
return nil, noCompiler() return nil, noCompiler()
} }
func (noToolchain) symabis(b *Builder, a *Action, sfiles []string) (string, error) {
return "", noCompiler()
}
func (noToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) error { func (noToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) error {
return noCompiler() return noCompiler()
} }
...@@ -2695,7 +2710,7 @@ func (b *Builder) swigDoIntSize(objdir string) (intsize string, err error) { ...@@ -2695,7 +2710,7 @@ func (b *Builder) swigDoIntSize(objdir string) (intsize string, err error) {
p := load.GoFilesPackage(srcs) p := load.GoFilesPackage(srcs)
if _, _, e := BuildToolchain.gc(b, &Action{Mode: "swigDoIntSize", Package: p, Objdir: objdir}, "", nil, false, srcs); e != nil { if _, _, e := BuildToolchain.gc(b, &Action{Mode: "swigDoIntSize", Package: p, Objdir: objdir}, "", nil, "", false, srcs); e != nil {
return "32", nil return "32", nil
} }
return "64", nil return "64", nil
......
...@@ -36,7 +36,7 @@ func (gcToolchain) linker() string { ...@@ -36,7 +36,7 @@ func (gcToolchain) linker() string {
return base.Tool("link") return base.Tool("link")
} }
func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) { func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, symabis string, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) {
p := a.Package p := a.Package
objdir := a.Objdir objdir := a.Objdir
if archive != "" { if archive != "" {
...@@ -98,6 +98,9 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, a ...@@ -98,6 +98,9 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, a
if strings.HasPrefix(runtimeVersion, "go1") && !strings.Contains(os.Args[0], "go_bootstrap") { if strings.HasPrefix(runtimeVersion, "go1") && !strings.Contains(os.Args[0], "go_bootstrap") {
gcargs = append(gcargs, "-goversion", runtimeVersion) gcargs = append(gcargs, "-goversion", runtimeVersion)
} }
if symabis != "" {
gcargs = append(gcargs, "-symabis", symabis)
}
gcflags := str.StringList(forcedGcflags, p.Internal.Gcflags) gcflags := str.StringList(forcedGcflags, p.Internal.Gcflags)
if compilingRuntime { if compilingRuntime {
...@@ -218,8 +221,7 @@ func trimDir(dir string) string { ...@@ -218,8 +221,7 @@ func trimDir(dir string) string {
return dir return dir
} }
func (gcToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error) { func asmArgs(a *Action, p *load.Package) []interface{} {
p := a.Package
// Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files. // Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
inc := filepath.Join(cfg.GOROOT, "pkg", "include") inc := filepath.Join(cfg.GOROOT, "pkg", "include")
args := []interface{}{cfg.BuildToolexec, base.Tool("asm"), "-trimpath", trimDir(a.Objdir), "-I", a.Objdir, "-I", inc, "-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch, forcedAsmflags, p.Internal.Asmflags} args := []interface{}{cfg.BuildToolexec, base.Tool("asm"), "-trimpath", trimDir(a.Objdir), "-I", a.Objdir, "-I", inc, "-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch, forcedAsmflags, p.Internal.Asmflags}
...@@ -241,6 +243,13 @@ func (gcToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error) ...@@ -241,6 +243,13 @@ func (gcToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error)
args = append(args, "-D", "GOMIPS64_"+cfg.GOMIPS64) args = append(args, "-D", "GOMIPS64_"+cfg.GOMIPS64)
} }
return args
}
func (gcToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error) {
p := a.Package
args := asmArgs(a, p)
var ofiles []string var ofiles []string
for _, sfile := range sfiles { for _, sfile := range sfiles {
ofile := a.Objdir + sfile[:len(sfile)-len(".s")] + ".o" ofile := a.Objdir + sfile[:len(sfile)-len(".s")] + ".o"
...@@ -253,6 +262,32 @@ func (gcToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error) ...@@ -253,6 +262,32 @@ func (gcToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error)
return ofiles, nil return ofiles, nil
} }
func (gcToolchain) symabis(b *Builder, a *Action, sfiles []string) (string, error) {
if len(sfiles) == 0 {
return "", nil
}
p := a.Package
symabis := a.Objdir + "symabis"
args := asmArgs(a, p)
args = append(args, "-symabis", "-o", symabis)
for _, sfile := range sfiles {
args = append(args, mkAbs(p.Dir, sfile))
}
// Supply an empty go_asm.h as if the compiler had been run.
// -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
}
if err := b.run(a, p.Dir, p.ImportPath, nil, args...); err != nil {
return "", err
}
return symabis, nil
}
// toolVerify checks that the command line args writes the same output file // toolVerify checks that the command line args writes the same output file
// if run using newTool instead. // if run using newTool instead.
// Unused now but kept around for future use. // Unused now but kept around for future use.
......
...@@ -51,7 +51,7 @@ func checkGccgoBin() { ...@@ -51,7 +51,7 @@ func checkGccgoBin() {
os.Exit(2) os.Exit(2)
} }
func (tools gccgoToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) { func (tools gccgoToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, symabis string, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) {
p := a.Package p := a.Package
objdir := a.Objdir objdir := a.Objdir
out := "_go_.o" out := "_go_.o"
...@@ -172,6 +172,10 @@ func (tools gccgoToolchain) asm(b *Builder, a *Action, sfiles []string) ([]strin ...@@ -172,6 +172,10 @@ func (tools gccgoToolchain) asm(b *Builder, a *Action, sfiles []string) ([]strin
return ofiles, nil return ofiles, nil
} }
func (gccgoToolchain) symabis(b *Builder, a *Action, sfiles []string) (string, error) {
return "", nil
}
func gccgoArchive(basedir, imp string) string { func gccgoArchive(basedir, imp string) string {
end := filepath.FromSlash(imp + ".a") end := filepath.FromSlash(imp + ".a")
afile := filepath.Join(basedir, end) afile := filepath.Join(basedir, end)
......
...@@ -807,10 +807,23 @@ func (t *test) run() { ...@@ -807,10 +807,23 @@ func (t *test) run() {
} }
} }
if len(asms) > 0 {
if err := ioutil.WriteFile(filepath.Join(longdir, "go_asm.h"), nil, 0666); err != nil {
t.err = fmt.Errorf("write empty go_asm.h: %s", err)
return
}
cmd := []string{goTool(), "tool", "asm", "-symabis", "-o", "symabis"}
cmd = append(cmd, asms...)
_, err = runcmd(cmd...)
if err != nil {
t.err = err
break
}
}
var objs []string var objs []string
cmd := []string{goTool(), "tool", "compile", "-e", "-D", ".", "-I", ".", "-o", "go.o"} cmd := []string{goTool(), "tool", "compile", "-e", "-D", ".", "-I", ".", "-o", "go.o"}
if len(asms) > 0 { if len(asms) > 0 {
cmd = append(cmd, "-asmhdr", "go_asm.h") cmd = append(cmd, "-asmhdr", "go_asm.h", "-symabis", "symabis")
} }
cmd = append(cmd, gos...) cmd = append(cmd, gos...)
_, err := runcmd(cmd...) _, err := runcmd(cmd...)
......
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