// IsRegularMemory reports whether t can be compared/hashed as regular memory. func IsRegularMemory(t *types.Type) bool { … } // Memrun finds runs of struct fields for which memory-only algs are appropriate. // t is the parent struct type, and start is the field index at which to start the run. // size is the length in bytes of the memory included in the run. // next is the index just after the end of the memory run. func Memrun(t *types.Type, start int) (size int64, next int) { … } // EqCanPanic reports whether == on type t could panic (has an interface somewhere). // t must be comparable. func EqCanPanic(t *types.Type) bool { … } // EqStructCost returns the cost of an equality comparison of two structs. // // The cost is determined using an algorithm which takes into consideration // the size of the registers in the current architecture and the size of the // memory-only fields in the struct. func EqStructCost(t *types.Type) int64 { … } // eqStructFieldCost returns the cost of an equality comparison of two struct fields. // t is the parent struct type, and i is the index of the field in the parent struct type. // eqStructFieldCost may compute the cost of several adjacent fields at once. It returns // the cost, the size of the set of fields it computed the cost for (in bytes), and the // index of the first field not part of the set of fields for which the cost // has already been calculated. func eqStructFieldCost(t *types.Type, i int) (int64, int64, int) { … } func calculateCostForType(t *types.Type) int64 { … } // EqStruct compares two structs np and nq for equality. // It works by building a list of boolean conditions to satisfy. // Conditions must be evaluated in the returned order and // properly short-circuited by the caller. // The first return value is the flattened list of conditions, // the second value is a boolean indicating whether any of the // comparisons could panic. func EqStruct(t *types.Type, np, nq ir.Node) ([]ir.Node, bool) { … } // EqString returns the nodes // // len(s) == len(t) // // and // // memequal(s.ptr, t.ptr, len(s)) // // which can be used to construct string equality comparison. // eqlen must be evaluated before eqmem, and shortcircuiting is required. func EqString(s, t ir.Node) (eqlen *ir.BinaryExpr, eqmem *ir.CallExpr) { … } // EqInterface returns the nodes // // s.tab == t.tab (or s.typ == t.typ, as appropriate) // // and // // ifaceeq(s.tab, s.data, t.data) (or efaceeq(s.typ, s.data, t.data), as appropriate) // // which can be used to construct interface equality comparison. // eqtab must be evaluated before eqdata, and shortcircuiting is required. func EqInterface(s, t ir.Node) (eqtab *ir.BinaryExpr, eqdata *ir.CallExpr) { … } // eqfield returns the node // // p.field == q.field func eqfield(p, q ir.Node, field int) ir.Node { … } // eqmem returns the node // // memequal(&p.field, &q.field, size) func eqmem(p, q ir.Node, field int, size int64) ir.Node { … } func eqmemfunc(size int64, t *types.Type) (fn *ir.Name, needsize bool) { … }