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 "golang.org/x/tools/go/packages"
18 "golang.org/x/tools/go/ssa"
19 "golang.org/x/tools/go/ssa/ssautil"
27 const message = "Hello, World!"
34 // This program demonstrates how to run the SSA builder on a single
35 // package of one or more already-parsed files. Its dependencies are
36 // loaded from compiler export data. This is what you'd typically use
37 // for a compiler; it does not depend on golang.org/x/tools/go/loader.
39 // It shows the printed representation of packages, functions, and
40 // instructions. Within the function listing, the name of each
41 // BasicBlock such as ".0.entry" is printed left-aligned, followed by
42 // the block's Instructions.
44 // For each instruction that defines an SSA virtual register
45 // (i.e. implements Value), the type of that value is shown in the
48 // Build and run the ssadump.go program if you want a standalone tool
49 // with similar functionality. It is located at
50 // golang.org/x/tools/cmd/ssadump.
52 func Example_buildPackage() {
53 // Parse the source files.
54 fset := token.NewFileSet()
55 f, err := parser.ParseFile(fset, "hello.go", hello, parser.ParseComments)
57 fmt.Print(err) // parse error
60 files := []*ast.File{f}
62 // Create the type-checker's package.
63 pkg := types.NewPackage("hello", "")
65 // Type-check the package, load dependencies.
66 // Create and build the SSA program.
67 hello, _, err := ssautil.BuildPackage(
68 &types.Config{Importer: importer.Default()}, fset, pkg, files, ssa.SanityCheckFunctions)
70 fmt.Print(err) // type error in some package
74 // Print out the package.
75 hello.WriteTo(os.Stdout)
77 // Print out the package-level functions.
78 hello.Func("init").WriteTo(os.Stdout)
79 hello.Func("main").WriteTo(os.Stdout)
85 // var init$guard bool
87 // const message message = "Hello, World!":untyped string
91 // # Synthetic: package initializer
94 // t0 = *init$guard bool
95 // if t0 goto 2 else 1
96 // 1: init.start P:1 S:1
97 // *init$guard = true:bool
100 // 2: init.done P:2 S:0
103 // # Name: hello.main
105 // # Location: hello.go:8:6
108 // t0 = new [1]interface{} (varargs) *[1]interface{}
109 // t1 = &t0[0:int] *interface{}
110 // t2 = make interface{} <- string ("Hello, World!":string) interface{}
112 // t3 = slice t0[:] []interface{}
113 // t4 = fmt.Println(t3...) (n int, err error)
117 // This example builds SSA code for a set of packages using the
118 // x/tools/go/packages API. This is what you would typically use for a
119 // analysis capable of operating on a single package.
120 func Example_loadPackages() {
121 // Load, parse, and type-check the initial packages.
122 cfg := &packages.Config{Mode: packages.LoadSyntax}
123 initial, err := packages.Load(cfg, "fmt", "net/http")
128 // Stop if any package had errors.
129 // This step is optional; without it, the next step
130 // will create SSA for only a subset of packages.
131 if packages.PrintErrors(initial) > 0 {
132 log.Fatalf("packages contain errors")
135 // Create SSA packages for all well-typed packages.
136 prog, pkgs := ssautil.Packages(initial, ssa.PrintPackages)
139 // Build SSA code for the well-typed initial packages.
140 for _, p := range pkgs {
147 // This example builds SSA code for a set of packages plus all their dependencies,
148 // using the x/tools/go/packages API.
149 // This is what you'd typically use for a whole-program analysis.
150 func Example_loadWholeProgram() {
151 // Load, parse, and type-check the whole program.
152 cfg := packages.Config{Mode: packages.LoadAllSyntax}
153 initial, err := packages.Load(&cfg, "fmt", "net/http")
158 // Create SSA packages for well-typed packages and their dependencies.
159 prog, pkgs := ssautil.AllPackages(initial, ssa.PrintPackages)
162 // Build SSA code for the whole program.