Source file src/simd/archsimd/_gen/cmd/hostinfo/gather/main.go

     1  // Copyright 2026 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  package main
     6  
     7  import (
     8  	"flag"
     9  	"fmt"
    10  	"log"
    11  	"maps"
    12  	"os"
    13  	"os/exec"
    14  	"path/filepath"
    15  	"runtime"
    16  	"slices"
    17  	"strings"
    18  
    19  	"simd/archsimd/_gen/gentools"
    20  )
    21  
    22  var printFlag = flag.Bool("print", false, "Print reproduction steps without executing them")
    23  
    24  var (
    25  	hostinfoDir string
    26  	goroot      string
    27  	workDir     string
    28  )
    29  
    30  // shellQuote quotes a single token for a UNIX shell.
    31  func shellQuote(s string) string {
    32  	if s == "" {
    33  		return "''"
    34  	}
    35  	safe := true
    36  	for _, r := range s {
    37  		if !((r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9') ||
    38  			r == '_' || r == '-' || r == '.' || r == '/' || r == '=' || r == ':' || r == ',') {
    39  			safe = false
    40  			break
    41  		}
    42  	}
    43  	if safe {
    44  		return s
    45  	}
    46  	return "'" + strings.ReplaceAll(s, "'", `'\''`) + "'"
    47  }
    48  
    49  func run(args ...string) {
    50  	if len(args) == 0 {
    51  		return
    52  	}
    53  	if *printFlag {
    54  		words := make([]string, len(args))
    55  		for i, a := range args {
    56  			words[i] = shellQuote(a)
    57  		}
    58  		fmt.Println(strings.Join(words, " "))
    59  		return
    60  	}
    61  
    62  	var env []string
    63  	for len(args) > 0 && strings.Contains(args[0], "=") {
    64  		env = append(env, args[0])
    65  		args = args[1:]
    66  	}
    67  	if len(args) == 0 {
    68  		return
    69  	}
    70  
    71  	c := exec.Command(args[0], args[1:]...)
    72  	if len(env) > 0 {
    73  		c.Env = append(os.Environ(), env...)
    74  	}
    75  	c.Stdin, c.Stdout, c.Stderr = os.Stdin, os.Stdout, os.Stderr
    76  	if err := c.Run(); err != nil {
    77  		log.Fatalf("%s failed: %v", args[0], err)
    78  	}
    79  }
    80  
    81  func compile(goos, goarch string) string {
    82  	bin := filepath.Join(workDir, fmt.Sprintf("hostinfo-%s-%s", goos, goarch))
    83  	run("GOOS="+goos, "GOARCH="+goarch, "GOEXPERIMENT=simd", "go", "build", "-C", hostinfoDir, "-o", bin, ".")
    84  	return bin
    85  }
    86  
    87  func runGomote(builder, goarch string) {
    88  	bin := compile("linux", goarch)
    89  	run("GOMOTE_GROUP=simd", "gomote", "create", builder)
    90  	run("gomote", "-group", "simd", "put", bin, "hostinfo")
    91  	run("gomote", "-group", "simd", "run", "./hostinfo", "-host", builder)
    92  	run("gomote", "-group", "simd", "destroy")
    93  }
    94  
    95  func runQEMUarm64(name, cpu string) {
    96  	bin := compile("linux", "arm64")
    97  	run("qemu-aarch64", "-cpu", cpu, bin, "-host", name)
    98  }
    99  
   100  var hosts = map[string]func(){
   101  	"local": func() {
   102  		run("GOEXPERIMENT=simd", "go", "run", "-C", hostinfoDir, ".", "-host", "local")
   103  	},
   104  	"gotip-linux-amd64_avx512": func() {
   105  		runGomote("gotip-linux-amd64_avx512", "amd64")
   106  	},
   107  	"gotip-linux-amd64": func() {
   108  		runGomote("gotip-linux-amd64", "amd64")
   109  	},
   110  	"gotip-linux-arm64": func() {
   111  		runGomote("gotip-linux-arm64", "arm64")
   112  	},
   113  	"qemu-aarch64-neon": func() {
   114  		runQEMUarm64("qemu-aarch64-neon", "neoverse-n1")
   115  	},
   116  	"qemu-aarch64-sve128": func() {
   117  		runQEMUarm64("qemu-aarch64-sve128", "neoverse-n2")
   118  	},
   119  	"qemu-aarch64-sve256": func() {
   120  		runQEMUarm64("qemu-aarch64-sve256", "neoverse-v1")
   121  	},
   122  	"wasip1-wasmtime": func() {
   123  		bin := compile("wasip1", "wasm")
   124  		run("wasmtime", "run", bin, "-host", "wasip1-wasmtime")
   125  	},
   126  	"wasip1-wazero": func() {
   127  		bin := compile("wasip1", "wasm")
   128  		run("wazero", "run", bin, "-host", "wasip1-wazero")
   129  	},
   130  	"js-node": func() {
   131  		bin := compile("js", "wasm")
   132  		run("node", filepath.Join(goroot, "lib/wasm/wasm_exec_node.js"), bin, "-host", "js-node")
   133  	},
   134  }
   135  
   136  func usage() {
   137  	fmt.Printf("Usage: gather [-print] <all | host ...>\n\n")
   138  	fmt.Println("Known pseudo-hosts:")
   139  	fmt.Println("  - all (all known pseudo-hosts; must appear alone)")
   140  	for _, host := range slices.Sorted(maps.Keys(hosts)) {
   141  		fmt.Printf("  - %s\n", host)
   142  	}
   143  	fmt.Println("\nFlags:")
   144  	flag.PrintDefaults()
   145  }
   146  
   147  func main() {
   148  	flag.Usage = func() {
   149  		usage()
   150  		os.Exit(0)
   151  	}
   152  	flag.Parse()
   153  
   154  	args := flag.Args()
   155  	if len(args) == 0 {
   156  		usage()
   157  		os.Exit(1)
   158  	}
   159  
   160  	var targets []string
   161  	if args[0] == "all" {
   162  		if len(args) > 1 {
   163  			fmt.Fprintln(os.Stderr, "Error: 'all' must appear alone")
   164  			os.Exit(1)
   165  		}
   166  		targets = slices.Sorted(maps.Keys(hosts))
   167  	} else {
   168  		for _, arg := range args {
   169  			if arg == "all" {
   170  				fmt.Fprintln(os.Stderr, "Error: 'all' must appear alone")
   171  				os.Exit(1)
   172  			}
   173  			if _, ok := hosts[arg]; !ok {
   174  				fmt.Fprintf(os.Stderr, "Unknown host: %s\n\n", arg)
   175  				usage()
   176  				os.Exit(1)
   177  			}
   178  			targets = append(targets, arg)
   179  		}
   180  	}
   181  
   182  	_, filename, _, ok := runtime.Caller(0)
   183  	if !ok {
   184  		log.Fatal("cannot determine script directory")
   185  	}
   186  	gatherDir := filepath.Dir(filename)
   187  	hostinfoDir = filepath.Dir(gatherDir)
   188  	goroot = gentools.DefaultGOROOT()
   189  
   190  	if *printFlag {
   191  		workDir = "/tmp"
   192  	} else {
   193  		var err error
   194  		workDir, err = os.MkdirTemp("", "hostinfo-*")
   195  		if err != nil {
   196  			log.Fatal(err)
   197  		}
   198  		defer os.RemoveAll(workDir)
   199  	}
   200  
   201  	for i, target := range targets {
   202  		if i > 0 {
   203  			fmt.Println()
   204  		}
   205  		hosts[target]()
   206  	}
   207  }
   208  

View as plain text