blob: 3b30b47504b8b1b8bc41ffdb625fd75d6f552cd1 [file] [log] [blame] [view]
This package contains the compiler's Static Single Assignment form
component. If you're not familiar with SSA, Wikipedia is a good starting
point:
https://en.wikipedia.org/wiki/Static_single_assignment_form
SSA is useful to perform transformations and optimizations, which can be
found in this package in the form of compiler passes and rewrite rules.
The former can be found in the "passes" array in compile.go, while the
latter are generated from gen/*.rules.
Like most other SSA forms, funcs consist of blocks and values. Values
perform an operation, which is encoded in the form of an operator and a
number of arguments. The semantics of each Op can be found in
gen/*Ops.go.
gen/* is used to generate code in the ssa package. This includes
opGen.go from gen/*Ops.go, and the rewrite*.go files from gen/*.rules.
To regenerate these files, see gen/README.
Blocks can have multiple forms. For example, BlockPlain will always hand
the control flow to another block, and BlockIf will flow to one of two
blocks depending on a value. See block.go for more details.
Values also have types. For example, a constant boolean value will have
a Bool type, and a variable definition value will have a memory type.
The memory type is special - it represents the global memory state. For
example, an Op that takes a memory argument depends on that memory
state, and an Op which has the memory type impacts the state of memory.
This is important so that memory operations are kept in the right order.
For example, take this program:
func f(a, b *int) {
*a = 3
*b = *a
}
The two generated stores may show up as follows:
v10 (4) = Store <mem> {int} v6 v8 v1
v14 (5) = Store <mem> {int} v7 v8 v10
Since the second store has a memory argument v10, it cannot be reordered
before the first store, which sets that global memory state. And the
logic translates to the code; reordering the two assignments would
result in a different program.
A good way to see and get used to the compiler's SSA in action is via
GOSSAFUNC. For example, to see func Foo's initial SSA form and final
generated assembly, one can run:
GOSSAFUNC=Foo go build
The generated ssa.html file will also contain the SSA func at each of
the compile passes, making it easy to see what each pass does to a
particular program. You can also click on values and blocks to highlight
them, to help follow the control flow and values.