func ArgLiveness(fn *ir.Func, f *ssa.Func, pp *objw.Progs) (blockIdx, valueIdx map[ssa.ID]int)
ArgLiveness computes the liveness information of register argument spill slots. An argument's spill slot is "live" if we know it contains a meaningful value, that is, we have stored the register value to it. Returns the liveness map indices at each Block entry and at each Value (where it changes).
func IsUnsafe(f *ssa.Func) bool
IsUnsafe indicates that all points in this function are unsafe-points.
func WriteFuncMap(fn *ir.Func, abiInfo *abi.ABIParamResultInfo)
WriteFuncMap writes the pointer bitmaps for bodyless function fn's inputs and outputs as the value of symbol <fn>.args_stackmap. If fn has outputs, two bitmaps are written, otherwise just one.
Interval hols the range [st,en).
type Interval struct {
// contains filtered or unexported fields
}
func (i1 *Interval) MergeInto(i2 Interval) error
MergeInto merges interval i2 into i1. This version happens to require that the two intervals either overlap or are adjacent.
func (i Interval) Overlaps(i2 Interval) bool
Overlaps returns true if here is any overlap between i and i2.
func (i Interval) String() string
Intervals is a sequence of sorted, disjoint intervals.
type Intervals []Interval
func (is Intervals) Merge(is2 Intervals) Intervals
Merge combines the intervals from "is" and "is2" and returns a new Intervals object containing all combined ranges from the two inputs.
func (is Intervals) Overlaps(is2 Intervals) bool
Overlaps returns whether any of the component ranges in is overlaps with some range in is2.
func (is *Intervals) String() string
IntervalsBuilder is a helper for constructing intervals based on live dataflow sets for a series of BBs where we're making a backwards pass over each BB looking for uses and kills. The expected use case is:
See the Live method comment for an IR example.
type IntervalsBuilder struct {
// contains filtered or unexported fields
}
func (c *IntervalsBuilder) Finish() (Intervals, error)
func (c *IntervalsBuilder) Kill(pos int) error
Kill method should be invoked on instruction at position p if instr should be treated as as having a kill (lifetime end) for the resource. See the example in the comment at the beginning of this file for an example. Note that if we see a kill at position K for a resource currently live since J, this will result in a lifetime segment of [K+1,J+1), the assumption being that the first live instruction will be the one after the kill position, not the kill position itself.
func (c *IntervalsBuilder) Live(pos int) error
Live method should be invoked on instruction at position p if instr contains an upwards-exposed use of a resource. See the example in the comment at the beginning of this file for an example.
Map maps from *ssa.Value to StackMapIndex. Also keeps track of unsafe ssa.Values and ssa.Blocks. (unsafe = can't be interrupted during GC.)
type Map struct { Vals map[ssa.ID]objw.StackMapIndex UnsafeVals map[ssa.ID]bool UnsafeBlocks map[ssa.ID]bool // The set of live, pointer-containing variables at the DeferReturn // call (only set when open-coded defers are used). DeferReturn objw.StackMapIndex }
func Compute(curfn *ir.Func, f *ssa.Func, stkptrsize int64, pp *objw.Progs) (Map, map[*ir.Name]bool)
Entry pointer for Compute analysis. Solves for the Compute of pointer variables in the function and emits a runtime data structure read by the garbage collector. Returns a map from GC safe points to their corresponding stack map index, and a map that contains all input parameters that may be partially live.
func (m Map) Get(v *ssa.Value) objw.StackMapIndex
func (m Map) GetUnsafe(v *ssa.Value) bool
func (m Map) GetUnsafeBlock(b *ssa.Block) bool
MergeLocalsState encapsulates information about which AUTO (stack-allocated) variables within a function can be safely merged/overlapped, e.g. share a stack slot with some other auto). An instance of MergeLocalsState is produced by MergeLocals() below and then consumed in ssagen.AllocFrame. The map 'partition' contains entries of the form <N,SL> where N is an *ir.Name and SL is a slice holding the indices (within 'vars') of other variables that share the same slot, specifically the slot of the first element in the partition, which we'll call the "leader". For example, if a function contains five variables where v1/v2/v3 are safe to overlap and v4/v5 are safe to overlap, the MergeLocalsState content might look like
vars: [v1, v2, v3, v4, v5] partition: v1 -> [1, 0, 2], v2 -> [1, 0, 2], v3 -> [1, 0, 2] v4 -> [3, 4], v5 -> [3, 4]
A nil MergeLocalsState indicates that no local variables meet the necessary criteria for overlap.
type MergeLocalsState struct {
// contains filtered or unexported fields
}
func MakeMergeLocalsState(partition map[*ir.Name][]int, vars []*ir.Name) (*MergeLocalsState, error)
for unit testing only.
func MergeLocals(fn *ir.Func, f *ssa.Func) *MergeLocalsState
MergeLocals analyzes the specified ssa function f to determine which of its auto variables can safely share the same stack slot, returning a state object that describes how the overlap should be done.
func (mls *MergeLocalsState) EstSavings() (int, int)
EstSavings returns the estimated reduction in stack size (number of bytes) for the given merge locals state via a pair of ints, the first for non-pointer types and the second for pointer types.
func (mls *MergeLocalsState) Followers(n *ir.Name, tmp []*ir.Name) []*ir.Name
Followers writes a list of the followers for leader n into the slice tmp.
func (mls *MergeLocalsState) IsLeader(n *ir.Name) bool
IsLeader returns whether a variable n is the leader (first element) in a sharing partition.
func (mls *MergeLocalsState) Leader(n *ir.Name) *ir.Name
Leader returns the leader variable for subsumed var n.
func (mls *MergeLocalsState) String() string
func (mls *MergeLocalsState) Subsumed(n *ir.Name) bool
Subsumed returns whether variable n is subsumed, e.g. appears in an overlap position but is not the leader in that partition.