// Rewrite append(src, x, y, z) so that any side effects in // x, y, z (including runtime panics) are evaluated in // initialization statements before the append. // For normal code generation, stop there and leave the // rest to ssagen. // // For race detector, expand append(src, a [, b]* ) to // // init { // s := src // const argc = len(args) - 1 // newLen := s.len + argc // if uint(newLen) <= uint(s.cap) { // s = s[:newLen] // } else { // s = growslice(s.ptr, newLen, s.cap, argc, elemType) // } // s[s.len - argc] = a // s[s.len - argc + 1] = b // ... // } // s func walkAppend(n *ir.CallExpr, init *ir.Nodes, dst ir.Node) ir.Node { … } // growslice(ptr *T, newLen, oldCap, num int, <type>) (ret []T) func walkGrowslice(slice *ir.Name, init *ir.Nodes, oldPtr, newLen, oldCap, num ir.Node) *ir.CallExpr { … } // walkClear walks an OCLEAR node. func walkClear(n *ir.UnaryExpr) ir.Node { … } // walkClose walks an OCLOSE node. func walkClose(n *ir.UnaryExpr, init *ir.Nodes) ir.Node { … } // Lower copy(a, b) to a memmove call or a runtime call. // // init { // n := len(a) // if n > len(b) { n = len(b) } // if a.ptr != b.ptr { memmove(a.ptr, b.ptr, n*sizeof(elem(a))) } // } // n; // // Also works if b is a string. func walkCopy(n *ir.BinaryExpr, init *ir.Nodes, runtimecall bool) ir.Node { … } // walkDelete walks an ODELETE node. func walkDelete(init *ir.Nodes, n *ir.CallExpr) ir.Node { … } // walkLenCap walks an OLEN or OCAP node. func walkLenCap(n *ir.UnaryExpr, init *ir.Nodes) ir.Node { … } // walkMakeChan walks an OMAKECHAN node. func walkMakeChan(n *ir.MakeExpr, init *ir.Nodes) ir.Node { … } // walkMakeMap walks an OMAKEMAP node. func walkMakeMap(n *ir.MakeExpr, init *ir.Nodes) ir.Node { … } func walkMakeSwissMap(n *ir.MakeExpr, init *ir.Nodes) ir.Node { … } func walkMakeOldMap(n *ir.MakeExpr, init *ir.Nodes) ir.Node { … } // walkMakeSlice walks an OMAKESLICE node. func walkMakeSlice(n *ir.MakeExpr, init *ir.Nodes) ir.Node { … } // walkMakeSliceCopy walks an OMAKESLICECOPY node. func walkMakeSliceCopy(n *ir.MakeExpr, init *ir.Nodes) ir.Node { … } // walkNew walks an ONEW node. func walkNew(n *ir.UnaryExpr, init *ir.Nodes) ir.Node { … } func walkMinMax(n *ir.CallExpr, init *ir.Nodes) ir.Node { … } // generate code for print. func walkPrint(nn *ir.CallExpr, init *ir.Nodes) ir.Node { … } // walkRecoverFP walks an ORECOVERFP node. func walkRecoverFP(nn *ir.CallExpr, init *ir.Nodes) ir.Node { … } // walkUnsafeData walks an OUNSAFESLICEDATA or OUNSAFESTRINGDATA expression. func walkUnsafeData(n *ir.UnaryExpr, init *ir.Nodes) ir.Node { … } func walkUnsafeSlice(n *ir.BinaryExpr, init *ir.Nodes) ir.Node { … } var math_MulUintptr … func walkUnsafeString(n *ir.BinaryExpr, init *ir.Nodes) ir.Node { … } func badtype(op ir.Op, tl, tr *types.Type) { … } func writebarrierfn(name string, l *types.Type, r *types.Type) ir.Node { … } // isRuneCount reports whether n is of the form len([]rune(string)). // These are optimized into a call to runtime.countrunes. func isRuneCount(n ir.Node) bool { … } // isByteCount reports whether n is of the form len(string([]byte)). func isByteCount(n ir.Node) bool { … } // isChanLenCap reports whether n is of the form len(c) or cap(c) for a channel c. // Note that this does not check for -n or instrumenting because this // is a correctness rewrite, not an optimization. func isChanLenCap(n ir.Node) bool { … }