Source file src/simd/_gen/main.go

     1  // Copyright 2025 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Run all SIMD-related code generators.
     6  package main
     7  
     8  import (
     9  	"flag"
    10  	"fmt"
    11  	"os"
    12  	"os/exec"
    13  	"path/filepath"
    14  	"strings"
    15  )
    16  
    17  const defaultXedPath = "$XEDPATH" + string(filepath.ListSeparator) + "./simdgen/xeddata" + string(filepath.ListSeparator) + "$HOME/xed/obj/dgen"
    18  
    19  var (
    20  	flagTmplgen = flag.Bool("tmplgen", true, "run tmplgen generator")
    21  	flagSimdgen = flag.Bool("simdgen", true, "run simdgen generator")
    22  
    23  	flagN       = flag.Bool("n", false, "dry run")
    24  	flagXedPath = flag.String("xedPath", defaultXedPath, "load XED datafile from `path`, which must be the XED obj/dgen directory")
    25  )
    26  
    27  var goRoot string
    28  
    29  func main() {
    30  	flag.Parse()
    31  	if flag.NArg() > 0 {
    32  		flag.Usage()
    33  		os.Exit(1)
    34  	}
    35  
    36  	if *flagXedPath == defaultXedPath {
    37  		// In general we want the shell to do variable expansion, but for the
    38  		// default value we don't get that, so do it ourselves.
    39  		*flagXedPath = os.ExpandEnv(defaultXedPath)
    40  	}
    41  
    42  	var err error
    43  	goRoot, err = resolveGOROOT()
    44  	if err != nil {
    45  		fmt.Fprintln(os.Stderr, err)
    46  		os.Exit(1)
    47  	}
    48  
    49  	if *flagTmplgen {
    50  		doTmplgen()
    51  	}
    52  	if *flagSimdgen {
    53  		doSimdgen()
    54  	}
    55  }
    56  
    57  func doTmplgen() {
    58  	goRun("-C", "tmplgen", ".")
    59  }
    60  
    61  func doSimdgen() {
    62  	xedPath, err := resolveXEDPath(*flagXedPath)
    63  	if err != nil {
    64  		fmt.Fprintln(os.Stderr, err)
    65  		os.Exit(1)
    66  	}
    67  
    68  	// Regenerate the XED-derived SIMD files
    69  	goRun("-C", "simdgen", ".", "-o", "godefs", "-goroot", goRoot, "-xedPath", prettyPath("./simdgen", xedPath), "go.yaml", "types.yaml", "categories.yaml")
    70  
    71  	// simdgen produces SSA rule files, so update the SSA files
    72  	goRun("-C", prettyPath(".", filepath.Join(goRoot, "src", "cmd", "compile", "internal", "ssa", "_gen")), ".")
    73  }
    74  
    75  func resolveXEDPath(pathList string) (xedPath string, err error) {
    76  	for _, path := range filepath.SplitList(pathList) {
    77  		if path == "" {
    78  			// Probably an unknown shell variable. Ignore.
    79  			continue
    80  		}
    81  		if _, err := os.Stat(filepath.Join(path, "all-dec-instructions.txt")); err == nil {
    82  			return filepath.Abs(path)
    83  		}
    84  	}
    85  	return "", fmt.Errorf("set $XEDPATH or -xedPath to the XED obj/dgen directory")
    86  }
    87  
    88  func resolveGOROOT() (goRoot string, err error) {
    89  	cmd := exec.Command("go", "env", "GOROOT")
    90  	cmd.Stderr = os.Stderr
    91  	out, err := cmd.Output()
    92  	if err != nil {
    93  		return "", fmt.Errorf("%s: %s", cmd, err)
    94  	}
    95  	goRoot = strings.TrimSuffix(string(out), "\n")
    96  	return goRoot, nil
    97  }
    98  
    99  func goRun(args ...string) {
   100  	exe := filepath.Join(goRoot, "bin", "go")
   101  	cmd := exec.Command(exe, append([]string{"run"}, args...)...)
   102  	run(cmd)
   103  }
   104  
   105  func run(cmd *exec.Cmd) {
   106  	cmd.Stdout = os.Stdout
   107  	cmd.Stderr = os.Stderr
   108  	fmt.Fprintf(os.Stderr, "%s\n", cmdString(cmd))
   109  	if *flagN {
   110  		return
   111  	}
   112  	if err := cmd.Run(); err != nil {
   113  		fmt.Fprintf(os.Stderr, "%s failed: %s\n", cmd, err)
   114  	}
   115  }
   116  
   117  func prettyPath(base, path string) string {
   118  	base, err := filepath.Abs(base)
   119  	if err != nil {
   120  		return path
   121  	}
   122  	p, err := filepath.Rel(base, path)
   123  	if err != nil {
   124  		return path
   125  	}
   126  	return p
   127  }
   128  
   129  func cmdString(cmd *exec.Cmd) string {
   130  	// TODO: Shell quoting?
   131  	// TODO: Environment.
   132  
   133  	var buf strings.Builder
   134  
   135  	cmdPath, err := exec.LookPath(filepath.Base(cmd.Path))
   136  	if err == nil && cmdPath == cmd.Path {
   137  		cmdPath = filepath.Base(cmdPath)
   138  	} else {
   139  		cmdPath = prettyPath(".", cmd.Path)
   140  	}
   141  	buf.WriteString(cmdPath)
   142  
   143  	for _, arg := range cmd.Args[1:] {
   144  		buf.WriteByte(' ')
   145  		buf.WriteString(arg)
   146  	}
   147  
   148  	return buf.String()
   149  }
   150  

View as plain text