From 3fe246ae0f5f0f8c839408097747fe7f9a7c04a4 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 18 Nov 2025 12:03:51 -0500 Subject: [PATCH] [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 Auto-Submit: Austin Clements LUCI-TryBot-Result: Go LUCI --- src/simd/_gen/main.go | 149 ++++++++++++++++++++++++++++++++++++++++++ src/simd/generate.go | 12 ++++ src/simd/no_tag.go | 9 --- 3 files changed, 161 insertions(+), 9 deletions(-) create mode 100644 src/simd/_gen/main.go create mode 100644 src/simd/generate.go delete mode 100644 src/simd/no_tag.go diff --git a/src/simd/_gen/main.go b/src/simd/_gen/main.go new file mode 100644 index 0000000000..5061de7110 --- /dev/null +++ b/src/simd/_gen/main.go @@ -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() +} diff --git a/src/simd/generate.go b/src/simd/generate.go new file mode 100644 index 0000000000..95ae5d7851 --- /dev/null +++ b/src/simd/generate.go @@ -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 diff --git a/src/simd/no_tag.go b/src/simd/no_tag.go deleted file mode 100644 index 65c191838f..0000000000 --- a/src/simd/no_tag.go +++ /dev/null @@ -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 . -- 2.52.0