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  }