2013-08-27 16:49:13 -06:00
|
|
|
// 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.
|
|
|
|
|
2013-05-17 15:02:47 -06:00
|
|
|
package ssa_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2013-09-04 11:15:49 -06:00
|
|
|
"go/build"
|
2013-05-17 15:02:47 -06:00
|
|
|
"go/parser"
|
|
|
|
"os"
|
2013-09-04 11:15:49 -06:00
|
|
|
|
|
|
|
"code.google.com/p/go.tools/importer"
|
|
|
|
"code.google.com/p/go.tools/ssa"
|
2013-05-17 15:02:47 -06:00
|
|
|
)
|
|
|
|
|
2013-05-17 15:33:09 -06:00
|
|
|
// This program demonstrates how to run the SSA builder on a "Hello,
|
|
|
|
// World!" program and shows the printed representation of packages,
|
|
|
|
// functions and instructions.
|
|
|
|
//
|
|
|
|
// Within the function listing, the name of each BasicBlock such as
|
|
|
|
// ".0.entry" is printed left-aligned, followed by the block's
|
|
|
|
// Instructions.
|
|
|
|
//
|
|
|
|
// For each instruction that defines an SSA virtual register
|
|
|
|
// (i.e. implements Value), the type of that value is shown in the
|
|
|
|
// right column.
|
|
|
|
//
|
|
|
|
// Build and run the ssadump.go program in this package if you want a
|
|
|
|
// standalone tool with similar functionality.
|
|
|
|
//
|
2013-05-17 15:02:47 -06:00
|
|
|
func Example() {
|
|
|
|
const hello = `
|
|
|
|
package main
|
|
|
|
|
|
|
|
import "fmt"
|
|
|
|
|
2013-05-17 15:33:09 -06:00
|
|
|
const message = "Hello, World!"
|
|
|
|
|
2013-05-17 15:02:47 -06:00
|
|
|
func main() {
|
2013-05-17 15:33:09 -06:00
|
|
|
fmt.Println(message)
|
2013-05-17 15:02:47 -06:00
|
|
|
}
|
|
|
|
`
|
2013-05-31 14:14:13 -06:00
|
|
|
// Construct an importer. Imports will be loaded as if by 'go build'.
|
2013-09-04 11:15:49 -06:00
|
|
|
imp := importer.New(&importer.Config{Build: &build.Default})
|
2013-05-17 15:02:47 -06:00
|
|
|
|
|
|
|
// Parse the input file.
|
2013-10-08 08:34:36 -06:00
|
|
|
file, err := parser.ParseFile(imp.Fset, "hello.go", hello, 0)
|
2013-05-17 15:02:47 -06:00
|
|
|
if err != nil {
|
2013-09-06 16:13:57 -06:00
|
|
|
fmt.Print(err) // parse error
|
2013-05-17 15:02:47 -06:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2013-10-10 10:37:49 -06:00
|
|
|
// Create single-file main package and import its dependencies.
|
|
|
|
mainInfo := imp.CreatePackage("main", file)
|
2013-05-17 15:02:47 -06:00
|
|
|
|
2013-06-03 14:46:57 -06:00
|
|
|
// Create SSA-form program representation.
|
|
|
|
var mode ssa.BuilderMode
|
|
|
|
prog := ssa.NewProgram(imp.Fset, mode)
|
2013-09-06 16:13:57 -06:00
|
|
|
if err := prog.CreatePackages(imp); err != nil {
|
|
|
|
fmt.Print(err) // type error in some package
|
|
|
|
return
|
2013-07-18 14:59:06 -06:00
|
|
|
}
|
2013-09-06 16:13:57 -06:00
|
|
|
mainPkg := prog.Package(mainInfo.Pkg)
|
2013-05-31 14:14:13 -06:00
|
|
|
|
2013-05-17 15:33:09 -06:00
|
|
|
// Print out the package.
|
|
|
|
mainPkg.DumpTo(os.Stdout)
|
|
|
|
|
2013-05-17 15:02:47 -06:00
|
|
|
// Build SSA code for bodies of functions in mainPkg.
|
2013-06-03 14:46:57 -06:00
|
|
|
mainPkg.Build()
|
2013-05-17 15:02:47 -06:00
|
|
|
|
|
|
|
// Print out the package-level functions.
|
2013-07-10 16:37:52 -06:00
|
|
|
mainPkg.Func("init").DumpTo(os.Stdout)
|
|
|
|
mainPkg.Func("main").DumpTo(os.Stdout)
|
2013-05-17 15:02:47 -06:00
|
|
|
|
|
|
|
// Output:
|
2013-05-17 15:33:09 -06:00
|
|
|
//
|
2013-05-31 14:14:13 -06:00
|
|
|
// package main:
|
2013-07-10 23:14:40 -06:00
|
|
|
// func init func()
|
2013-05-22 15:56:18 -06:00
|
|
|
// var init$guard *bool
|
|
|
|
// func main func()
|
|
|
|
// const message message = "Hello, World!":untyped string
|
2013-05-17 15:33:09 -06:00
|
|
|
//
|
|
|
|
// # Name: main.init
|
2013-07-03 15:57:20 -06:00
|
|
|
// # Synthetic: package initializer
|
2013-05-17 15:33:09 -06:00
|
|
|
// func init():
|
|
|
|
// .0.entry: P:0 S:2
|
2013-05-22 15:56:18 -06:00
|
|
|
// t0 = *init$guard bool
|
2013-05-17 15:33:09 -06:00
|
|
|
// if t0 goto 2.init.done else 1.init.start
|
|
|
|
// .1.init.start: P:1 S:1
|
2013-05-22 15:56:18 -06:00
|
|
|
// *init$guard = true:bool
|
2013-05-17 15:33:09 -06:00
|
|
|
// t1 = fmt.init() ()
|
|
|
|
// jump 2.init.done
|
|
|
|
// .2.init.done: P:2 S:0
|
2013-10-08 10:31:39 -06:00
|
|
|
// return
|
2013-05-17 15:33:09 -06:00
|
|
|
//
|
2013-05-17 15:02:47 -06:00
|
|
|
// # Name: main.main
|
2013-07-03 15:57:20 -06:00
|
|
|
// # Location: hello.go:8:6
|
2013-05-17 15:02:47 -06:00
|
|
|
// func main():
|
2013-05-17 15:33:09 -06:00
|
|
|
// .0.entry: P:0 S:0
|
2013-08-01 12:06:10 -06:00
|
|
|
// t0 = new [1]interface{} (varargs) *[1]interface{}
|
|
|
|
// t1 = &t0[0:untyped integer] *interface{}
|
|
|
|
// t2 = make interface{} <- string ("Hello, World!":string) interface{}
|
|
|
|
// *t1 = t2
|
|
|
|
// t3 = slice t0[:] []interface{}
|
|
|
|
// t4 = fmt.Println(t3) (n int, err error)
|
2013-10-08 10:31:39 -06:00
|
|
|
// return
|
2013-05-17 15:02:47 -06:00
|
|
|
}
|