github.com/golangci/go-tools@v0.0.0-20190318060251-af6baa5dc196/ssa/example_test.go (about) 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. 4 5 package ssa_test 6 7 import ( 8 "fmt" 9 "go/ast" 10 "go/importer" 11 "go/parser" 12 "go/token" 13 "go/types" 14 "os" 15 16 "golang.org/x/tools/go/loader" 17 "github.com/golangci/go-tools/ssa" 18 "github.com/golangci/go-tools/ssa/ssautil" 19 ) 20 21 const hello = ` 22 package main 23 24 import "fmt" 25 26 const message = "Hello, World!" 27 28 func main() { 29 fmt.Println(message) 30 } 31 ` 32 33 // This program demonstrates how to run the SSA builder on a single 34 // package of one or more already-parsed files. Its dependencies are 35 // loaded from compiler export data. This is what you'd typically use 36 // for a compiler; it does not depend on golang.org/x/tools/go/loader. 37 // 38 // It shows the printed representation of packages, functions, and 39 // instructions. Within the function listing, the name of each 40 // BasicBlock such as ".0.entry" is printed left-aligned, followed by 41 // the block's Instructions. 42 // 43 // For each instruction that defines an SSA virtual register 44 // (i.e. implements Value), the type of that value is shown in the 45 // right column. 46 // 47 // Build and run the ssadump.go program if you want a standalone tool 48 // with similar functionality. It is located at 49 // golang.org/x/tools/cmd/ssadump. 50 // 51 func ExampleBuildPackage() { 52 // Parse the source files. 53 fset := token.NewFileSet() 54 f, err := parser.ParseFile(fset, "hello.go", hello, parser.ParseComments) 55 if err != nil { 56 fmt.Print(err) // parse error 57 return 58 } 59 files := []*ast.File{f} 60 61 // Create the type-checker's package. 62 pkg := types.NewPackage("hello", "") 63 64 // Type-check the package, load dependencies. 65 // Create and build the SSA program. 66 hello, _, err := ssautil.BuildPackage( 67 &types.Config{Importer: importer.Default()}, fset, pkg, files, ssa.SanityCheckFunctions) 68 if err != nil { 69 fmt.Print(err) // type error in some package 70 return 71 } 72 73 // Print out the package. 74 hello.WriteTo(os.Stdout) 75 76 // Print out the package-level functions. 77 hello.Func("init").WriteTo(os.Stdout) 78 hello.Func("main").WriteTo(os.Stdout) 79 80 // Output: 81 // 82 // package hello: 83 // func init func() 84 // var init$guard bool 85 // func main func() 86 // const message message = "Hello, World!":untyped string 87 // 88 // # Name: hello.init 89 // # Package: hello 90 // # Synthetic: package initializer 91 // func init(): 92 // 0: entry P:0 S:2 93 // t0 = *init$guard bool 94 // if t0 goto 2 else 1 95 // 1: init.start P:1 S:1 96 // *init$guard = true:bool 97 // t1 = fmt.init() () 98 // jump 2 99 // 2: init.done P:2 S:0 100 // return 101 // 102 // # Name: hello.main 103 // # Package: hello 104 // # Location: hello.go:8:6 105 // func main(): 106 // 0: entry P:0 S:0 107 // t0 = new [1]interface{} (varargs) *[1]interface{} 108 // t1 = &t0[0:int] *interface{} 109 // t2 = make interface{} <- string ("Hello, World!":string) interface{} 110 // *t1 = t2 111 // t3 = slice t0[:] []interface{} 112 // t4 = fmt.Println(t3...) (n int, err error) 113 // return 114 } 115 116 // This program shows how to load a main package (cmd/cover) and all its 117 // dependencies from source, using the loader, and then build SSA code 118 // for the entire program. This is what you'd typically use for a 119 // whole-program analysis. 120 // 121 func ExampleLoadProgram() { 122 // Load cmd/cover and its dependencies. 123 var conf loader.Config 124 conf.Import("cmd/cover") 125 lprog, err := conf.Load() 126 if err != nil { 127 fmt.Print(err) // type error in some package 128 return 129 } 130 131 // Create SSA-form program representation. 132 prog := ssautil.CreateProgram(lprog, ssa.SanityCheckFunctions) 133 134 // Build SSA code for the entire cmd/cover program. 135 prog.Build() 136 137 // Output: 138 }