fix(arch): narrow file names by go/build's suffix rule

Assisted-by: GLM 5.3 Flash
This commit is contained in:
petrbalvin committed 2026-10-06 23:59:47 +02:00
1 parent c107b45933
commit a90ec84bee
2 files changed
+60 -12

No files matched your search

+31 -10
View File
@@ -24,20 +24,41 @@ const (
Unknown Arch = ""
)
// FromFilename guesses the target architecture from a source file name. Go
// assembly files conventionally carry a GOARCH suffix such as "_amd64.s",
// "_arm64.s", "_riscv64.s" or "_loong64.s". It returns Unknown when no suffix
// matches.
// FromFilename guesses the target architecture from a source file name, by
// go/build's goodOSArchFile rule: directories are stripped, the name is cut
// at its first dot, everything before the first underscore is ignored and a
// trailing _test segment is dropped; the name is per-architecture only when
// its final underscore segment is an architecture name (foo_amd64.s,
// sys_darwin_arm64.s, foo_amd64_test.s). Any other name narrows nothing:
// not one whose last segment merely contains an architecture name
// (x_loong64y.s), not one with no underscore at all (amd64.s, which
// go/build also keeps generic), and not one differing in case
// (foo_AMD64.s), because the segment match is case-sensitive as go/build's
// is. A name carrying an operating system alone (foo_linux.s) narrows by
// GOOS rather than architecture, and one carrying an architecture gasm
// does not assemble for (vlop_arm.s) reports Unknown so the caller's own
// port filter decides. It returns Unknown when the name narrows nothing.
func FromFilename(name string) Arch {
lower := strings.ToLower(name)
switch {
case strings.Contains(lower, "_amd64"):
if i := strings.LastIndexByte(name, '/'); i >= 0 {
name = name[i+1:]
}
name, _, _ = strings.Cut(name, ".")
i := strings.Index(name, "_")
if i < 0 {
return Unknown
}
segs := strings.Split(name[i:], "_")
if last := len(segs) - 1; segs[last] == "test" {
segs = segs[:last]
}
switch segs[len(segs)-1] {
case "amd64":
return AMD64
case strings.Contains(lower, "_arm64"):
case "arm64":
return ARM64
case strings.Contains(lower, "_riscv64"), strings.Contains(lower, "_riscv"):
case "riscv64":
return RISCV
case strings.Contains(lower, "_loong64"), strings.Contains(lower, "_loong"):
case "loong64":
return LOONG64
default:
return Unknown
+29 -2
View File
@@ -7,13 +7,40 @@ import "testing"
func TestFromFilename(t *testing.T) {
cases := map[string]Arch{
// Positive: the final underscore segment is the architecture.
"avx2_amd64.s": AMD64,
"foo_arm64.s": ARM64,
"portable.s": Unknown,
"decode_ARM64.S": ARM64,
"kernels_amd64.s": AMD64,
"kernel_riscv64.s": RISCV,
"kernel_loong64.s": LOONG64,
"decode_arm64.S": ARM64, // the extension is cut with the first dot
// OS before arch: the _<os>_<arch> pair form.
"sys_darwin_arm64.s": ARM64,
"rt0_linux_amd64.s": AMD64,
// A trailing _test segment is dropped before the suffix rule.
"foo_amd64_test.s": AMD64,
// Trailing junk: a final segment that merely contains an
// architecture name narrows nothing, exactly as go/build's
// segment rule says.
"x_loong64y.s": Unknown,
"asm_amd64x.s": Unknown, // a real GOROOT name
"asm_darwin_arm64_gc.s": Unknown, // the trailing _gc segment is junk
"x_loong.s": Unknown,
"foo_amd64x_test.s": Unknown,
// Case sensitivity: the segment match is exact, as go/build's is.
"foo_AMD64.s": Unknown,
"decode_ARM64.S": Unknown,
// No underscore at all: generic whatever the stem says.
"amd64.s": Unknown,
"portable.s": Unknown,
// A GOOS-only name narrows by operating system, not architecture.
"foo_linux.s": Unknown,
// An architecture gasm does not assemble for: named, but Unknown.
"vlop_arm.s": Unknown,
"foo_riscv.s": Unknown,
// Directories are stripped first, whatever dots they carry.
"some/dir/kernel_loong64.s": LOONG64,
"/a.b/x_amd64.s": AMD64,
}
for name, want := range cases {
if got := FromFilename(name); got != want {