feat(cli): add gasm profile command for basic-block structure
Assisted-by: DeepSeek V4 Pro
This commit is contained in:
@@ -16,6 +16,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
@@ -57,6 +58,8 @@ func main() {
|
|||||||
os.Exit(cmdDebug(os.Args[2:]))
|
os.Exit(cmdDebug(os.Args[2:]))
|
||||||
case "diff":
|
case "diff":
|
||||||
os.Exit(cmdDiff(os.Args[2:]))
|
os.Exit(cmdDiff(os.Args[2:]))
|
||||||
|
case "profile":
|
||||||
|
os.Exit(cmdProfile(os.Args[2:]))
|
||||||
case "lsp":
|
case "lsp":
|
||||||
os.Exit(cmdLSP(os.Args[2:]))
|
os.Exit(cmdLSP(os.Args[2:]))
|
||||||
case "version", "--version", "-V":
|
case "version", "--version", "-V":
|
||||||
@@ -118,6 +121,7 @@ func usage(w io.Writer) {
|
|||||||
{"verify", "JIT-assemble and run dynamic checks (amd64, riscv64)"},
|
{"verify", "JIT-assemble and run dynamic checks (amd64, riscv64)"},
|
||||||
{"debug", "interactive source-level debugger (amd64)"},
|
{"debug", "interactive source-level debugger (amd64)"},
|
||||||
{"diff", "compare machine code of two .s files"},
|
{"diff", "compare machine code of two .s files"},
|
||||||
|
{"profile", "show basic-block structure of functions"},
|
||||||
{"lsp", "run the language server over stdio"},
|
{"lsp", "run the language server over stdio"},
|
||||||
{"version", "print the version (same as --version)"},
|
{"version", "print the version (same as --version)"},
|
||||||
}
|
}
|
||||||
@@ -637,6 +641,67 @@ 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>", `
|
||||||
|
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 {
|
||||||
|
fmt.Fprintln(os.Stderr, "usage: gasm profile <file.s>")
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
path := fs.Arg(0)
|
||||||
|
|
||||||
|
// Load the file to get function metadata.
|
||||||
|
k, err := verify.Load(path)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "gasm profile: %v\n", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
defer k.Close()
|
||||||
|
|
||||||
|
for _, name := range k.FuncNames() {
|
||||||
|
fl, err := k.Func(name)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Printf("%s: %d bytes, args=%d, frame=%d", name, fl.Size, fl.Args, fl.Frame)
|
||||||
|
if fl.NoSplit {
|
||||||
|
fmt.Printf(" NOSPLIT")
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
// Show labels and their offsets.
|
||||||
|
if len(fl.Labels) > 0 {
|
||||||
|
fmt.Println(" labels:")
|
||||||
|
// Sort labels by offset.
|
||||||
|
type labelOff struct {
|
||||||
|
name string
|
||||||
|
off int
|
||||||
|
}
|
||||||
|
var labels []labelOff
|
||||||
|
for name, off := range fl.Labels {
|
||||||
|
labels = append(labels, labelOff{name, off})
|
||||||
|
}
|
||||||
|
sort.Slice(labels, func(i, j int) bool { return labels[i].off < labels[j].off })
|
||||||
|
for _, l := range labels {
|
||||||
|
fmt.Printf(" %-20s +%#04x\n", l.name, l.off)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show basic blocks.
|
||||||
|
blocks, err := k.Blocks(name)
|
||||||
|
if err == nil && len(blocks) > 0 {
|
||||||
|
fmt.Printf(" basic blocks: %d\n", len(blocks))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
// cmdVerifyRISCV handles the verify subcommand for RISC-V files.
|
// cmdVerifyRISCV handles the verify subcommand for RISC-V files.
|
||||||
// JIT requires RISC-V hardware; only ground-truth and profile are available.
|
// JIT requires RISC-V hardware; only ground-truth and profile are available.
|
||||||
func cmdVerifyRISCV(path string, groundTruth, profile bool) int {
|
func cmdVerifyRISCV(path string, groundTruth, profile bool) int {
|
||||||
|
|||||||
Reference in New Issue
Block a user