Skip to content

Instantly share code, notes, and snippets.

@ksurent
Last active December 16, 2023 17:30
Show Gist options
  • Save ksurent/ba316c7e5ccfad0259cd69beb53f87d7 to your computer and use it in GitHub Desktop.
Save ksurent/ba316c7e5ccfad0259cd69beb53f87d7 to your computer and use it in GitHub Desktop.
Print Go's SSA form, much like ssadump but with concrete types
package main
import (
"flag"
"fmt"
"go/build"
"go/types"
"os"
"golang.org/x/tools/go/loader"
"golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/ssautil"
)
func main() {
if err := doMain(); err != nil {
fmt.Fprintf(os.Stderr, "ssadump: %s\n", err)
os.Exit(1)
}
}
func doMain() error {
flag.Parse()
args := flag.Args()
if len(args) == 0 {
fmt.Fprintln(os.Stderr, "need packages")
os.Exit(1)
}
conf := loader.Config{Build: &build.Default}
if _, err := conf.FromArgs(args, false); err != nil {
return err
}
goprog, err := conf.Load()
if err != nil {
return err
}
ssaprog := ssautil.CreateProgram(goprog, 0)
ssaprog.Build()
initial := goprog.InitialPackages()
initialMap := make(map[*types.Package]struct{}, len(initial))
for _, pi := range initial {
initialMap[pi.Pkg] = struct{}{}
}
for fn, _ := range ssautil.AllFunctions(ssaprog) {
if fn.Pkg == nil {
continue
}
if _, ok := initialMap[fn.Pkg.Pkg]; !ok {
continue
}
fmt.Println(fn.String())
for _, b := range fn.Blocks {
fmt.Printf("%s:\n", b.String())
for _, i := range b.Instrs {
if v, ok := i.(ssa.Value); ok {
fmt.Printf("\t[%-20T] %s = %s\n", i, v.Name(), i)
} else {
fmt.Printf("\t[%-20T] %s\n", i, i)
}
}
}
}
return nil
}
@maxim-ge
Copy link

Thanks a lot for this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment