--- /dev/null
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// irdump: a tool for displaying the IR form of Go programs.
+package main
+
+import (
+ "flag"
+ "fmt"
+ "go/build"
+ "os"
+ "runtime/pprof"
+
+ "golang.org/x/tools/go/buildutil"
+ "golang.org/x/tools/go/packages"
+ "honnef.co/go/tools/ir"
+ "honnef.co/go/tools/ir/irutil"
+)
+
+// flags
+var (
+ mode = ir.BuilderMode(ir.PrintPackages | ir.PrintFunctions)
+ testFlag = flag.Bool("test", false, "include implicit test packages and executables")
+ cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
+ dot bool
+ html string
+)
+
+func init() {
+ flag.Var(&mode, "build", ir.BuilderModeDoc)
+ flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
+ flag.BoolVar(&dot, "dot", false, "Print Graphviz dot of CFG")
+ flag.StringVar(&html, "html", "", "Print HTML for 'function'")
+}
+
+const usage = `IR builder.
+Usage: irdump [-build=[DBCSNFL]] [-test] [-arg=...] package...
+Use -help flag to display options.
+
+Examples:
+% irdump -build=F hello.go # dump IR form of a single package
+% irdump -build=F -test fmt # dump IR form of a package and its tests
+`
+
+func main() {
+ if err := doMain(); err != nil {
+ fmt.Fprintf(os.Stderr, "irdump: %s\n", err)
+ os.Exit(1)
+ }
+}
+
+func doMain() error {
+ flag.Parse()
+ if len(flag.Args()) == 0 {
+ fmt.Fprint(os.Stderr, usage)
+ os.Exit(1)
+ }
+
+ cfg := &packages.Config{
+ Mode: packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedDeps | packages.NeedTypes | packages.NeedTypesSizes | packages.NeedSyntax | packages.NeedTypesInfo,
+ Tests: *testFlag,
+ }
+
+ // Profiling support.
+ if *cpuprofile != "" {
+ f, err := os.Create(*cpuprofile)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ pprof.StartCPUProfile(f)
+ defer pprof.StopCPUProfile()
+ }
+
+ // Load, parse and type-check the initial packages.
+ initial, err := packages.Load(cfg, flag.Args()...)
+ if err != nil {
+ return err
+ }
+ if len(initial) == 0 {
+ return fmt.Errorf("no packages")
+ }
+ if packages.PrintErrors(initial) > 0 {
+ return fmt.Errorf("packages contain errors")
+ }
+
+ // Create IR-form program representation.
+ _, pkgs := irutil.Packages(initial, mode, &irutil.Options{PrintFunc: html})
+
+ for i, p := range pkgs {
+ if p == nil {
+ return fmt.Errorf("cannot build IR for package %s", initial[i])
+ }
+ }
+
+ // Build and display only the initial packages
+ // (and synthetic wrappers).
+ for _, p := range pkgs {
+ p.Build()
+ }
+
+ if dot {
+ for _, p := range pkgs {
+ for _, m := range p.Members {
+ if fn, ok := m.(*ir.Function); ok {
+ fmt.Println("digraph{")
+ fmt.Printf("label = %q;\n", fn.Name())
+ for _, b := range fn.Blocks {
+ fmt.Printf("n%d [label=\"%d: %s\"]\n", b.Index, b.Index, b.Comment)
+ for _, succ := range b.Succs {
+ fmt.Printf("n%d -> n%d\n", b.Index, succ.Index)
+ }
+ }
+ fmt.Println("}")
+ }
+ }
+ }
+ }
+ return nil
+}