fix: restore iota blocks, asm --format flag and prose after the syntax pass
Test / vet (push) Successful in 48s
Test / test (push) Successful in 2m35s
Test / build (push) Successful in 40s

This commit is contained in:
2026-08-29 17:12:53 +02:00
parent 15e8b88d32
commit 56ad158772
34 changed files with 170 additions and 183 deletions
+30 -30
View File
@@ -299,7 +299,7 @@ given.
rc = 1
continue
}
out := format.Source(path, src)
out := format.Source(src)
if dirMode || *write {
if out != src {
if err := os.WriteFile(path, []byte(out), 0o644); err != nil {
@@ -447,7 +447,7 @@ requires -p, the package path, and the installed Go toolchain).
return 1
}
img, err := assembleFile(path, targetArch, f)
img, err := assembleFile(targetArch, f)
if err != nil {
fmt.Fprintf(os.Stderr, "%s: %v\n", path, err)
return 1
@@ -544,7 +544,7 @@ requires -p, the package path, and the installed Go toolchain).
// cmdDiff compares the machine code of two assembly files.
func cmdDiff(args []string) int {
fs := newCommand("diff", "gasm diff <file1.s> <file2.s>", `
set := newCommand("diff", "gasm diff <file1.s> <file2.s>", `
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,
@@ -553,13 +553,13 @@ 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 {
mapSpec := set.String("map", "", "comma-separated old=new pairs to match functions with different names")
set.Parse(args)
if set.NArg() != 2 {
fmt.Fprintln(os.Stderr, "usage: gasm diff <file1.s> <file2.s>")
return 2
}
path1, path2 := fs.Arg(0), fs.Arg(1)
path1, path2 := set.Arg(0), set.Arg(1)
// Parse the name mapping (file1 name → file2 name).
nameMap := make(map[string]string)
@@ -640,7 +640,7 @@ e.g. --map wideCopyAVX2=wideCopyAVX512 pairs the two regardless of suffix.
}
// assembleFile assembles a parsed file for the given architecture and returns the image.
func assembleFile(path string, targetArch arch.Arch, f *ast.File) (*asm.Image, error) {
func assembleFile(targetArch arch.Arch, f *ast.File) (*asm.Image, error) {
switch targetArch {
case arch.AMD64:
return asm.AssembleFile(f)
@@ -668,7 +668,7 @@ func assemblePath(path string) (*asm.Image, error) {
if len(errs) > 0 {
return nil, fmt.Errorf("parse errors")
}
return assembleFile(path, arch.FromFilename(path), f)
return assembleFile(arch.FromFilename(path), f)
}
// printByteDiff shows the first few byte differences between two code blocks.
@@ -688,18 +688,18 @@ func printByteDiff(a, b []byte) {
// cmdProfile shows the basic-block structure of functions in an assembly file.
func cmdProfile(args []string) int {
fs := newCommand("profile", "gasm profile <file.s>", `
flagSet := newCommand("profile", "gasm profile <file.s>", `
Show the basic-block structure of functions in an assembly file.
Lists each function's labels, their offsets, and the block boundaries.
This is the static structure; for runtime execution counts, use
gasm verify --fuzz which exercises the code paths.
`)
fs.Parse(args)
if fs.NArg() != 1 {
flagSet.Parse(args)
if flagSet.NArg() != 1 {
fmt.Fprintln(os.Stderr, "usage: gasm profile <file.s>")
return 2
}
path := fs.Arg(0)
path := flagSet.Arg(0)
// Load the file to get function metadata.
k, err := verify.Load(path)
@@ -1021,7 +1021,7 @@ func cmdVerifyARM64(path string, groundTruth, profile bool) int {
}
func cmdVerify(args []string) int {
fs := newCommand("verify", "gasm verify [-smoke] [-abi] [-fuzz] [-ground-truth] [-profile] [-call] <file.s>", `
set := newCommand("verify", "gasm verify [-smoke] [-abi] [-fuzz] [-ground-truth] [-profile] [-call] <file.s>", `
Assemble FILE (amd64), map it into executable memory and report the available
functions. This confirms the assembled image is self-consistent (no
unresolved external symbols) and executable — the prerequisite for dynamic
@@ -1047,25 +1047,25 @@ With -call, a single function is invoked with user-supplied buffers (-buf)
instead of the smoke/abi/fuzz sweeps. Useful for partial functions (e.g.
decoders) that crash on random input but should succeed on valid data.
`)
smoke := fs.Bool("smoke", false, "call each NOSPLIT function with zeroed args")
abi := fs.Bool("abi", false, "run ABI-checking calls (sentinel registers + red zone)")
abiN := fs.Int("abi-n", 100, "number of ABI check iterations with varied inputs")
profile := fs.Bool("profile", false, "list basic-block structure per function")
groundTruth := fs.Bool("ground-truth", false, "compare machine code byte-for-byte against go tool asm")
fuzz := fs.Bool("fuzz", false, "differential fuzz: JIT both gasm and go-tool-asm versions, compare outputs")
fuzzN := fs.Int("n", 1000, "number of fuzz iterations per function")
fuzzOne := fs.String("fuzz-one", "", "") // hidden: fuzz a single function (subprocess mode)
sweepOne := fs.String("sweep-one", "", "") // hidden: smoke/abi a single function (subprocess mode)
call := fs.String("call", "", "call a single function with -buf instead of the sweeps")
bufSpec := fs.String("buf", "", "buffer spec for -call: name:size:pattern[,name:size:pattern] (zero, ones, seq, or hex)")
scalarSpec := fs.String("args", "", "scalar args for -call: name=value[,name=value] (decimal or 0x hex)")
repeat := fs.Int("repeat", 1, "number of times to repeat a -call invocation")
fs.Parse(args)
if fs.NArg() != 1 {
smoke := set.Bool("smoke", false, "call each NOSPLIT function with zeroed args")
abi := set.Bool("abi", false, "run ABI-checking calls (sentinel registers + red zone)")
abiN := set.Int("abi-n", 100, "number of ABI check iterations with varied inputs")
profile := set.Bool("profile", false, "list basic-block structure per function")
groundTruth := set.Bool("ground-truth", false, "compare machine code byte-for-byte against go tool asm")
fuzz := set.Bool("fuzz", false, "differential fuzz: JIT both gasm and go-tool-asm versions, compare outputs")
fuzzN := set.Int("n", 1000, "number of fuzz iterations per function")
fuzzOne := set.String("fuzz-one", "", "") // hidden: fuzz a single function (subprocess mode)
sweepOne := set.String("sweep-one", "", "") // hidden: smoke/abi a single function (subprocess mode)
call := set.String("call", "", "call a single function with -buf instead of the sweeps")
bufSpec := set.String("buf", "", "buffer spec for -call: name:size:pattern[,name:size:pattern] (zero, ones, seq, or hex)")
scalarSpec := set.String("args", "", "scalar args for -call: name=value[,name=value] (decimal or 0x hex)")
repeat := set.Int("repeat", 1, "number of times to repeat a -call invocation")
set.Parse(args)
if set.NArg() != 1 {
fmt.Fprintln(os.Stderr, "usage: gasm verify [-smoke] [-abi] [-fuzz] [-ground-truth] [-profile] [-call] <file.s>")
return 2
}
path := fs.Arg(0)
path := set.Arg(0)
targetArch := arch.FromFilename(path)
switch targetArch {
case arch.AMD64: