Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions cmd/loopvec-toolexec/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,30 @@ type compileArgs struct {
importcfg int // index in args of the importcfg path, or -1
files []int // indexes in args of the Go source files
// unsupported is set for build modes whose objects the nested simd build
// would not match (race, msan, asan, shared, dynlink, -trimpath).
// would not match (race, msan, asan, shared, dynlink, -trimpath). -shared
// is also what the go command passes for a position-independent
// executable, the default build mode on some targets (see defaultPIE);
// there the nested build uses the same default and matches.
unsupported bool
}

// defaultPIE reports whether the target builds position-independent
// executables by default (internal/platform.DefaultPIE), so that the go command
// passes -shared to every compile of a default build. The go command sets GOOS
// for the tools it runs. On windows -race turns the default off, but -race is
// unsupported here on its own.
func defaultPIE() bool {
goos := os.Getenv("GOOS")
if goos == "" {
goos = runtime.GOOS
}
switch goos {
case "android", "darwin", "ios", "windows":
return true
}
return false
}

func parseCompileArgs(args []string) compileArgs {
c := compileArgs{importcfg: -1}
first := len(args)
Expand All @@ -59,8 +79,10 @@ func parseCompileArgs(args []string) compileArgs {
c.lang = args[i+1]
case strings.HasPrefix(arg, "-lang="):
c.lang = strings.TrimPrefix(arg, "-lang=")
case arg == "-race", arg == "-msan", arg == "-asan", arg == "-shared", arg == "-dynlink":
case arg == "-race", arg == "-msan", arg == "-asan", arg == "-dynlink":
c.unsupported = true
case arg == "-shared":
c.unsupported = !defaultPIE()
case arg == "-trimpath" && hasValue && strings.Contains(args[i+1], ";"):
c.unsupported = true
}
Expand Down
64 changes: 64 additions & 0 deletions testdata/toolexec_buildmode_pie.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# The go command compiles a position-independent executable with -shared. It is the
# default build mode on darwin, ios, android and windows, where the nested simd build
# is one too, so a default build is rewritten there. Asking for one where it is not
# the default (-buildmode=pie on linux) still leaves the package alone: the nested
# build would not match it.

# Reference: the scalar program.
exec go run .
cmp stdout want.out

env GOEXPERIMENT=simd
env GOCACHE=$WORK/gocache
env LOOPVEC_TOOLEXEC_LOG=$WORK/log
env LOOPVEC_TOOLEXEC_LOG_PKGS=example.com/app/vec

[GOOS:darwin] exec go build -toolexec=$LOOPVEC_TOOLEXEC -o app .
[GOOS:darwin] cmp log rewrote.want

[GOOS:linux] env LOOPVEC_TOOLEXEC_DEBUG=1
[GOOS:linux] exec go build -buildmode=pie -toolexec=$LOOPVEC_TOOLEXEC -o app .
[GOOS:linux] cmp log skipped.want

[GOOS:darwin] exec ./app
[GOOS:darwin] cmp stdout want.out
[GOOS:linux] exec ./app
[GOOS:linux] cmp stdout want.out

-- go.mod --
module example.com/app

go 1.27.1
-- vec/vec.go --
package vec

func AddInt32s(dst, a, b []int32) {
for i := range dst {
dst[i] = a[i] + b[i]
}
}
-- main.go --
package main

import (
"fmt"

"example.com/app/vec"
)

func main() {
dst := make([]int32, 21)
a := make([]int32, 21)
b := make([]int32, 21)
for i := range a {
a[i], b[i] = int32(i), int32(2*i)
}
vec.AddInt32s(dst, a, b)
fmt.Println(dst)
}
-- want.out --
[0 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60]
-- rewrote.want --
rewrote 1 loop(s) in example.com/app/vec
-- skipped.want --
skipped example.com/app/vec: simd unavailable or unsupported build mode
4 changes: 3 additions & 1 deletion toolexec.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ Packages are left alone when:
`os`, `strconv`, `sync`, `sync/atomic`, `math`, and more). Rewritten code
imports `simd`, so rewriting these would create an import cycle.
- They use cgo, or the build uses `-race`, `-msan`, `-asan`, `-shared`,
`-dynlink` or `-trimpath`.
`-dynlink` or `-trimpath`. `-shared` is accepted where a position-independent
executable is the default build (darwin, ios, android, windows), since the
nested simd build is one there too.
- They are cryptographic: `crypto/...` and `golang.org/x/crypto/...`, vendored
copies included. Constant-time code is written so that its running time does
not depend on secret data, and a rewrite adds a runtime overlap check, a length
Expand Down