1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // irdump: a tool for displaying the IR form of Go programs.
15 "golang.org/x/tools/go/buildutil"
16 "golang.org/x/tools/go/packages"
17 "honnef.co/go/tools/ir"
18 "honnef.co/go/tools/ir/irutil"
23 mode = ir.BuilderMode(ir.PrintPackages | ir.PrintFunctions)
24 testFlag = flag.Bool("test", false, "include implicit test packages and executables")
25 cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
31 flag.Var(&mode, "build", ir.BuilderModeDoc)
32 flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
33 flag.BoolVar(&dot, "dot", false, "Print Graphviz dot of CFG")
34 flag.StringVar(&html, "html", "", "Print HTML for 'function'")
37 const usage = `IR builder.
38 Usage: irdump [-build=[DBCSNFL]] [-test] [-arg=...] package...
39 Use -help flag to display options.
42 % irdump -build=F hello.go # dump IR form of a single package
43 % irdump -build=F -test fmt # dump IR form of a package and its tests
47 if err := doMain(); err != nil {
48 fmt.Fprintf(os.Stderr, "irdump: %s\n", err)
55 if len(flag.Args()) == 0 {
56 fmt.Fprint(os.Stderr, usage)
60 cfg := &packages.Config{
61 Mode: packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedDeps | packages.NeedTypes | packages.NeedTypesSizes | packages.NeedSyntax | packages.NeedTypesInfo,
66 if *cpuprofile != "" {
67 f, err := os.Create(*cpuprofile)
69 fmt.Fprintln(os.Stderr, err)
72 pprof.StartCPUProfile(f)
73 defer pprof.StopCPUProfile()
76 // Load, parse and type-check the initial packages.
77 initial, err := packages.Load(cfg, flag.Args()...)
81 if len(initial) == 0 {
82 return fmt.Errorf("no packages")
84 if packages.PrintErrors(initial) > 0 {
85 return fmt.Errorf("packages contain errors")
88 // Create IR-form program representation.
89 _, pkgs := irutil.Packages(initial, mode, &irutil.Options{PrintFunc: html})
91 for i, p := range pkgs {
93 return fmt.Errorf("cannot build IR for package %s", initial[i])
97 // Build and display only the initial packages
98 // (and synthetic wrappers).
99 for _, p := range pkgs {
104 for _, p := range pkgs {
105 for _, m := range p.Members {
106 if fn, ok := m.(*ir.Function); ok {
107 fmt.Println("digraph{")
108 fmt.Printf("label = %q;\n", fn.Name())
109 for _, b := range fn.Blocks {
110 fmt.Printf("n%d [label=\"%d: %s\"]\n", b.Index, b.Index, b.Comment)
111 for _, succ := range b.Succs {
112 fmt.Printf("n%d -> n%d\n", b.Index, succ.Index)