func postExpandCallsDecompose(f *Func) { … } func expandCalls(f *Func) { … } func (x *expandState) rewriteFuncResults(v *Value, b *Block, aux *AuxCall) { … } func (x *expandState) rewriteCallArgs(v *Value, firstArg int) { … } func (x *expandState) decomposePair(pos src.XPos, b *Block, a, mem *Value, t0, t1 *types.Type, o0, o1 Op, rc *registerCursor) *Value { … } func (x *expandState) decomposeOne(pos src.XPos, b *Block, a, mem *Value, t0 *types.Type, o0 Op, rc *registerCursor) *Value { … } // decomposeAsNecessary converts a value (perhaps an aggregate) passed to a call or returned by a function, // into the appropriate sequence of stores and register assignments to transmit that value in a given ABI, and // returns the current memory after this convert/rewrite (it may be the input memory, perhaps stores were needed.) // 'pos' is the source position all this is tied to // 'b' is the enclosing block // 'a' is the value to decompose // 'm0' is the input memory arg used for the first store (or returned if there are no stores) // 'rc' is a registerCursor which identifies the register/memory destination for the value func (x *expandState) decomposeAsNecessary(pos src.XPos, b *Block, a, m0 *Value, rc registerCursor) *Value { … } // Convert scalar OpArg into the proper OpWhateverArg instruction // Convert scalar OpSelectN into perhaps-differently-indexed OpSelectN // Convert aggregate OpArg into Make of its parts (which are eventually scalars) // Convert aggregate OpSelectN into Make of its parts (which are eventually scalars) // Returns the converted value. // // - "pos" the position for any generated instructions // - "b" the block for any generated instructions // - "container" the outermost OpArg/OpSelectN // - "a" the instruction to overwrite, if any (only the outermost caller) // - "m0" the memory arg for any loads that are necessary // - "at" the type of the Arg/part // - "rc" the register/memory cursor locating the various parts of the Arg. func (x *expandState) rewriteSelectOrArg(pos src.XPos, b *Block, container, a, m0 *Value, at *types.Type, rc registerCursor) *Value { … } // rewriteWideSelectToStores handles the case of a SelectN'd result from a function call that is too large for SSA, // but is transferred in registers. In this case the register cursor tracks both operands; the register sources and // the memory destinations. // This returns the memory flowing out of the last store func (x *expandState) rewriteWideSelectToStores(pos src.XPos, b *Block, container, m0 *Value, at *types.Type, rc registerCursor) *Value { … } func isBlockMultiValueExit(b *Block) bool { … } type Abi1RO … type registerCursor … func (c *registerCursor) String() string { … } // next effectively post-increments the register cursor; the receiver is advanced, // the (aligned) old value is returned. func (c *registerCursor) next(t *types.Type) registerCursor { … } // plus returns a register cursor offset from the original, without modifying the original. func (c *registerCursor) plus(regWidth Abi1RO) registerCursor { … } // at returns the register cursor for component i of t, where the first // component is numbered 0. func (c *registerCursor) at(t *types.Type, i int) registerCursor { … } func (c *registerCursor) init(regs []abi.RegIndex, info *abi.ABIParamResultInfo, result *[]*Value, storeDest *Value, storeOffset int64) { … } func (c *registerCursor) addArg(v *Value) { … } func (c *registerCursor) hasRegs() bool { … } func (c *registerCursor) ArgOpAndRegisterFor() (Op, int64) { … } // ArgOpAndRegisterFor converts an abi register index into an ssa Op and corresponding // arg register index. func ArgOpAndRegisterFor(r abi.RegIndex, abiConfig *abi.ABIConfig) (Op, int64) { … } type selKey … type expandState … // intPairTypes returns the pair of 32-bit int types needed to encode a 64-bit integer type on a target // that has no 64-bit integer registers. func (x *expandState) intPairTypes(et types.Kind) (tHi, tLo *types.Type) { … } // offsetFrom creates an offset from a pointer, simplifying chained offsets and offsets from SP func (x *expandState) offsetFrom(b *Block, from *Value, offset int64, pt *types.Type) *Value { … } func (x *expandState) regWidth(t *types.Type) Abi1RO { … } // regOffset returns the register offset of the i'th element of type t func (x *expandState) regOffset(t *types.Type, i int) Abi1RO { … } // prAssignForArg returns the ABIParamAssignment for v, assumed to be an OpArg. func (x *expandState) prAssignForArg(v *Value) *abi.ABIParamAssignment { … } // ParamAssignmentForArgName returns the ABIParamAssignment for f's arg with matching name. func ParamAssignmentForArgName(f *Func, name *ir.Name) *abi.ABIParamAssignment { … } // indent increments (or decrements) the indentation. func (x *expandState) indent(n int) { … } // Printf does an indented fmt.Printf on the format and args. func (x *expandState) Printf(format string, a ...interface{ … } func (x *expandState) invalidateRecursively(a *Value) { … }