blob: 1ebbedc5709fc121b031f69716cee6c7cf44ce1a [file] [log] [blame]
// Package ssa defines a representation of the elements of Go programs
// (packages, types, functions, variables and constants) using a
// static single-assignment (SSA) form intermediate representation
// (IR) for the bodies of functions.
//
// THIS INTERFACE IS EXPERIMENTAL AND IS LIKELY TO CHANGE.
//
// For an introduction to SSA form, see
// http://en.wikipedia.org/wiki/Static_single_assignment_form.
// This page provides a broader reading list:
// http://www.dcs.gla.ac.uk/~jsinger/ssa.html.
//
// The level of abstraction of the SSA form is intentionally close to
// the source language to facilitate construction of source analysis
// tools. It is not primarily intended for machine code generation.
//
// All looping, branching and switching constructs are replaced with
// unstructured control flow. We may add higher-level control flow
// primitives in the future to facilitate constant-time dispatch of
// switch statements, for example.
//
// Builder encapsulates the tasks of type-checking (using go/types)
// abstract syntax trees (as defined by go/ast) for the source files
// comprising a Go program, and the conversion of each function from
// Go ASTs to the SSA representation.
//
// By supplying an instance of the SourceLocator function prototype,
// clients may control how the builder locates, loads and parses Go
// sources files for imported packages. This package provides
// MakeGoBuildLoader, which creates a loader that uses go/build to
// locate packages in the Go source distribution, and go/parser to
// parse them.
//
// The builder initially builds a naive SSA form in which all local
// variables are addresses of stack locations with explicit loads and
// stores. Registerisation of eligible locals and φ-node insertion
// using dominance and dataflow are then performed as a second pass
// called "lifting" to improve the accuracy and performance of
// subsequent analyses; this pass can be skipped by setting the
// NaiveForm builder flag.
//
// The primary interfaces of this package are:
//
// - Member: a named member of a Go package.
// - Value: an expression that yields a value.
// - Instruction: a statement that consumes values and performs computation.
//
// A computation that yields a result implements both the Value and
// Instruction interfaces. The following table shows for each
// concrete type which of these interfaces it implements.
//
// Value? Instruction? Member?
// *Alloc ✔ ✔
// *BinOp ✔ ✔
// *Builtin ✔ ✔
// *Call ✔ ✔
// *Capture ✔
// *ChangeInterface ✔ ✔
// *ChangeType ✔ ✔
// *Constant ✔ (const)
// *Convert ✔ ✔
// *Defer ✔
// *Extract ✔ ✔
// *Field ✔ ✔
// *FieldAddr ✔ ✔
// *Function ✔ ✔ (func)
// *Global ✔ ✔ (var)
// *Go ✔
// *If ✔
// *Index ✔ ✔
// *IndexAddr ✔ ✔
// *Jump ✔
// *Literal ✔
// *Lookup ✔ ✔
// *MakeChan ✔ ✔
// *MakeClosure ✔ ✔
// *MakeInterface ✔ ✔
// *MakeMap ✔ ✔
// *MakeSlice ✔ ✔
// *MapUpdate ✔
// *Next ✔ ✔
// *Panic ✔
// *Parameter ✔
// *Phi ✔ ✔
// *Range ✔ ✔
// *Ret ✔
// *RunDefers ✔
// *Select ✔ ✔
// *Slice ✔ ✔
// *Type ✔ (type)
// *TypeAssert ✔ ✔
// *UnOp ✔ ✔
//
// Other key types in this package include: Program, Package, Function
// and BasicBlock.
//
// The program representation constructed by this package is fully
// resolved internally, i.e. it does not rely on the names of Values,
// Packages, Functions, Types or BasicBlocks for the correct
// interpretation of the program. Only the identities of objects and
// the topology of the SSA and type graphs are semantically
// significant. (There is one exception: Ids, used to identify field
// and method names, contain strings.) Avoidance of name-based
// operations simplifies the implementation of subsequent passes and
// can make them very efficient. Many objects are nonetheless named
// to aid in debugging, but it is not essential that the names be
// 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().
//
// TODO(adonovan): Consider how token.Pos source location information
// should be made available generally. Currently it is only present
// in package Members and selected Instructions for which there is a
// direct source correspondence. We'll need to work harder to tie all
// defs/uses of named variables together, esp. because SSA splits them
// into separate webs.
//
// TODO(adonovan): it is practically impossible for clients to
// construct well-formed SSA functions/packages/programs directly; we
// assume this is the job of the ssa.Builder alone.
// Nonetheless it may be wise to give clients a little more
// 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