[dev.simd] simd: make 'go generate' generate everything

The simd package involves quite a lot of code generation.
Currently, that's spread across a few different tools.
Bring the process together in simd/_gen/main.go and make
'go generate' in the simd package do the right thing.

Change-Id: Iba7e120987f13840a23ed32a528e2398fc7a6065
Reviewed-on: https://go-review.googlesource.com/c/go/+/721663
Reviewed-by: David Chase <drchase@google.com>
Auto-Submit: Austin Clements <austin@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Austin Clements 2025-11-18 12:03:51 -05:00 committed by Gopher Robot
parent cf45adf140
commit 3fe246ae0f
3 changed files with 161 additions and 9 deletions

149
src/simd/_gen/main.go Normal file
View file

@ -0,0 +1,149 @@
// Copyright 2025 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.
// Run all SIMD-related code generators.
package main
import (
"flag"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
)
const defaultXedPath = "$XEDPATH" + string(filepath.ListSeparator) + "./simdgen/xeddata" + string(filepath.ListSeparator) + "$HOME/xed/obj/dgen"
var (
flagTmplgen = flag.Bool("tmplgen", true, "run tmplgen generator")
flagSimdgen = flag.Bool("simdgen", true, "run simdgen generator")
flagN = flag.Bool("n", false, "dry run")
flagXedPath = flag.String("xedPath", defaultXedPath, "load XED datafile from `path`, which must be the XED obj/dgen directory")
)
var goRoot string
func main() {
flag.Parse()
if flag.NArg() > 0 {
flag.Usage()
os.Exit(1)
}
if *flagXedPath == defaultXedPath {
// In general we want the shell to do variable expansion, but for the
// default value we don't get that, so do it ourselves.
*flagXedPath = os.ExpandEnv(defaultXedPath)
}
var err error
goRoot, err = resolveGOROOT()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
if *flagTmplgen {
doTmplgen()
}
if *flagSimdgen {
doSimdgen()
}
}
func doTmplgen() {
goRun("-C", "tmplgen", ".")
}
func doSimdgen() {
xedPath, err := resolveXEDPath(*flagXedPath)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
// Regenerate the XED-derived SIMD files
goRun("-C", "simdgen", ".", "-o", "godefs", "-goroot", goRoot, "-xedPath", prettyPath("./simdgen", xedPath), "go.yaml", "types.yaml", "categories.yaml")
// simdgen produces SSA rule files, so update the SSA files
goRun("-C", prettyPath(".", filepath.Join(goRoot, "src", "cmd", "compile", "internal", "ssa", "_gen")), ".")
}
func resolveXEDPath(pathList string) (xedPath string, err error) {
for _, path := range filepath.SplitList(pathList) {
if path == "" {
// Probably an unknown shell variable. Ignore.
continue
}
if _, err := os.Stat(filepath.Join(path, "all-dec-instructions.txt")); err == nil {
return filepath.Abs(path)
}
}
return "", fmt.Errorf("set $XEDPATH or -xedPath to the XED obj/dgen directory")
}
func resolveGOROOT() (goRoot string, err error) {
cmd := exec.Command("go", "env", "GOROOT")
cmd.Stderr = os.Stderr
out, err := cmd.Output()
if err != nil {
return "", fmt.Errorf("%s: %s", cmd, err)
}
goRoot = strings.TrimSuffix(string(out), "\n")
return goRoot, nil
}
func goRun(args ...string) {
exe := filepath.Join(goRoot, "bin", "go")
cmd := exec.Command(exe, append([]string{"run"}, args...)...)
run(cmd)
}
func run(cmd *exec.Cmd) {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
fmt.Fprintf(os.Stderr, "%s\n", cmdString(cmd))
if *flagN {
return
}
if err := cmd.Run(); err != nil {
fmt.Fprintf(os.Stderr, "%s failed: %s\n", cmd, err)
}
}
func prettyPath(base, path string) string {
base, err := filepath.Abs(base)
if err != nil {
return path
}
p, err := filepath.Rel(base, path)
if err != nil {
return path
}
return p
}
func cmdString(cmd *exec.Cmd) string {
// TODO: Shell quoting?
// TODO: Environment.
var buf strings.Builder
cmdPath, err := exec.LookPath(filepath.Base(cmd.Path))
if err == nil && cmdPath == cmd.Path {
cmdPath = filepath.Base(cmdPath)
} else {
cmdPath = prettyPath(".", cmd.Path)
}
buf.WriteString(cmdPath)
for _, arg := range cmd.Args[1:] {
buf.WriteByte(' ')
buf.WriteString(arg)
}
return buf.String()
}

12
src/simd/generate.go Normal file
View file

@ -0,0 +1,12 @@
// Copyright 2025 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 simd
// Invoke code generators.
//
// This file intentionally has no goexperiment.simd build tag, so that go
// generate can run without a GOEXPERIMENT set.
//go:generate go run -C _gen . -tmplgen -simdgen

View file

@ -1,9 +0,0 @@
// Copyright 2025 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 simd
// This file has no build tag, so that go generate can run without a build tag.
//go:generate go run -C _gen/tmplgen .