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 "honnef.co/go/tools/go/ir"
16 "honnef.co/go/tools/go/ir/irutil"
18 "golang.org/x/tools/go/buildutil"
19 "golang.org/x/tools/go/packages"
24 mode = ir.BuilderMode(ir.PrintPackages | ir.PrintFunctions)
25 testFlag = flag.Bool("test", false, "include implicit test packages and executables")
26 cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
32 flag.Var(&mode, "build", ir.BuilderModeDoc)
33 flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
34 flag.BoolVar(&dot, "dot", false, "Print Graphviz dot of CFG")
35 flag.StringVar(&html, "html", "", "Print HTML for 'function'")
38 const usage = `IR builder.
39 Usage: irdump [-build=[DBCSNFL]] [-test] [-arg=...] package...
40 Use -help flag to display options.
43 % irdump -build=F hello.go # dump IR form of a single package
44 % irdump -build=F -test fmt # dump IR form of a package and its tests
48 if err := doMain(); err != nil {
49 fmt.Fprintf(os.Stderr, "irdump: %s\n", err)
56 if len(flag.Args()) == 0 {
57 fmt.Fprint(os.Stderr, usage)
61 cfg := &packages.Config{
62 Mode: packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedDeps | packages.NeedTypes | packages.NeedTypesSizes | packages.NeedSyntax | packages.NeedTypesInfo,
67 if *cpuprofile != "" {
68 f, err := os.Create(*cpuprofile)
70 fmt.Fprintln(os.Stderr, err)
73 pprof.StartCPUProfile(f)
74 defer pprof.StopCPUProfile()
77 // Load, parse and type-check the initial packages.
78 initial, err := packages.Load(cfg, flag.Args()...)
82 if len(initial) == 0 {
83 return fmt.Errorf("no packages")
85 if packages.PrintErrors(initial) > 0 {
86 return fmt.Errorf("packages contain errors")
89 // Create IR-form program representation.
90 _, pkgs := irutil.Packages(initial, mode, &irutil.Options{PrintFunc: html})
92 for i, p := range pkgs {
94 return fmt.Errorf("cannot build IR for package %s", initial[i])
98 // Build and display only the initial packages
99 // (and synthetic wrappers).
100 for _, p := range pkgs {
105 for _, p := range pkgs {
106 for _, m := range p.Members {
107 if fn, ok := m.(*ir.Function); ok {
108 fmt.Println("digraph{")
109 fmt.Printf("label = %q;\n", fn.Name())
110 for _, b := range fn.Blocks {
111 fmt.Printf("n%d [label=\"%d: %s\"]\n", b.Index, b.Index, b.Comment)
112 for _, succ := range b.Succs {
113 fmt.Printf("n%d -> n%d\n", b.Index, succ.Index)