mirror of
https://github.com/golang/go
synced 2024-11-18 07:24:45 -07:00
8cdf1f1cb1
Extracted Builder.findMethod function to handle methodset/receiver logic common to function calls (Builder.setCall) and bound method closure creation (Builder.selector). Capture: added explicit Name, Type fields to Capture instead of relying on Outer field, which is now un-exported since its only purpose is to let Builder.expr(case *ast.FuncLit) know which values to put in the closure; it is nilled immediately after. Simplified Function.lookup() logic: there's no need to walk the Outer chain each time to set Alloc.Heap=true, as it's already set during creation of the outermost Capture{outer:*Alloc}. Added interp/testdata/boundmeth.go test. Cosmetic changes: - add support for bound method thunks to Function.FullName(). - Simplified {Literal,Global,Builtin,Function}.String() - doc: Captures are no longer necessarily addresses. - added yet another missing pair of "()" (go/types accessors). - print "Synthetic" not "Declared at -" for synthetic functions. - use '$' not center-dot in synthetic identifiers (easier to type). R=gri CC=golang-dev https://golang.org/cl/9654043
103 lines
2.9 KiB
Go
103 lines
2.9 KiB
Go
package ssa_test
|
|
|
|
import (
|
|
"code.google.com/p/go.tools/ssa"
|
|
"fmt"
|
|
"go/ast"
|
|
"go/parser"
|
|
"os"
|
|
)
|
|
|
|
// 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.
|
|
//
|
|
func Example() {
|
|
const hello = `
|
|
package main
|
|
|
|
import "fmt"
|
|
|
|
const message = "Hello, World!"
|
|
|
|
func main() {
|
|
fmt.Println(message)
|
|
}
|
|
`
|
|
|
|
// Construct a builder. Imports will be loaded as if by 'go build'.
|
|
builder := ssa.NewBuilder(&ssa.Context{Loader: ssa.MakeGoBuildLoader(nil)})
|
|
|
|
// Parse the input file.
|
|
file, err := parser.ParseFile(builder.Prog.Files, "hello.go", hello, parser.DeclarationErrors)
|
|
if err != nil {
|
|
fmt.Printf(err.Error()) // parse error
|
|
return
|
|
}
|
|
|
|
// Create a "main" package containing one file.
|
|
mainPkg, err := builder.CreatePackage("main", []*ast.File{file})
|
|
if err != nil {
|
|
fmt.Printf(err.Error()) // type error
|
|
return
|
|
}
|
|
|
|
// Print out the package.
|
|
mainPkg.DumpTo(os.Stdout)
|
|
fmt.Println()
|
|
|
|
// Build SSA code for bodies of functions in mainPkg.
|
|
builder.BuildPackage(mainPkg)
|
|
|
|
// Print out the package-level functions.
|
|
mainPkg.Init.DumpTo(os.Stdout)
|
|
for _, mem := range mainPkg.Members {
|
|
if fn, ok := mem.(*ssa.Function); ok {
|
|
fn.DumpTo(os.Stdout)
|
|
}
|
|
}
|
|
|
|
// Output:
|
|
//
|
|
// Package main:
|
|
// var init$guard *bool
|
|
// func main func()
|
|
// const message message = "Hello, World!":untyped string
|
|
//
|
|
// # Name: main.init
|
|
// # Synthetic
|
|
// func init():
|
|
// .0.entry: P:0 S:2
|
|
// t0 = *init$guard bool
|
|
// if t0 goto 2.init.done else 1.init.start
|
|
// .1.init.start: P:1 S:1
|
|
// *init$guard = true:bool
|
|
// t1 = fmt.init() ()
|
|
// jump 2.init.done
|
|
// .2.init.done: P:2 S:0
|
|
// ret
|
|
//
|
|
// # Name: main.main
|
|
// # Declared at hello.go:8:6
|
|
// func main():
|
|
// .0.entry: P:0 S:0
|
|
// a0 = new [1]interface{} *[1]interface{}
|
|
// t0 = &a0[0:untyped integer] *interface{}
|
|
// t1 = make interface interface{} <- string ("Hello, World!":string) interface{}
|
|
// *t0 = t1
|
|
// t2 = slice a0[:] []interface{}
|
|
// t3 = fmt.Println(t2) (n int, err error)
|
|
// ret
|
|
}
|