mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
code.google.com/p/go.tools/ssa: include ssa.Package and init() function in example output.
Also: - remove redundant text in doc.go. - fix (yet more) cases of missing parens in Printf, fallout from go/types accessors refactoring. - don't mix spaces and tabs within lines printed by ssa.Function.DumpTo: it makes it too hard to constructed expected outputs for tests. (Tabs may appear at line start though.) Sadly godoc -play won't run this program; it complains it can't import "code.google.com/p/go.exp/ssa". Any idea why? R=gri CC=golang-dev https://golang.org/cl/9481044
This commit is contained in:
parent
87334f402b
commit
113d6d30b1
51
ssa/doc.go
51
ssa/doc.go
@ -107,56 +107,6 @@
|
||||
// either accurate or unambiguous. The public API exposes a number of
|
||||
// name-based maps for client convenience.
|
||||
//
|
||||
// Given a Go source package such as this:
|
||||
//
|
||||
// package main
|
||||
//
|
||||
// import "fmt"
|
||||
//
|
||||
// const message = "Hello, World!"
|
||||
//
|
||||
// func main() {
|
||||
// fmt.Println(message)
|
||||
// }
|
||||
//
|
||||
// The SSA Builder creates a *Program containing a main *Package such
|
||||
// as this:
|
||||
//
|
||||
// Package (Name: "main")
|
||||
// Members:
|
||||
// "message": *Constant (Type: untyped string, Value: "Hello, World!")
|
||||
// "init·guard": *Global (Type: *bool)
|
||||
// "main": *Function (Type: func())
|
||||
// Init: *Function (Type: func())
|
||||
//
|
||||
// The printed representation of the function main.main is shown
|
||||
// below. 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.
|
||||
//
|
||||
// # Name: main.main
|
||||
// # Declared at hello.go:7:6
|
||||
// func main():
|
||||
// .0.entry:
|
||||
// t0 = new [1]interface{} *[1]interface{}
|
||||
// t1 = &t0[0:untyped integer] *interface{}
|
||||
// t2 = make interface interface{} <- string ("Hello, World!":string) interface{}
|
||||
// *t1 = t2
|
||||
// t3 = slice t0[:] []interface{}
|
||||
// t4 = fmt.Println(t3) (n int, err error)
|
||||
// ret
|
||||
//
|
||||
//
|
||||
// The ssadump utility is an example of an application that loads and
|
||||
// dumps the SSA form of a Go program, whether a single package or a
|
||||
// whole program.
|
||||
//
|
||||
// TODO(adonovan): demonstrate more features in the example:
|
||||
// parameters and control flow at the least.
|
||||
//
|
||||
// TODO(adonovan): Consider the exceptional control-flow implications
|
||||
// of defer and recover().
|
||||
//
|
||||
@ -174,4 +124,5 @@
|
||||
// flexibility. For example, analysis tools may wish to construct a
|
||||
// fake ssa.Function for the root of the callgraph, a fake "reflect"
|
||||
// package, etc.
|
||||
//
|
||||
package ssa
|
||||
|
@ -8,15 +8,31 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// This example demonstrates the SSA builder.
|
||||
// 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("Hello, World!")
|
||||
fmt.Println(message)
|
||||
}
|
||||
`
|
||||
|
||||
@ -26,21 +42,26 @@ func main() {
|
||||
// Parse the input file.
|
||||
file, err := parser.ParseFile(builder.Prog.Files, "hello.go", hello, parser.DeclarationErrors)
|
||||
if err != nil {
|
||||
fmt.Printf("Parsing failed: %s\n", err.Error())
|
||||
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("Type-checking failed: %s\n", err.Error())
|
||||
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)
|
||||
@ -48,10 +69,29 @@ func main() {
|
||||
}
|
||||
|
||||
// Output:
|
||||
//
|
||||
// Package main:
|
||||
// var init·guard *bool
|
||||
// func main func()
|
||||
// const message message = "Hello, World!":untyped string
|
||||
//
|
||||
// # Name: main.init
|
||||
// # Declared at -
|
||||
// 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:6:6
|
||||
// # Declared at hello.go:8:6
|
||||
// func main():
|
||||
// .0.entry: P:0 S:0
|
||||
// .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{}
|
||||
|
@ -554,13 +554,17 @@ func (f *Function) DumpTo(w io.Writer) {
|
||||
io.WriteString(w, "\t(external)\n")
|
||||
}
|
||||
|
||||
// NB. column calculations are confused by non-ASCII characters.
|
||||
const punchcard = 80 // for old time's sake.
|
||||
for _, b := range f.Blocks {
|
||||
if b == nil {
|
||||
// Corrupt CFG.
|
||||
fmt.Fprintf(w, ".nil:\n")
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(w, ".%s:\t\t\t\t\t\t\t P:%d S:%d\n", b, len(b.Preds), len(b.Succs))
|
||||
n, _ := fmt.Fprintf(w, ".%s:", b)
|
||||
fmt.Fprintf(w, "%*sP:%d S:%d\n", punchcard-1-n-len("P:n S:n"), "", len(b.Preds), len(b.Succs))
|
||||
|
||||
if false { // CFG debugging
|
||||
fmt.Fprintf(w, "\t# CFG: %s --> %s --> %s\n", b.Preds, b, b.Succs)
|
||||
}
|
||||
@ -568,7 +572,7 @@ func (f *Function) DumpTo(w io.Writer) {
|
||||
io.WriteString(w, "\t")
|
||||
switch v := instr.(type) {
|
||||
case Value:
|
||||
l := 80 // for old time's sake.
|
||||
l := punchcard
|
||||
// Left-align the instruction.
|
||||
if name := v.Name(); name != "" {
|
||||
n, _ := fmt.Fprintf(w, "%s = ", name)
|
||||
|
@ -17,7 +17,7 @@ func (id Id) String() string {
|
||||
if id.Pkg == nil {
|
||||
return id.Name
|
||||
}
|
||||
return fmt.Sprintf("%s/%s", id.Pkg.Path, id.Name)
|
||||
return fmt.Sprintf("%s/%s", id.Pkg.Path(), id.Name)
|
||||
}
|
||||
|
||||
// relName returns the name of v relative to i.
|
||||
@ -360,7 +360,7 @@ func (p *Package) String() string {
|
||||
}
|
||||
|
||||
func (p *Package) DumpTo(w io.Writer) {
|
||||
fmt.Fprintf(w, "Package %s:\n", p.Types.Path)
|
||||
fmt.Fprintf(w, "Package %s:\n", p.Types.Path())
|
||||
|
||||
var names []string
|
||||
maxname := 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user