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.
17 "honnef.co/go/tools/go/ir"
18 "honnef.co/go/tools/go/ir/irutil"
20 "golang.org/x/tools/go/packages"
28 const message = "Hello, World!"
35 // This program demonstrates how to run the IR builder on a single
36 // package of one or more already-parsed files. Its dependencies are
37 // loaded from compiler export data. This is what you'd typically use
38 // for a compiler; it does not depend on golang.org/x/tools/go/loader.
40 // It shows the printed representation of packages, functions, and
41 // instructions. Within the function listing, the name of each
42 // BasicBlock such as ".0.entry" is printed left-aligned, followed by
43 // the block's Instructions.
45 // For each instruction that defines an IR virtual register
46 // (i.e. implements Value), the type of that value is shown in the
49 // Build and run the irdump.go program if you want a standalone tool
50 // with similar functionality. It is located at
51 // honnef.co/go/tools/internal/cmd/irdump.
53 func Example_buildPackage() {
54 // Parse the source files.
55 fset := token.NewFileSet()
56 f, err := parser.ParseFile(fset, "hello.go", hello, parser.ParseComments)
58 fmt.Print(err) // parse error
61 files := []*ast.File{f}
63 // Create the type-checker's package.
64 pkg := types.NewPackage("hello", "")
66 // Type-check the package, load dependencies.
67 // Create and build the IR program.
68 hello, _, err := irutil.BuildPackage(
69 &types.Config{Importer: importer.Default()}, fset, pkg, files, ir.SanityCheckFunctions)
71 fmt.Print(err) // type error in some package
75 // Print out the package.
76 hello.WriteTo(os.Stdout)
78 // Print out the package-level functions.
79 hello.Func("init").WriteTo(os.Stdout)
80 hello.Func("main").WriteTo(os.Stdout)
85 // var init$guard bool
87 // const message message = Const <untyped string> {"Hello, World!"}
91 // # Synthetic: package initializer
94 // t1 = Const <bool> {true}
95 // t2 = Load <bool> init$guard
101 // b2: ← b0 # init.start
102 // Store {bool} init$guard t1
103 // t6 = Call <()> fmt.init
106 // # Name: hello.main
108 // # Location: hello.go:8:1
111 // t1 = Const <string> {"Hello, World!"}
112 // t2 = Const <int> {0}
113 // t3 = HeapAlloc <*[1]interface{}>
114 // t4 = IndexAddr <*interface{}> t3 t2
115 // t5 = MakeInterface <interface{}> t1
116 // Store {interface{}} t4 t5
117 // t7 = Slice <[]interface{}> t3 <nil> <nil> <nil>
118 // t8 = Call <(n int, err error)> fmt.Println t7
125 // This example builds IR code for a set of packages using the
126 // x/tools/go/packages API. This is what you would typically use for a
127 // analysis capable of operating on a single package.
128 func Example_loadPackages() {
129 // Load, parse, and type-check the initial packages.
130 cfg := &packages.Config{Mode: packages.LoadSyntax}
131 initial, err := packages.Load(cfg, "fmt", "net/http")
136 // Stop if any package had errors.
137 // This step is optional; without it, the next step
138 // will create IR for only a subset of packages.
139 if packages.PrintErrors(initial) > 0 {
140 log.Fatalf("packages contain errors")
143 // Create IR packages for all well-typed packages.
144 prog, pkgs := irutil.Packages(initial, ir.PrintPackages, nil)
147 // Build IR code for the well-typed initial packages.
148 for _, p := range pkgs {
155 // This example builds IR code for a set of packages plus all their dependencies,
156 // using the x/tools/go/packages API.
157 // This is what you'd typically use for a whole-program analysis.
158 func Example_loadWholeProgram() {
159 // Load, parse, and type-check the whole program.
160 cfg := packages.Config{Mode: packages.LoadAllSyntax}
161 initial, err := packages.Load(&cfg, "fmt", "net/http")
166 // Create IR packages for well-typed packages and their dependencies.
167 prog, pkgs := irutil.AllPackages(initial, ir.PrintPackages, nil)
170 // Build IR code for the whole program.