feat(cli): add --map flag to diff for comparing differently-named
functions
This commit is contained in:
@@ -9,6 +9,12 @@ and this project adheres to [Conventional Commits](https://www.conventionalcommi
|
||||
|
||||
Unreleased changes on the `development` branch.
|
||||
|
||||
### Added
|
||||
|
||||
- **`gasm diff --map`** — compare functions whose names differ between files
|
||||
(e.g. `--map wideCopyAVX2=wideCopyAVX512` pairs AVX2 and AVX-512 variants
|
||||
regardless of suffix). Unmapped functions fall back to the original name match.
|
||||
|
||||
## [0.29.0] — 2026-08-05
|
||||
|
||||
RISC-V GOOBJ emission, YMM vector register display, named buffer allocation
|
||||
|
||||
+35
-6
@@ -542,7 +542,11 @@ Compare the machine code produced by assembling two files.
|
||||
Shows which functions differ and the byte-level differences.
|
||||
Useful for verifying that two implementations produce identical code,
|
||||
or for tracking encoding changes between Go assembler versions.
|
||||
|
||||
Use --map to compare functions whose names differ between the files,
|
||||
e.g. --map wideCopyAVX2=wideCopyAVX512 pairs the two regardless of suffix.
|
||||
`)
|
||||
mapSpec := fs.String("map", "", "comma-separated old=new pairs to match functions with different names")
|
||||
fs.Parse(args)
|
||||
if fs.NArg() != 2 {
|
||||
fmt.Fprintln(os.Stderr, "usage: gasm diff <file1.s> <file2.s>")
|
||||
@@ -550,6 +554,19 @@ or for tracking encoding changes between Go assembler versions.
|
||||
}
|
||||
path1, path2 := fs.Arg(0), fs.Arg(1)
|
||||
|
||||
// Parse the name mapping (file1 name → file2 name).
|
||||
nameMap := make(map[string]string)
|
||||
if *mapSpec != "" {
|
||||
for _, pair := range strings.Split(*mapSpec, ",") {
|
||||
old, new, ok := strings.Cut(pair, "=")
|
||||
if !ok || old == "" || new == "" {
|
||||
fmt.Fprintf(os.Stderr, "gasm diff: invalid --map pair %q (expected old=new)\n", pair)
|
||||
return 2
|
||||
}
|
||||
nameMap[old] = new
|
||||
}
|
||||
}
|
||||
|
||||
// Assemble both files.
|
||||
img1, err := assembleFile(path1)
|
||||
if err != nil {
|
||||
@@ -562,7 +579,7 @@ or for tracking encoding changes between Go assembler versions.
|
||||
return 1
|
||||
}
|
||||
|
||||
// Compare functions by name.
|
||||
// Compare functions by name, honouring the --map overrides.
|
||||
funcs1 := make(map[string][]byte)
|
||||
for _, fn := range img1.Funcs {
|
||||
funcs1[fn.Name] = img1.Code[fn.Offset : fn.Offset+fn.Size]
|
||||
@@ -572,25 +589,37 @@ or for tracking encoding changes between Go assembler versions.
|
||||
funcs2[fn.Name] = img2.Code[fn.Offset : fn.Offset+fn.Size]
|
||||
}
|
||||
|
||||
// Find common functions and compare.
|
||||
// Track which file2 functions were consumed (by direct match or via --map)
|
||||
// so the "only in file2" pass skips them.
|
||||
matched2 := make(map[string]bool)
|
||||
|
||||
diffs := 0
|
||||
for name, code1 := range funcs1 {
|
||||
code2, ok := funcs2[name]
|
||||
target := name
|
||||
if mapped, ok := nameMap[name]; ok {
|
||||
target = mapped
|
||||
}
|
||||
code2, ok := funcs2[target]
|
||||
if !ok {
|
||||
fmt.Printf("%s: only in %s\n", name, path1)
|
||||
diffs++
|
||||
continue
|
||||
}
|
||||
matched2[target] = true
|
||||
label := name
|
||||
if target != name {
|
||||
label = name + " → " + target
|
||||
}
|
||||
if !bytes.Equal(code1, code2) {
|
||||
fmt.Printf("%s: DIFFERS (%d vs %d bytes)\n", name, len(code1), len(code2))
|
||||
fmt.Printf("%s: DIFFERS (%d vs %d bytes)\n", label, len(code1), len(code2))
|
||||
printByteDiff(code1, code2)
|
||||
diffs++
|
||||
} else {
|
||||
fmt.Printf("%s: identical (%d bytes)\n", name, len(code1))
|
||||
fmt.Printf("%s: identical (%d bytes)\n", label, len(code1))
|
||||
}
|
||||
}
|
||||
for name := range funcs2 {
|
||||
if _, ok := funcs1[name]; !ok {
|
||||
if !matched2[name] {
|
||||
fmt.Printf("%s: only in %s\n", name, path2)
|
||||
diffs++
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user