summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Möhrmann <moehrmann@google.com>2018-10-23 13:50:07 +0200
committerMartin Möhrmann <moehrmann@google.com>2020-05-07 17:50:24 +0000
commit6ed4661807b219781d1aa452b7f210e21ad1974b (patch)
treed5ed10a2a7eb5096b1b67264468b8dc549d04d72
parent97240d546c3ae54871c7c196e504e4a0a06faf87 (diff)
downloadgo-git-6ed4661807b219781d1aa452b7f210e21ad1974b.tar.gz
cmd/compile: optimize make+copy pattern to avoid memclr
match: m = make([]T, x); copy(m, s) for pointer free T and x==len(s) rewrite to: m = mallocgc(x*elemsize(T), nil, false); memmove(&m, &s, x*elemsize(T)) otherwise rewrite to: m = makeslicecopy([]T, x, s) This avoids memclear and shading of pointers in the newly created slice before the copy. With this CL "s" is only be allowed to bev a variable and not a more complex expression. This restriction could be lifted in future versions of this optimization when it can be proven that "s" is not referencing "m". Triggers 450 times during make.bash.. Reduces go binary size by ~8 kbyte. name old time/op new time/op delta MakeSliceCopy/mallocmove/Byte 71.1ns ± 1% 65.8ns ± 0% -7.49% (p=0.000 n=10+9) MakeSliceCopy/mallocmove/Int 71.2ns ± 1% 66.0ns ± 0% -7.27% (p=0.000 n=10+8) MakeSliceCopy/mallocmove/Ptr 104ns ± 4% 99ns ± 1% -5.13% (p=0.000 n=10+10) MakeSliceCopy/makecopy/Byte 70.3ns ± 0% 68.0ns ± 0% -3.22% (p=0.000 n=10+9) MakeSliceCopy/makecopy/Int 70.3ns ± 0% 68.5ns ± 1% -2.59% (p=0.000 n=9+10) MakeSliceCopy/makecopy/Ptr 102ns ± 0% 99ns ± 1% -2.97% (p=0.000 n=9+9) MakeSliceCopy/nilappend/Byte 75.4ns ± 0% 74.9ns ± 2% -0.63% (p=0.015 n=9+9) MakeSliceCopy/nilappend/Int 75.6ns ± 0% 76.4ns ± 3% ~ (p=0.245 n=9+10) MakeSliceCopy/nilappend/Ptr 107ns ± 0% 108ns ± 1% +0.93% (p=0.005 n=9+10) Fixes #26252 Change-Id: Iec553dd1fef6ded16197216a472351c8799a8e71 Reviewed-on: https://go-review.googlesource.com/c/go/+/146719 Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: Martin Möhrmann <moehrmann@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
-rw-r--r--src/cmd/compile/internal/gc/builtin.go626
-rw-r--r--src/cmd/compile/internal/gc/builtin/runtime.go2
-rw-r--r--src/cmd/compile/internal/gc/fmt.go176
-rw-r--r--src/cmd/compile/internal/gc/op_string.go161
-rw-r--r--src/cmd/compile/internal/gc/order.go76
-rw-r--r--src/cmd/compile/internal/gc/syntax.go60
-rw-r--r--src/cmd/compile/internal/gc/typecheck.go43
-rw-r--r--src/cmd/compile/internal/gc/walk.go60
-rw-r--r--src/runtime/slice.go49
-rw-r--r--src/runtime/slice_test.go78
-rw-r--r--test/codegen/slices.go183
-rw-r--r--test/makeslice.go149
12 files changed, 1160 insertions, 503 deletions
diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go
index c2525395b0..2cf2f4687e 100644
--- a/src/cmd/compile/internal/gc/builtin.go
+++ b/src/cmd/compile/internal/gc/builtin.go
@@ -10,325 +10,329 @@ var runtimeDecls = [...]struct {
typ int
}{
{"newobject", funcTag, 4},
- {"panicdivide", funcTag, 5},
- {"panicshift", funcTag, 5},
- {"panicmakeslicelen", funcTag, 5},
- {"panicmakeslicecap", funcTag, 5},
- {"throwinit", funcTag, 5},
- {"panicwrap", funcTag, 5},
- {"gopanic", funcTag, 7},
- {"gorecover", funcTag, 10},
- {"goschedguarded", funcTag, 5},
- {"goPanicIndex", funcTag, 12},
- {"goPanicIndexU", funcTag, 14},
- {"goPanicSliceAlen", funcTag, 12},
- {"goPanicSliceAlenU", funcTag, 14},
- {"goPanicSliceAcap", funcTag, 12},
- {"goPanicSliceAcapU", funcTag, 14},
- {"goPanicSliceB", funcTag, 12},
- {"goPanicSliceBU", funcTag, 14},
- {"goPanicSlice3Alen", funcTag, 12},
- {"goPanicSlice3AlenU", funcTag, 14},
- {"goPanicSlice3Acap", funcTag, 12},
- {"goPanicSlice3AcapU", funcTag, 14},
- {"goPanicSlice3B", funcTag, 12},
- {"goPanicSlice3BU", funcTag, 14},
- {"goPanicSlice3C", funcTag, 12},
- {"goPanicSlice3CU", funcTag, 14},
- {"printbool", funcTag, 16},
- {"printfloat", funcTag, 18},
- {"printint", funcTag, 20},
- {"printhex", funcTag, 22},
- {"printuint", funcTag, 22},
- {"printcomplex", funcTag, 24},
- {"printstring", funcTag, 26},
- {"printpointer", funcTag, 27},
- {"printiface", funcTag, 27},
- {"printeface", funcTag, 27},
- {"printslice", funcTag, 27},
- {"printnl", funcTag, 5},
- {"printsp", funcTag, 5},
- {"printlock", funcTag, 5},
- {"printunlock", funcTag, 5},
- {"concatstring2", funcTag, 30},
- {"concatstring3", funcTag, 31},
- {"concatstring4", funcTag, 32},
- {"concatstring5", funcTag, 33},
- {"concatstrings", funcTag, 35},
- {"cmpstring", funcTag, 36},
- {"intstring", funcTag, 39},
- {"slicebytetostring", funcTag, 40},
- {"slicebytetostringtmp", funcTag, 41},
- {"slicerunetostring", funcTag, 44},
- {"stringtoslicebyte", funcTag, 46},
- {"stringtoslicerune", funcTag, 49},
- {"slicecopy", funcTag, 51},
- {"slicestringcopy", funcTag, 52},
- {"decoderune", funcTag, 53},
- {"countrunes", funcTag, 54},
- {"convI2I", funcTag, 55},
- {"convT16", funcTag, 57},
- {"convT32", funcTag, 57},
- {"convT64", funcTag, 57},
- {"convTstring", funcTag, 57},
- {"convTslice", funcTag, 57},
- {"convT2E", funcTag, 58},
- {"convT2Enoptr", funcTag, 58},
- {"convT2I", funcTag, 58},
- {"convT2Inoptr", funcTag, 58},
- {"assertE2I", funcTag, 55},
- {"assertE2I2", funcTag, 59},
- {"assertI2I", funcTag, 55},
- {"assertI2I2", funcTag, 59},
- {"panicdottypeE", funcTag, 60},
- {"panicdottypeI", funcTag, 60},
- {"panicnildottype", funcTag, 61},
- {"ifaceeq", funcTag, 63},
- {"efaceeq", funcTag, 63},
- {"fastrand", funcTag, 65},
- {"makemap64", funcTag, 67},
- {"makemap", funcTag, 68},
- {"makemap_small", funcTag, 69},
- {"mapaccess1", funcTag, 70},
- {"mapaccess1_fast32", funcTag, 71},
- {"mapaccess1_fast64", funcTag, 71},
- {"mapaccess1_faststr", funcTag, 71},
- {"mapaccess1_fat", funcTag, 72},
- {"mapaccess2", funcTag, 73},
- {"mapaccess2_fast32", funcTag, 74},
- {"mapaccess2_fast64", funcTag, 74},
- {"mapaccess2_faststr", funcTag, 74},
- {"mapaccess2_fat", funcTag, 75},
- {"mapassign", funcTag, 70},
- {"mapassign_fast32", funcTag, 71},
- {"mapassign_fast32ptr", funcTag, 71},
- {"mapassign_fast64", funcTag, 71},
- {"mapassign_fast64ptr", funcTag, 71},
- {"mapassign_faststr", funcTag, 71},
- {"mapiterinit", funcTag, 76},
- {"mapdelete", funcTag, 76},
- {"mapdelete_fast32", funcTag, 77},
- {"mapdelete_fast64", funcTag, 77},
- {"mapdelete_faststr", funcTag, 77},
- {"mapiternext", funcTag, 78},
- {"mapclear", funcTag, 79},
- {"makechan64", funcTag, 81},
- {"makechan", funcTag, 82},
- {"chanrecv1", funcTag, 84},
- {"chanrecv2", funcTag, 85},
- {"chansend1", funcTag, 87},
- {"closechan", funcTag, 27},
- {"writeBarrier", varTag, 89},
- {"typedmemmove", funcTag, 90},
- {"typedmemclr", funcTag, 91},
- {"typedslicecopy", funcTag, 92},
- {"selectnbsend", funcTag, 93},
- {"selectnbrecv", funcTag, 94},
- {"selectnbrecv2", funcTag, 96},
- {"selectsetpc", funcTag, 61},
- {"selectgo", funcTag, 97},
- {"block", funcTag, 5},
- {"makeslice", funcTag, 98},
- {"makeslice64", funcTag, 99},
- {"growslice", funcTag, 101},
- {"memmove", funcTag, 102},
- {"memclrNoHeapPointers", funcTag, 103},
- {"memclrHasPointers", funcTag, 103},
- {"memequal", funcTag, 104},
- {"memequal0", funcTag, 105},
- {"memequal8", funcTag, 105},
- {"memequal16", funcTag, 105},
- {"memequal32", funcTag, 105},
- {"memequal64", funcTag, 105},
- {"memequal128", funcTag, 105},
- {"f32equal", funcTag, 106},
- {"f64equal", funcTag, 106},
- {"c64equal", funcTag, 106},
- {"c128equal", funcTag, 106},
- {"strequal", funcTag, 106},
- {"interequal", funcTag, 106},
- {"nilinterequal", funcTag, 106},
- {"memhash", funcTag, 107},
- {"memhash0", funcTag, 108},
- {"memhash8", funcTag, 108},
- {"memhash16", funcTag, 108},
- {"memhash32", funcTag, 108},
- {"memhash64", funcTag, 108},
- {"memhash128", funcTag, 108},
- {"f32hash", funcTag, 108},
- {"f64hash", funcTag, 108},
- {"c64hash", funcTag, 108},
- {"c128hash", funcTag, 108},
- {"strhash", funcTag, 108},
- {"interhash", funcTag, 108},
- {"nilinterhash", funcTag, 108},
- {"int64div", funcTag, 109},
- {"uint64div", funcTag, 110},
- {"int64mod", funcTag, 109},
- {"uint64mod", funcTag, 110},
- {"float64toint64", funcTag, 111},
- {"float64touint64", funcTag, 112},
- {"float64touint32", funcTag, 113},
- {"int64tofloat64", funcTag, 114},
- {"uint64tofloat64", funcTag, 115},
- {"uint32tofloat64", funcTag, 116},
- {"complex128div", funcTag, 117},
- {"racefuncenter", funcTag, 118},
- {"racefuncenterfp", funcTag, 5},
- {"racefuncexit", funcTag, 5},
- {"raceread", funcTag, 118},
- {"racewrite", funcTag, 118},
- {"racereadrange", funcTag, 119},
- {"racewriterange", funcTag, 119},
- {"msanread", funcTag, 119},
- {"msanwrite", funcTag, 119},
- {"checkptrAlignment", funcTag, 120},
- {"checkptrArithmetic", funcTag, 122},
- {"libfuzzerTraceCmp1", funcTag, 124},
- {"libfuzzerTraceCmp2", funcTag, 126},
- {"libfuzzerTraceCmp4", funcTag, 127},
- {"libfuzzerTraceCmp8", funcTag, 128},
- {"libfuzzerTraceConstCmp1", funcTag, 124},
- {"libfuzzerTraceConstCmp2", funcTag, 126},
- {"libfuzzerTraceConstCmp4", funcTag, 127},
- {"libfuzzerTraceConstCmp8", funcTag, 128},
- {"x86HasPOPCNT", varTag, 15},
- {"x86HasSSE41", varTag, 15},
- {"x86HasFMA", varTag, 15},
- {"armHasVFPv4", varTag, 15},
- {"arm64HasATOMICS", varTag, 15},
+ {"mallocgc", funcTag, 8},
+ {"panicdivide", funcTag, 9},
+ {"panicshift", funcTag, 9},
+ {"panicmakeslicelen", funcTag, 9},
+ {"panicmakeslicecap", funcTag, 9},
+ {"throwinit", funcTag, 9},
+ {"panicwrap", funcTag, 9},
+ {"gopanic", funcTag, 11},
+ {"gorecover", funcTag, 14},
+ {"goschedguarded", funcTag, 9},
+ {"goPanicIndex", funcTag, 16},
+ {"goPanicIndexU", funcTag, 18},
+ {"goPanicSliceAlen", funcTag, 16},
+ {"goPanicSliceAlenU", funcTag, 18},
+ {"goPanicSliceAcap", funcTag, 16},
+ {"goPanicSliceAcapU", funcTag, 18},
+ {"goPanicSliceB", funcTag, 16},
+ {"goPanicSliceBU", funcTag, 18},
+ {"goPanicSlice3Alen", funcTag, 16},
+ {"goPanicSlice3AlenU", funcTag, 18},
+ {"goPanicSlice3Acap", funcTag, 16},
+ {"goPanicSlice3AcapU", funcTag, 18},
+ {"goPanicSlice3B", funcTag, 16},
+ {"goPanicSlice3BU", funcTag, 18},
+ {"goPanicSlice3C", funcTag, 16},
+ {"goPanicSlice3CU", funcTag, 18},
+ {"printbool", funcTag, 19},
+ {"printfloat", funcTag, 21},
+ {"printint", funcTag, 23},
+ {"printhex", funcTag, 25},
+ {"printuint", funcTag, 25},
+ {"printcomplex", funcTag, 27},
+ {"printstring", funcTag, 29},
+ {"printpointer", funcTag, 30},
+ {"printiface", funcTag, 30},
+ {"printeface", funcTag, 30},
+ {"printslice", funcTag, 30},
+ {"printnl", funcTag, 9},
+ {"printsp", funcTag, 9},
+ {"printlock", funcTag, 9},
+ {"printunlock", funcTag, 9},
+ {"concatstring2", funcTag, 33},
+ {"concatstring3", funcTag, 34},
+ {"concatstring4", funcTag, 35},
+ {"concatstring5", funcTag, 36},
+ {"concatstrings", funcTag, 38},
+ {"cmpstring", funcTag, 39},
+ {"intstring", funcTag, 42},
+ {"slicebytetostring", funcTag, 43},
+ {"slicebytetostringtmp", funcTag, 44},
+ {"slicerunetostring", funcTag, 47},
+ {"stringtoslicebyte", funcTag, 49},
+ {"stringtoslicerune", funcTag, 52},
+ {"slicecopy", funcTag, 53},
+ {"slicestringcopy", funcTag, 54},
+ {"decoderune", funcTag, 55},
+ {"countrunes", funcTag, 56},
+ {"convI2I", funcTag, 57},
+ {"convT16", funcTag, 58},
+ {"convT32", funcTag, 58},
+ {"convT64", funcTag, 58},
+ {"convTstring", funcTag, 58},
+ {"convTslice", funcTag, 58},
+ {"convT2E", funcTag, 59},
+ {"convT2Enoptr", funcTag, 59},
+ {"convT2I", funcTag, 59},
+ {"convT2Inoptr", funcTag, 59},
+ {"assertE2I", funcTag, 57},
+ {"assertE2I2", funcTag, 60},
+ {"assertI2I", funcTag, 57},
+ {"assertI2I2", funcTag, 60},
+ {"panicdottypeE", funcTag, 61},
+ {"panicdottypeI", funcTag, 61},
+ {"panicnildottype", funcTag, 62},
+ {"ifaceeq", funcTag, 64},
+ {"efaceeq", funcTag, 64},
+ {"fastrand", funcTag, 66},
+ {"makemap64", funcTag, 68},
+ {"makemap", funcTag, 69},
+ {"makemap_small", funcTag, 70},
+ {"mapaccess1", funcTag, 71},
+ {"mapaccess1_fast32", funcTag, 72},
+ {"mapaccess1_fast64", funcTag, 72},
+ {"mapaccess1_faststr", funcTag, 72},
+ {"mapaccess1_fat", funcTag, 73},
+ {"mapaccess2", funcTag, 74},
+ {"mapaccess2_fast32", funcTag, 75},
+ {"mapaccess2_fast64", funcTag, 75},
+ {"mapaccess2_faststr", funcTag, 75},
+ {"mapaccess2_fat", funcTag, 76},
+ {"mapassign", funcTag, 71},
+ {"mapassign_fast32", funcTag, 72},
+ {"mapassign_fast32ptr", funcTag, 72},
+ {"mapassign_fast64", funcTag, 72},
+ {"mapassign_fast64ptr", funcTag, 72},
+ {"mapassign_faststr", funcTag, 72},
+ {"mapiterinit", funcTag, 77},
+ {"mapdelete", funcTag, 77},
+ {"mapdelete_fast32", funcTag, 78},
+ {"mapdelete_fast64", funcTag, 78},
+ {"mapdelete_faststr", funcTag, 78},
+ {"mapiternext", funcTag, 79},
+ {"mapclear", funcTag, 80},
+ {"makechan64", funcTag, 82},
+ {"makechan", funcTag, 83},
+ {"chanrecv1", funcTag, 85},
+ {"chanrecv2", funcTag, 86},
+ {"chansend1", funcTag, 88},
+ {"closechan", funcTag, 30},
+ {"writeBarrier", varTag, 90},
+ {"typedmemmove", funcTag, 91},
+ {"typedmemclr", funcTag, 92},
+ {"typedslicecopy", funcTag, 93},
+ {"selectnbsend", funcTag, 94},
+ {"selectnbrecv", funcTag, 95},
+ {"selectnbrecv2", funcTag, 97},
+ {"selectsetpc", funcTag, 62},
+ {"selectgo", funcTag, 98},
+ {"block", funcTag, 9},
+ {"makeslice", funcTag, 99},
+ {"makeslice64", funcTag, 100},
+ {"makeslicecopy", funcTag, 101},
+ {"growslice", funcTag, 103},
+ {"memmove", funcTag, 104},
+ {"memclrNoHeapPointers", funcTag, 105},
+ {"memclrHasPointers", funcTag, 105},
+ {"memequal", funcTag, 106},
+ {"memequal0", funcTag, 107},
+ {"memequal8", funcTag, 107},
+ {"memequal16", funcTag, 107},
+ {"memequal32", funcTag, 107},
+ {"memequal64", funcTag, 107},
+ {"memequal128", funcTag, 107},
+ {"f32equal", funcTag, 108},
+ {"f64equal", funcTag, 108},
+ {"c64equal", funcTag, 108},
+ {"c128equal", funcTag, 108},
+ {"strequal", funcTag, 108},
+ {"interequal", funcTag, 108},
+ {"nilinterequal", funcTag, 108},
+ {"memhash", funcTag, 109},
+ {"memhash0", funcTag, 110},
+ {"memhash8", funcTag, 110},
+ {"memhash16", funcTag, 110},
+ {"memhash32", funcTag, 110},
+ {"memhash64", funcTag, 110},
+ {"memhash128", funcTag, 110},
+ {"f32hash", funcTag, 110},
+ {"f64hash", funcTag, 110},
+ {"c64hash", funcTag, 110},
+ {"c128hash", funcTag, 110},
+ {"strhash", funcTag, 110},
+ {"interhash", funcTag, 110},
+ {"nilinterhash", funcTag, 110},
+ {"int64div", funcTag, 111},
+ {"uint64div", funcTag, 112},
+ {"int64mod", funcTag, 111},
+ {"uint64mod", funcTag, 112},
+ {"float64toint64", funcTag, 113},
+ {"float64touint64", funcTag, 114},
+ {"float64touint32", funcTag, 115},
+ {"int64tofloat64", funcTag, 116},
+ {"uint64tofloat64", funcTag, 117},
+ {"uint32tofloat64", funcTag, 118},
+ {"complex128div", funcTag, 119},
+ {"racefuncenter", funcTag, 120},
+ {"racefuncenterfp", funcTag, 9},
+ {"racefuncexit", funcTag, 9},
+ {"raceread", funcTag, 120},
+ {"racewrite", funcTag, 120},
+ {"racereadrange", funcTag, 121},
+ {"racewriterange", funcTag, 121},
+ {"msanread", funcTag, 121},
+ {"msanwrite", funcTag, 121},
+ {"checkptrAlignment", funcTag, 122},
+ {"checkptrArithmetic", funcTag, 124},
+ {"libfuzzerTraceCmp1", funcTag, 126},
+ {"libfuzzerTraceCmp2", funcTag, 128},
+ {"libfuzzerTraceCmp4", funcTag, 129},
+ {"libfuzzerTraceCmp8", funcTag, 130},
+ {"libfuzzerTraceConstCmp1", funcTag, 126},
+ {"libfuzzerTraceConstCmp2", funcTag, 128},
+ {"libfuzzerTraceConstCmp4", funcTag, 129},
+ {"libfuzzerTraceConstCmp8", funcTag, 130},
+ {"x86HasPOPCNT", varTag, 6},
+ {"x86HasSSE41", varTag, 6},
+ {"x86HasFMA", varTag, 6},
+ {"armHasVFPv4", varTag, 6},
+ {"arm64HasATOMICS", varTag, 6},
}
func runtimeTypes() []*types.Type {
- var typs [129]*types.Type
+ var typs [131]*types.Type
typs[0] = types.Bytetype
typs[1] = types.NewPtr(typs[0])
typs[2] = types.Types[TANY]
typs[3] = types.NewPtr(typs[2])
typs[4] = functype(nil, []*Node{anonfield(typs[1])}, []*Node{anonfield(typs[3])})
- typs[5] = functype(nil, nil, nil)
- typs[6] = types.Types[TINTER]
- typs[7] = functype(nil, []*Node{anonfield(typs[6])}, nil)
- typs[8] = types.Types[TINT32]
- typs[9] = types.NewPtr(typs[8])
- typs[10] = functype(nil, []*Node{anonfield(typs[9])}, []*Node{anonfield(typs[6])})
- typs[11] = types.Types[TINT]
- typs[12] = functype(nil, []*Node{anonfield(typs[11]), anonfield(typs[11])}, nil)
- typs[13] = types.Types[TUINT]
- typs[14] = functype(nil, []*Node{anonfield(typs[13]), anonfield(typs[11])}, nil)
- typs[15] = types.Types[TBOOL]
- typs[16] = functype(nil, []*Node{anonfield(typs[15])}, nil)
- typs[17] = types.Types[TFLOAT64]
- typs[18] = functype(nil, []*Node{anonfield(typs[17])}, nil)
- typs[19] = types.Types[TINT64]
- typs[20] = functype(nil, []*Node{anonfield(typs[19])}, nil)
- typs[21] = types.Types[TUINT64]
- typs[22] = functype(nil, []*Node{anonfield(typs[21])}, nil)
- typs[23] = types.Types[TCOMPLEX128]
- typs[24] = functype(nil, []*Node{anonfield(typs[23])}, nil)
- typs[25] = types.Types[TSTRING]
- typs[26] = functype(nil, []*Node{anonfield(typs[25])}, nil)
- typs[27] = functype(nil, []*Node{anonfield(typs[2])}, nil)
- typs[28] = types.NewArray(typs[0], 32)
- typs[29] = types.NewPtr(typs[28])
- typs[30] = functype(nil, []*Node{anonfield(typs[29]), anonfield(typs[25]), anonfield(typs[25])}, []*Node{anonfield(typs[25])})
- typs[31] = functype(nil, []*Node{anonfield(typs[29]), anonfield(typs[25]), anonfield(typs[25]), anonfield(typs[25])}, []*Node{anonfield(typs[25])})
- typs[32] = functype(nil, []*Node{anonfield(typs[29]), anonfield(typs[25]), anonfield(typs[25]), anonfield(typs[25]), anonfield(typs[25])}, []*Node{anonfield(typs[25])})
- typs[33] = functype(nil, []*Node{anonfield(typs[29]), anonfield(typs[25]), anonfield(typs[25]), anonfield(typs[25]), anonfield(typs[25]), anonfield(typs[25])}, []*Node{anonfield(typs[25])})
- typs[34] = types.NewSlice(typs[25])
- typs[35] = functype(nil, []*Node{anonfield(typs[29]), anonfield(typs[34])}, []*Node{anonfield(typs[25])})
- typs[36] = functype(nil, []*Node{anonfield(typs[25]), anonfield(typs[25])}, []*Node{anonfield(typs[11])})
- typs[37] = types.NewArray(typs[0], 4)
- typs[38] = types.NewPtr(typs[37])
- typs[39] = functype(nil, []*Node{anonfield(typs[38]), anonfield(typs[19])}, []*Node{anonfield(typs[25])})
- typs[40] = functype(nil, []*Node{anonfield(typs[29]), anonfield(typs[1]), anonfield(typs[11])}, []*Node{anonfield(typs[25])})
- typs[41] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[11])}, []*Node{anonfield(typs[25])})
- typs[42] = types.Runetype
- typs[43] = types.NewSlice(typs[42])
- typs[44] = functype(nil, []*Node{anonfield(typs[29]), anonfield(typs[43])}, []*Node{anonfield(typs[25])})
- typs[45] = types.NewSlice(typs[0])
- typs[46] = functype(nil, []*Node{anonfield(typs[29]), anonfield(typs[25])}, []*Node{anonfield(typs[45])})
- typs[47] = types.NewArray(typs[42], 32)
- typs[48] = types.NewPtr(typs[47])
- typs[49] = functype(nil, []*Node{anonfield(typs[48]), anonfield(typs[25])}, []*Node{anonfield(typs[43])})
- typs[50] = types.Types[TUINTPTR]
- typs[51] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[11]), anonfield(typs[3]), anonfield(typs[11]), anonfield(typs[50])}, []*Node{anonfield(typs[11])})
- typs[52] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[11]), anonfield(typs[25])}, []*Node{anonfield(typs[11])})
- typs[53] = functype(nil, []*Node{anonfield(typs[25]), anonfield(typs[11])}, []*Node{anonfield(typs[42]), anonfield(typs[11])})
- typs[54] = functype(nil, []*Node{anonfield(typs[25])}, []*Node{anonfield(typs[11])})
- typs[55] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2])})
- typs[56] = types.Types[TUNSAFEPTR]
- typs[57] = functype(nil, []*Node{anonfield(typs[2])}, []*Node{anonfield(typs[56])})
- typs[58] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, []*Node{anonfield(typs[2])})
- typs[59] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2]), anonfield(typs[15])})
- typs[60] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil)
- typs[61] = functype(nil, []*Node{anonfield(typs[1])}, nil)
- typs[62] = types.NewPtr(typs[50])
- typs[63] = functype(nil, []*Node{anonfield(typs[62]), anonfield(typs[56]), anonfield(typs[56])}, []*Node{anonfield(typs[15])})
- typs[64] = types.Types[TUINT32]
- typs[65] = functype(nil, nil, []*Node{anonfield(typs[64])})
- typs[66] = types.NewMap(typs[2], typs[2])
- typs[67] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[19]), anonfield(typs[3])}, []*Node{anonfield(typs[66])})
- typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[11]), anonfield(typs[3])}, []*Node{anonfield(typs[66])})
- typs[69] = functype(nil, nil, []*Node{anonfield(typs[66])})
- typs[70] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3])}, []*Node{anonfield(typs[3])})
- typs[71] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[2])}, []*Node{anonfield(typs[3])})
- typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])})
- typs[73] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[15])})
- typs[74] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[15])})
- typs[75] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[15])})
- typs[76] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[3])}, nil)
- typs[77] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66]), anonfield(typs[2])}, nil)
- typs[78] = functype(nil, []*Node{anonfield(typs[3])}, nil)
- typs[79] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[66])}, nil)
- typs[80] = types.NewChan(typs[2], types.Cboth)
- typs[81] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[19])}, []*Node{anonfield(typs[80])})
- typs[82] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[11])}, []*Node{anonfield(typs[80])})
- typs[83] = types.NewChan(typs[2], types.Crecv)
- typs[84] = functype(nil, []*Node{anonfield(typs[83]), anonfield(typs[3])}, nil)
- typs[85] = functype(nil, []*Node{anonfield(typs[83]), anonfield(typs[3])}, []*Node{anonfield(typs[15])})
- typs[86] = types.NewChan(typs[2], types.Csend)
- typs[87] = functype(nil, []*Node{anonfield(typs[86]), anonfield(typs[3])}, nil)
- typs[88] = types.NewArray(typs[0], 3)
- typs[89] = tostruct([]*Node{namedfield("enabled", typs[15]), namedfield("pad", typs[88]), namedfield("needed", typs[15]), namedfield("cgo", typs[15]), namedfield("alignme", typs[21])})
- typs[90] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil)
- typs[91] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil)
- typs[92] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[11]), anonfield(typs[3]), anonfield(typs[11])}, []*Node{anonfield(typs[11])})
- typs[93] = functype(nil, []*Node{anonfield(typs[86]), anonfield(typs[3])}, []*Node{anonfield(typs[15])})
- typs[94] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[83])}, []*Node{anonfield(typs[15])})
- typs[95] = types.NewPtr(typs[15])
- typs[96] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[95]), anonfield(typs[83])}, []*Node{anonfield(typs[15])})
- typs[97] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[11])}, []*Node{anonfield(typs[11]), anonfield(typs[15])})
- typs[98] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[11]), anonfield(typs[11])}, []*Node{anonfield(typs[56])})
- typs[99] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[56])})
- typs[100] = types.NewSlice(typs[2])
- typs[101] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[100]), anonfield(typs[11])}, []*Node{anonfield(typs[100])})
- typs[102] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[50])}, nil)
- typs[103] = functype(nil, []*Node{anonfield(typs[56]), anonfield(typs[50])}, nil)
- typs[104] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[50])}, []*Node{anonfield(typs[15])})
- typs[105] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[15])})
- typs[106] = functype(nil, []*Node{anonfield(typs[56]), anonfield(typs[56])}, []*Node{anonfield(typs[15])})
- typs[107] = functype(nil, []*Node{anonfield(typs[56]), anonfield(typs[50]), anonfield(typs[50])}, []*Node{anonfield(typs[50])})
- typs[108] = functype(nil, []*Node{anonfield(typs[56]), anonfield(typs[50])}, []*Node{anonfield(typs[50])})
- typs[109] = functype(nil, []*Node{anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[19])})
- typs[110] = functype(nil, []*Node{anonfield(typs[21]), anonfield(typs[21])}, []*Node{anonfield(typs[21])})
- typs[111] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[19])})
- typs[112] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[21])})
- typs[113] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[64])})
- typs[114] = functype(nil, []*Node{anonfield(typs[19])}, []*Node{anonfield(typs[17])})
- typs[115] = functype(nil, []*Node{anonfield(typs[21])}, []*Node{anonfield(typs[17])})
- typs[116] = functype(nil, []*Node{anonfield(typs[64])}, []*Node{anonfield(typs[17])})
- typs[117] = functype(nil, []*Node{anonfield(typs[23]), anonfield(typs[23])}, []*Node{anonfield(typs[23])})
- typs[118] = functype(nil, []*Node{anonfield(typs[50])}, nil)
- typs[119] = functype(nil, []*Node{anonfield(typs[50]), anonfield(typs[50])}, nil)
- typs[120] = functype(nil, []*Node{anonfield(typs[56]), anonfield(typs[1]), anonfield(typs[50])}, nil)
- typs[121] = types.NewSlice(typs[56])
- typs[122] = functype(nil, []*Node{anonfield(typs[56]), anonfield(typs[121])}, nil)
- typs[123] = types.Types[TUINT8]
- typs[124] = functype(nil, []*Node{anonfield(typs[123]), anonfield(typs[123])}, nil)
- typs[125] = types.Types[TUINT16]
+ typs[5] = types.Types[TUINTPTR]
+ typs[6] = types.Types[TBOOL]
+ typs[7] = types.Types[TUNSAFEPTR]
+ typs[8] = functype(nil, []*Node{anonfield(typs[5]), anonfield(typs[1]), anonfield(typs[6])}, []*Node{anonfield(typs[7])})
+ typs[9] = functype(nil, nil, nil)
+ typs[10] = types.Types[TINTER]
+ typs[11] = functype(nil, []*Node{anonfield(typs[10])}, nil)
+ typs[12] = types.Types[TINT32]
+ typs[13] = types.NewPtr(typs[12])
+ typs[14] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[10])})
+ typs[15] = types.Types[TINT]
+ typs[16] = functype(nil, []*Node{anonfield(typs[15]), anonfield(typs[15])}, nil)
+ typs[17] = types.Types[TUINT]
+ typs[18] = functype(nil, []*Node{anonfield(typs[17]), anonfield(typs[15])}, nil)
+ typs[19] = functype(nil, []*Node{anonfield(typs[6])}, nil)
+ typs[20] = types.Types[TFLOAT64]
+ typs[21] = functype(nil, []*Node{anonfield(typs[20])}, nil)
+ typs[22] = types.Types[TINT64]
+ typs[23] = functype(nil, []*Node{anonfield(typs[22])}, nil)
+ typs[24] = types.Types[TUINT64]
+ typs[25] = functype(nil, []*Node{anonfield(typs[24])}, nil)
+ typs[26] = types.Types[TCOMPLEX128]
+ typs[27] = functype(nil, []*Node{anonfield(typs[26])}, nil)
+ typs[28] = types.Types[TSTRING]
+ typs[29] = functype(nil, []*Node{anonfield(typs[28])}, nil)
+ typs[30] = functype(nil, []*Node{anonfield(typs[2])}, nil)
+ typs[31] = types.NewArray(typs[0], 32)
+ typs[32] = types.NewPtr(typs[31])
+ typs[33] = functype(nil, []*Node{anonfield(typs[32]), anonfield(typs[28]), anonfield(typs[28])}, []*Node{anonfield(typs[28])})
+ typs[34] = functype(nil, []*Node{anonfield(typs[32]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []*Node{anonfield(typs[28])})
+ typs[35] = functype(nil, []*Node{anonfield(typs[32]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []*Node{anonfield(typs[28])})
+ typs[36] = functype(nil, []*Node{anonfield(typs[32]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []*Node{anonfield(typs[28])})
+ typs[37] = types.NewSlice(typs[28])
+ typs[38] = functype(nil, []*Node{anonfield(typs[32]), anonfield(typs[37])}, []*Node{anonfield(typs[28])})
+ typs[39] = functype(nil, []*Node{anonfield(typs[28]), anonfield(typs[28])}, []*Node{anonfield(typs[15])})
+ typs[40] = types.NewArray(typs[0], 4)
+ typs[41] = types.NewPtr(typs[40])
+ typs[42] = functype(nil, []*Node{anonfield(typs[41]), anonfield(typs[22])}, []*Node{anonfield(typs[28])})
+ typs[43] = functype(nil, []*Node{anonfield(typs[32]), anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[28])})
+ typs[44] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[28])})
+ typs[45] = types.Runetype
+ typs[46] = types.NewSlice(typs[45])
+ typs[47] = functype(nil, []*Node{anonfield(typs[32]), anonfield(typs[46])}, []*Node{anonfield(typs[28])})
+ typs[48] = types.NewSlice(typs[0])
+ typs[49] = functype(nil, []*Node{anonfield(typs[32]), anonfield(typs[28])}, []*Node{anonfield(typs[48])})
+ typs[50] = types.NewArray(typs[45], 32)
+ typs[51] = types.NewPtr(typs[50])
+ typs[52] = functype(nil, []*Node{anonfield(typs[51]), anonfield(typs[28])}, []*Node{anonfield(typs[46])})
+ typs[53] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[5])}, []*Node{anonfield(typs[15])})
+ typs[54] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[28])}, []*Node{anonfield(typs[15])})
+ typs[55] = functype(nil, []*Node{anonfield(typs[28]), anonfield(typs[15])}, []*Node{anonfield(typs[45]), anonfield(typs[15])})
+ typs[56] = functype(nil, []*Node{anonfield(typs[28])}, []*Node{anonfield(typs[15])})
+ typs[57] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2])})
+ typs[58] = functype(nil, []*Node{anonfield(typs[2])}, []*Node{anonfield(typs[7])})
+ typs[59] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, []*Node{anonfield(typs[2])})
+ typs[60] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2]), anonfield(typs[6])})
+ typs[61] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil)
+ typs[62] = functype(nil, []*Node{anonfield(typs[1])}, nil)
+ typs[63] = types.NewPtr(typs[5])
+ typs[64] = functype(nil, []*Node{anonfield(typs[63]), anonfield(typs[7]), anonfield(typs[7])}, []*Node{anonfield(typs[6])})
+ typs[65] = types.Types[TUINT32]
+ typs[66] = functype(nil, nil, []*Node{anonfield(typs[65])})
+ typs[67] = types.NewMap(typs[2], typs[2])
+ typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[3])}, []*Node{anonfield(typs[67])})
+ typs[69] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*Node{anonfield(typs[67])})
+ typs[70] = functype(nil, nil, []*Node{anonfield(typs[67])})
+ typs[71] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []*Node{anonfield(typs[3])})
+ typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []*Node{anonfield(typs[3])})
+ typs[73] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])})
+ typs[74] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[6])})
+ typs[75] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[6])})
+ typs[76] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[6])})
+ typs[77] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, nil)
+ typs[78] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, nil)
+ typs[79] = functype(nil, []*Node{anonfield(typs[3])}, nil)
+ typs[80] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67])}, nil)
+ typs[81] = types.NewChan(typs[2], types.Cboth)
+ typs[82] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22])}, []*Node{anonfield(typs[81])})
+ typs[83] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[81])})
+ typs[84] = types.NewChan(typs[2], types.Crecv)
+ typs[85] = functype(nil, []*Node{anonfield(typs[84]), anonfield(typs[3])}, nil)
+ typs[86] = functype(nil, []*Node{anonfield(typs[84]), anonfield(typs[3])}, []*Node{anonfield(typs[6])})
+ typs[87] = types.NewChan(typs[2], types.Csend)
+ typs[88] = functype(nil, []*Node{anonfield(typs[87]), anonfield(typs[3])}, nil)
+ typs[89] = types.NewArray(typs[0], 3)
+ typs[90] = tostruct([]*Node{namedfield("enabled", typs[6]), namedfield("pad", typs[89]), namedfield("needed", typs[6]), namedfield("cgo", typs[6]), namedfield("alignme", typs[24])})
+ typs[91] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil)
+ typs[92] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil)
+ typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15])}, []*Node{anonfield(typs[15])})
+ typs[94] = functype(nil, []*Node{anonfield(typs[87]), anonfield(typs[3])}, []*Node{anonfield(typs[6])})
+ typs[95] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[84])}, []*Node{anonfield(typs[6])})
+ typs[96] = types.NewPtr(typs[6])
+ typs[97] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[96]), anonfield(typs[84])}, []*Node{anonfield(typs[6])})
+ typs[98] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[15]), anonfield(typs[6])})
+ typs[99] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[7])})
+ typs[100] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[22])}, []*Node{anonfield(typs[7])})
+ typs[101] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[7])}, []*Node{anonfield(typs[7])})
+ typs[102] = types.NewSlice(typs[2])
+ typs[103] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[102]), anonfield(typs[15])}, []*Node{anonfield(typs[102])})
+ typs[104] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, nil)
+ typs[105] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5])}, nil)
+ typs[106] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, []*Node{anonfield(typs[6])})
+ typs[107] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[6])})
+ typs[108] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[7])}, []*Node{anonfield(typs[6])})
+ typs[109] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5]), anonfield(typs[5])}, []*Node{anonfield(typs[5])})
+ typs[110] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5])}, []*Node{anonfield(typs[5])})
+ typs[111] = functype(nil, []*Node{anonfield(typs[22]), anonfield(typs[22])}, []*Node{anonfield(typs[22])})
+ typs[112] = functype(nil, []*Node{anonfield(typs[24]), anonfield(typs[24])}, []*Node{anonfield(typs[24])})
+ typs[113] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[22])})
+ typs[114] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[24])})
+ typs[115] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[65])})
+ typs[116] = functype(nil, []*Node{anonfield(typs[22])}, []*Node{anonfield(typs[20])})
+ typs[117] = functype(nil, []*Node{anonfield(typs[24])}, []*Node{anonfield(typs[20])})
+ typs[118] = functype(nil, []*Node{anonfield(typs[65])}, []*Node{anonfield(typs[20])})
+ typs[119] = functype(nil, []*Node{anonfield(typs[26]), anonfield(typs[26])}, []*Node{anonfield(typs[26])})
+ typs[120] = functype(nil, []*Node{anonfield(typs[5])}, nil)
+ typs[121] = functype(nil, []*Node{anonfield(typs[5]), anonfield(typs[5])}, nil)
+ typs[122] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[1]), anonfield(typs[5])}, nil)
+ typs[123] = types.NewSlice(typs[7])
+ typs[124] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[123])}, nil)
+ typs[125] = types.Types[TUINT8]
typs[126] = functype(nil, []*Node{anonfield(typs[125]), anonfield(typs[125])}, nil)
- typs[127] = functype(nil, []*Node{anonfield(typs[64]), anonfield(typs[64])}, nil)
- typs[128] = functype(nil, []*Node{anonfield(typs[21]), anonfield(typs[21])}, nil)
+ typs[127] = types.Types[TUINT16]
+ typs[128] = functype(nil, []*Node{anonfield(typs[127]), anonfield(typs[127])}, nil)
+ typs[129] = functype(nil, []*Node{anonfield(typs[65]), anonfield(typs[65])}, nil)
+ typs[130] = functype(nil, []*Node{anonfield(typs[24]), anonfield(typs[24])}, nil)
return typs[:]
}
diff --git a/src/cmd/compile/internal/gc/builtin/runtime.go b/src/cmd/compile/internal/gc/builtin/runtime.go
index 3475d4c375..00448272c5 100644
--- a/src/cmd/compile/internal/gc/builtin/runtime.go
+++ b/src/cmd/compile/internal/gc/builtin/runtime.go
@@ -15,6 +15,7 @@ package runtime
import "unsafe"
func newobject(typ *byte) *any
+func mallocgc(size uintptr, typ *byte, needszero bool) unsafe.Pointer
func panicdivide()
func panicshift()
func panicmakeslicelen()
@@ -174,6 +175,7 @@ func block()
func makeslice(typ *byte, len int, cap int) unsafe.Pointer
func makeslice64(typ *byte, len int64, cap int64) unsafe.Pointer
+func makeslicecopy(typ *byte, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer
func growslice(typ *byte, old []any, cap int) (ary []any)
func memmove(to *any, frm *any, length uintptr)
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go
index 63a58d0a06..d6cc9fa4cf 100644
--- a/src/cmd/compile/internal/gc/fmt.go
+++ b/src/cmd/compile/internal/gc/fmt.go
@@ -1165,92 +1165,93 @@ func (n *Node) stmtfmt(s fmt.State, mode fmtMode) {
}
var opprec = []int{
- OALIGNOF: 8,
- OAPPEND: 8,
- OBYTES2STR: 8,
- OARRAYLIT: 8,
- OSLICELIT: 8,
- ORUNES2STR: 8,
- OCALLFUNC: 8,
- OCALLINTER: 8,
- OCALLMETH: 8,
- OCALL: 8,
- OCAP: 8,
- OCLOSE: 8,
- OCONVIFACE: 8,
- OCONVNOP: 8,
- OCONV: 8,
- OCOPY: 8,
- ODELETE: 8,
- OGETG: 8,
- OLEN: 8,
- OLITERAL: 8,
- OMAKESLICE: 8,
- OMAKE: 8,
- OMAPLIT: 8,
- ONAME: 8,
- ONEW: 8,
- ONONAME: 8,
- OOFFSETOF: 8,
- OPACK: 8,
- OPANIC: 8,
- OPAREN: 8,
- OPRINTN: 8,
- OPRINT: 8,
- ORUNESTR: 8,
- OSIZEOF: 8,
- OSTR2BYTES: 8,
- OSTR2RUNES: 8,
- OSTRUCTLIT: 8,
- OTARRAY: 8,
- OTCHAN: 8,
- OTFUNC: 8,
- OTINTER: 8,
- OTMAP: 8,
- OTSTRUCT: 8,
- OINDEXMAP: 8,
- OINDEX: 8,
- OSLICE: 8,
- OSLICESTR: 8,
- OSLICEARR: 8,
- OSLICE3: 8,
- OSLICE3ARR: 8,
- OSLICEHEADER: 8,
- ODOTINTER: 8,
- ODOTMETH: 8,
- ODOTPTR: 8,
- ODOTTYPE2: 8,
- ODOTTYPE: 8,
- ODOT: 8,
- OXDOT: 8,
- OCALLPART: 8,
- OPLUS: 7,
- ONOT: 7,
- OBITNOT: 7,
- ONEG: 7,
- OADDR: 7,
- ODEREF: 7,
- ORECV: 7,
- OMUL: 6,
- ODIV: 6,
- OMOD: 6,
- OLSH: 6,
- ORSH: 6,
- OAND: 6,
- OANDNOT: 6,
- OADD: 5,
- OSUB: 5,
- OOR: 5,
- OXOR: 5,
- OEQ: 4,
- OLT: 4,
- OLE: 4,
- OGE: 4,
- OGT: 4,
- ONE: 4,
- OSEND: 3,
- OANDAND: 2,
- OOROR: 1,
+ OALIGNOF: 8,
+ OAPPEND: 8,
+ OBYTES2STR: 8,
+ OARRAYLIT: 8,
+ OSLICELIT: 8,
+ ORUNES2STR: 8,
+ OCALLFUNC: 8,
+ OCALLINTER: 8,
+ OCALLMETH: 8,
+ OCALL: 8,
+ OCAP: 8,
+ OCLOSE: 8,
+ OCONVIFACE: 8,
+ OCONVNOP: 8,
+ OCONV: 8,
+ OCOPY: 8,
+ ODELETE: 8,
+ OGETG: 8,
+ OLEN: 8,
+ OLITERAL: 8,
+ OMAKESLICE: 8,
+ OMAKESLICECOPY: 8,
+ OMAKE: 8,
+ OMAPLIT: 8,
+ ONAME: 8,
+ ONEW: 8,
+ ONONAME: 8,
+ OOFFSETOF: 8,
+ OPACK: 8,
+ OPANIC: 8,
+ OPAREN: 8,
+ OPRINTN: 8,
+ OPRINT: 8,
+ ORUNESTR: 8,
+ OSIZEOF: 8,
+ OSTR2BYTES: 8,
+ OSTR2RUNES: 8,
+ OSTRUCTLIT: 8,
+ OTARRAY: 8,
+ OTCHAN: 8,
+ OTFUNC: 8,
+ OTINTER: 8,
+ OTMAP: 8,
+ OTSTRUCT: 8,
+ OINDEXMAP: 8,
+ OINDEX: 8,
+ OSLICE: 8,
+ OSLICESTR: 8,
+ OSLICEARR: 8,
+ OSLICE3: 8,
+ OSLICE3ARR: 8,
+ OSLICEHEADER: 8,
+ ODOTINTER: 8,
+ ODOTMETH: 8,
+ ODOTPTR: 8,
+ ODOTTYPE2: 8,
+ ODOTTYPE: 8,
+ ODOT: 8,
+ OXDOT: 8,
+ OCALLPART: 8,
+ OPLUS: 7,
+ ONOT: 7,
+ OBITNOT: 7,
+ ONEG: 7,
+ OADDR: 7,
+ ODEREF: 7,
+ ORECV: 7,
+ OMUL: 6,
+ ODIV: 6,
+ OMOD: 6,
+ OLSH: 6,
+ ORSH: 6,
+ OAND: 6,
+ OANDNOT: 6,
+ OADD: 5,
+ OSUB: 5,
+ OOR: 5,
+ OXOR: 5,
+ OEQ: 4,
+ OLT: 4,
+ OLE: 4,
+ OGE: 4,
+ OGT: 4,
+ ONE: 4,
+ OSEND: 3,
+ OANDAND: 2,
+ OOROR: 1,
// Statements handled by stmtfmt
OAS: -1,
@@ -1572,6 +1573,9 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) {
}
mode.Fprintf(s, "make(%v)", n.Type)
+ case OMAKESLICECOPY:
+ mode.Fprintf(s, "makeslicecopy(%v, %v, %v)", n.Type, n.Left, n.Right)
+
case OPLUS, ONEG, OADDR, OBITNOT, ODEREF, ONOT, ORECV:
// Unary
mode.Fprintf(s, "%#v", n.Op)
diff --git a/src/cmd/compile/internal/gc/op_string.go b/src/cmd/compile/internal/gc/op_string.go
index 3622884527..41d588309c 100644
--- a/src/cmd/compile/internal/gc/op_string.go
+++ b/src/cmd/compile/internal/gc/op_string.go
@@ -82,89 +82,90 @@ func _() {
_ = x[OMAKECHAN-71]
_ = x[OMAKEMAP-72]
_ = x[OMAKESLICE-73]
- _ = x[OMUL-74]
- _ = x[ODIV-75]
- _ = x[OMOD-76]
- _ = x[OLSH-77]
- _ = x[ORSH-78]
- _ = x[OAND-79]
- _ = x[OANDNOT-80]
- _ = x[ONEW-81]
- _ = x[ONEWOBJ-82]
- _ = x[ONOT-83]
- _ = x[OBITNOT-84]
- _ = x[OPLUS-85]
- _ = x[ONEG-86]
- _ = x[OOROR-87]
- _ = x[OPANIC-88]
- _ = x[OPRINT-89]
- _ = x[OPRINTN-90]
- _ = x[OPAREN-91]
- _ = x[OSEND-92]
- _ = x[OSLICE-93]
- _ = x[OSLICEARR-94]
- _ = x[OSLICESTR-95]
- _ = x[OSLICE3-96]
- _ = x[OSLICE3ARR-97]
- _ = x[OSLICEHEADER-98]
- _ = x[ORECOVER-99]
- _ = x[ORECV-100]
- _ = x[ORUNESTR-101]
- _ = x[OSELRECV-102]
- _ = x[OSELRECV2-103]
- _ = x[OIOTA-104]
- _ = x[OREAL-105]
- _ = x[OIMAG-106]
- _ = x[OCOMPLEX-107]
- _ = x[OALIGNOF-108]
- _ = x[OOFFSETOF-109]
- _ = x[OSIZEOF-110]
- _ = x[OBLOCK-111]
- _ = x[OBREAK-112]
- _ = x[OCASE-113]
- _ = x[OCONTINUE-114]
- _ = x[ODEFER-115]
- _ = x[OEMPTY-116]
- _ = x[OFALL-117]
- _ = x[OFOR-118]
- _ = x[OFORUNTIL-119]
- _ = x[OGOTO-120]
- _ = x[OIF-121]
- _ = x[OLABEL-122]
- _ = x[OGO-123]
- _ = x[ORANGE-124]
- _ = x[ORETURN-125]
- _ = x[OSELECT-126]
- _ = x[OSWITCH-127]
- _ = x[OTYPESW-128]
- _ = x[OTCHAN-129]
- _ = x[OTMAP-130]
- _ = x[OTSTRUCT-131]
- _ = x[OTINTER-132]
- _ = x[OTFUNC-133]
- _ = x[OTARRAY-134]
- _ = x[ODDD-135]
- _ = x[OINLCALL-136]
- _ = x[OEFACE-137]
- _ = x[OITAB-138]
- _ = x[OIDATA-139]
- _ = x[OSPTR-140]
- _ = x[OCLOSUREVAR-141]
- _ = x[OCFUNC-142]
- _ = x[OCHECKNIL-143]
- _ = x[OVARDEF-144]
- _ = x[OVARKILL-145]
- _ = x[OVARLIVE-146]
- _ = x[ORESULT-147]
- _ = x[OINLMARK-148]
- _ = x[ORETJMP-149]
- _ = x[OGETG-150]
- _ = x[OEND-151]
+ _ = x[OMAKESLICECOPY-74]
+ _ = x[OMUL-75]
+ _ = x[ODIV-76]
+ _ = x[OMOD-77]
+ _ = x[OLSH-78]
+ _ = x[ORSH-79]
+ _ = x[OAND-80]
+ _ = x[OANDNOT-81]
+ _ = x[ONEW-82]
+ _ = x[ONEWOBJ-83]
+ _ = x[ONOT-84]
+ _ = x[OBITNOT-85]
+ _ = x[OPLUS-86]
+ _ = x[ONEG-87]
+ _ = x[OOROR-88]
+ _ = x[OPANIC-89]
+ _ = x[OPRINT-90]
+ _ = x[OPRINTN-91]
+ _ = x[OPAREN-92]
+ _ = x[OSEND-93]
+ _ = x[OSLICE-94]
+ _ = x[OSLICEARR-95]
+ _ = x[OSLICESTR-96]
+ _ = x[OSLICE3-97]
+ _ = x[OSLICE3ARR-98]
+ _ = x[OSLICEHEADER-99]
+ _ = x[ORECOVER-100]
+ _ = x[ORECV-101]
+ _ = x[ORUNESTR-102]
+ _ = x[OSELRECV-103]
+ _ = x[OSELRECV2-104]
+ _ = x[OIOTA-105]
+ _ = x[OREAL-106]
+ _ = x[OIMAG-107]
+ _ = x[OCOMPLEX-108]
+ _ = x[OALIGNOF-109]
+ _ = x[OOFFSETOF-110]
+ _ = x[OSIZEOF-111]
+ _ = x[OBLOCK-112]
+ _ = x[OBREAK-113]
+ _ = x[OCASE-114]
+ _ = x[OCONTINUE-115]
+ _ = x[ODEFER-116]
+ _ = x[OEMPTY-117]
+ _ = x[OFALL-118]
+ _ = x[OFOR-119]
+ _ = x[OFORUNTIL-120]
+ _ = x[OGOTO-121]
+ _ = x[OIF-122]
+ _ = x[OLABEL-123]
+ _ = x[OGO-124]
+ _ = x[ORANGE-125]
+ _ = x[ORETURN-126]
+ _ = x[OSELECT-127]
+ _ = x[OSWITCH-128]
+ _ = x[OTYPESW-129]
+ _ = x[OTCHAN-130]
+ _ = x[OTMAP-131]
+ _ = x[OTSTRUCT-132]
+ _ = x[OTINTER-133]
+ _ = x[OTFUNC-134]
+ _ = x[OTARRAY-135]
+ _ = x[ODDD-136]
+ _ = x[OINLCALL-137]
+ _ = x[OEFACE-138]
+ _ = x[OITAB-139]
+ _ = x[OIDATA-140]
+ _ = x[OSPTR-141]
+ _ = x[OCLOSUREVAR-142]
+ _ = x[OCFUNC-143]
+ _ = x[OCHECKNIL-144]
+ _ = x[OVARDEF-145]
+ _ = x[OVARKILL-146]
+ _ = x[OVARLIVE-147]
+ _ = x[ORESULT-148]
+ _ = x[OINLMARK-149]
+ _ = x[ORETJMP-150]
+ _ = x[OGETG-151]
+ _ = x[OEND-152]
}
-const _Op_name = "XXXNAMENONAMETYPEPACKLITERALADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMULDIVMODLSHRSHANDANDNOTNEWNEWOBJNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFBLOCKBREAKCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKRETJMPGETGEND"
+const _Op_name = "XXXNAMENONAMETYPEPACKLITERALADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNEWOBJNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFBLOCKBREAKCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKRETJMPGETGEND"
-var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 36, 39, 45, 49, 55, 61, 70, 82, 91, 100, 112, 121, 123, 126, 136, 143, 150, 157, 161, 165, 173, 181, 190, 198, 201, 206, 213, 220, 226, 235, 243, 251, 257, 261, 270, 277, 281, 284, 291, 299, 307, 314, 320, 323, 329, 336, 344, 348, 355, 363, 365, 367, 369, 371, 373, 375, 380, 385, 393, 396, 405, 408, 412, 420, 427, 436, 439, 442, 445, 448, 451, 454, 460, 463, 469, 472, 478, 482, 485, 489, 494, 499, 505, 510, 514, 519, 527, 535, 541, 550, 561, 568, 572, 579, 586, 594, 598, 602, 606, 613, 620, 628, 634, 639, 644, 648, 656, 661, 666, 670, 673, 681, 685, 687, 692, 694, 699, 705, 711, 717, 723, 728, 732, 739, 745, 750, 756, 759, 766, 771, 775, 780, 784, 794, 799, 807, 813, 820, 827, 833, 840, 846, 850, 853}
+var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 36, 39, 45, 49, 55, 61, 70, 82, 91, 100, 112, 121, 123, 126, 136, 143, 150, 157, 161, 165, 173, 181, 190, 198, 201, 206, 213, 220, 226, 235, 243, 251, 257, 261, 270, 277, 281, 284, 291, 299, 307, 314, 320, 323, 329, 336, 344, 348, 355, 363, 365, 367, 369, 371, 373, 375, 380, 385, 393, 396, 405, 408, 412, 420, 427, 436, 449, 452, 455, 458, 461, 464, 467, 473, 476, 482, 485, 491, 495, 498, 502, 507, 512, 518, 523, 527, 532, 540, 548, 554, 563, 574, 581, 585, 592, 599, 607, 611, 615, 619, 626, 633, 641, 647, 652, 657, 661, 669, 674, 679, 683, 686, 694, 698, 700, 705, 707, 712, 718, 724, 730, 736, 741, 745, 752, 758, 763, 769, 772, 779, 784, 788, 793, 797, 807, 812, 820, 826, 833, 840, 846, 853, 859, 863, 866}
func (i Op) String() string {
if i >= Op(len(_Op_index)-1) {
diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go
index 8bce71b883..6b6107290a 100644
--- a/src/cmd/compile/internal/gc/order.go
+++ b/src/cmd/compile/internal/gc/order.go
@@ -319,9 +319,80 @@ func (o *Order) cleanTemp(top ordermarker) {
// stmtList orders each of the statements in the list.
func (o *Order) stmtList(l Nodes) {
- for _, n := range l.Slice() {
- o.stmt(n)
+ s := l.Slice()
+ for i := range s {
+ orderMakeSliceCopy(s[i:])
+ o.stmt(s[i])
+ }
+}
+
+// orderMakeSliceCopy matches the pattern:
+// m = OMAKESLICE([]T, x); OCOPY(m, s)
+// and rewrites it to:
+// m = OMAKESLICECOPY([]T, x, s); nil
+func orderMakeSliceCopy(s []*Node) {
+ const go115makeslicecopy = true
+ if !go115makeslicecopy {
+ return
}
+
+ if Debug['N'] != 0 || instrumenting {
+ return
+ }
+
+ if len(s) < 2 {
+ return
+ }
+
+ asn := s[0]
+ copyn := s[1]
+
+ if asn == nil || asn.Op != OAS {
+ return
+ }
+ if asn.Left.Op != ONAME {
+ return
+ }
+ if asn.Left.isBlank() {
+ return
+ }
+ maken := asn.Right
+ if maken == nil || maken.Op != OMAKESLICE {
+ return
+ }
+ if maken.Esc == EscNone {
+ return
+ }
+ if maken.Left == nil || maken.Right != nil {
+ return
+ }
+ if copyn.Op != OCOPY {
+ return
+ }
+ if copyn.Left.Op != ONAME {
+ return
+ }
+ if asn.Left.Sym != copyn.Left.Sym {
+ return
+ }
+ if copyn.Right.Op != ONAME {
+ return
+ }
+
+ if copyn.Left.Sym == copyn.Right.Sym {
+ return
+ }
+
+ maken.Op = OMAKESLICECOPY
+ maken.Right = copyn.Right
+ // Set bounded when m = OMAKESLICE([]T, len(s)); OCOPY(m, s)
+ maken.SetBounded(maken.Left.Op == OLEN && samesafeexpr(maken.Left.Left, copyn.Right))
+
+ maken = typecheck(maken, ctxExpr)
+
+ s[1] = nil // remove separate copy call
+
+ return
}
// edge inserts coverage instrumentation for libfuzzer.
@@ -1150,6 +1221,7 @@ func (o *Order) expr(n, lhs *Node) *Node {
OMAKECHAN,
OMAKEMAP,
OMAKESLICE,
+ OMAKESLICECOPY,
ONEW,
OREAL,
ORECOVER,
diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go
index a9bd723351..b658410c53 100644
--- a/src/cmd/compile/internal/gc/syntax.go
+++ b/src/cmd/compile/internal/gc/syntax.go
@@ -208,12 +208,16 @@ func (n *Node) MarkNonNil() {
// SetBounded indicates whether operation n does not need safety checks.
// When n is an index or slice operation, n does not need bounds checks.
// When n is a dereferencing operation, n does not need nil checks.
+// When n is a makeslice+copy operation, n does not need length and cap checks.
func (n *Node) SetBounded(b bool) {
switch n.Op {
case OINDEX, OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR, OSLICESTR:
// No bounds checks needed.
case ODOTPTR, ODEREF:
// No nil check needed.
+ case OMAKESLICECOPY:
+ // No length and cap checks needed
+ // since new slice and copied over slice data have same length.
default:
Fatalf("SetBounded(%v)", n)
}
@@ -714,30 +718,38 @@ const (
ODCLCONST // const pi = 3.14
ODCLTYPE // type Int int or type Int = int
- ODELETE // delete(Left, Right)
- ODOT // Left.Sym (Left is of struct type)
- ODOTPTR // Left.Sym (Left is of pointer to struct type)
- ODOTMETH // Left.Sym (Left is non-interface, Right is method name)
- ODOTINTER // Left.Sym (Left is interface, Right is method name)
- OXDOT // Left.Sym (before rewrite to one of the preceding)
- ODOTTYPE // Left.Right or Left.Type (.Right during parsing, .Type once resolved); after walk, .Right contains address of interface type descriptor and .Right.Right contains address of concrete type descriptor
- ODOTTYPE2 // Left.Right or Left.Type (.Right during parsing, .Type once resolved; on rhs of OAS2DOTTYPE); after walk, .Right contains address of interface type descriptor
- OEQ // Left == Right
- ONE // Left != Right
- OLT // Left < Right
- OLE // Left <= Right
- OGE // Left >= Right
- OGT // Left > Right
- ODEREF // *Left
- OINDEX // Left[Right] (index of array or slice)
- OINDEXMAP // Left[Right] (index of map)
- OKEY // Left:Right (key:value in struct/array/map literal)
- OSTRUCTKEY // Sym:Left (key:value in struct literal, after type checking)
- OLEN // len(Left)
- OMAKE // make(List) (before type checking converts to one of the following)
- OMAKECHAN // make(Type, Left) (type is chan)
- OMAKEMAP // make(Type, Left) (type is map)
- OMAKESLICE // make(Type, Left, Right) (type is slice)
+ ODELETE // delete(Left, Right)
+ ODOT // Left.Sym (Left is of struct type)
+ ODOTPTR // Left.Sym (Left is of pointer to struct type)
+ ODOTMETH // Left.Sym (Left is non-interface, Right is method name)
+ ODOTINTER // Left.Sym (Left is interface, Right is method name)
+ OXDOT // Left.Sym (before rewrite to one of the preceding)
+ ODOTTYPE // Left.Right or Left.Type (.Right during parsing, .Type once resolved); after walk, .Right contains address of interface type descriptor and .Right.Right contains address of concrete type descriptor
+ ODOTTYPE2 // Left.Right or Left.Type (.Right during parsing, .Type once resolved; on rhs of OAS2DOTTYPE); after walk, .Right contains address of interface type descriptor
+ OEQ // Left == Right
+ ONE // Left != Right
+ OLT // Left < Right
+ OLE // Left <= Right
+ OGE // Left >= Right
+ OGT // Left > Right
+ ODEREF // *Left
+ OINDEX // Left[Right] (index of array or slice)
+ OINDEXMAP // Left[Right] (index of map)
+ OKEY // Left:Right (key:value in struct/array/map literal)
+ OSTRUCTKEY // Sym:Left (key:value in struct literal, after type checking)
+ OLEN // len(Left)
+ OMAKE // make(List) (before type checking converts to one of the following)
+ OMAKECHAN // make(Type, Left) (type is chan)
+ OMAKEMAP // make(Type, Left) (type is map)
+ OMAKESLICE // make(Type, Left, Right) (type is slice)
+ OMAKESLICECOPY // makeslicecopy(Type, Left, Right) (type is slice; Left is length and Right is the copied from slice)
+ // OMAKESLICECOPY is created by the order pass and corresponds to:
+ // s = make(Type, Left); copy(s, Right)
+ //
+ // Bounded can be set on the node when Left == len(Right) is known at compile time.
+ //
+ // This node is created so the walk pass can optimize this pattern which would
+ // otherwise be hard to detect after the order pass.
OMUL // Left * Right
ODIV // Left / Right
OMOD // Left % Right
diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index 6e04908b46..8132aee863 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -1149,6 +1149,49 @@ func typecheck1(n *Node, top int) (res *Node) {
n.List.SetFirst(l)
n.List.SetSecond(c)
+ case OMAKESLICECOPY:
+ // Errors here are Fatalf instead of yyerror because only the compiler
+ // can construct an OMAKESLICECOPY node.
+ // Components used in OMAKESCLICECOPY that are supplied by parsed source code
+ // have already been typechecked in OMAKE and OCOPY earlier.
+ ok |= ctxExpr
+
+ t := n.Type
+
+ if t == nil {
+ Fatalf("no type specified for OMAKESLICECOPY")
+ }
+
+ if !t.IsSlice() {
+ Fatalf("invalid type %v for OMAKESLICECOPY", n.Type)
+ }
+
+ if n.Left == nil {
+ Fatalf("missing len argument for OMAKESLICECOPY")
+ }
+
+ if n.Right == nil {
+ Fatalf("missing slice argument to copy for OMAKESLICECOPY")
+ }
+
+ n.Left = typecheck(n.Left, ctxExpr)
+ n.Right = typecheck(n.Right, ctxExpr)
+
+ n.Left = defaultlit(n.Left, types.Types[TINT])
+
+ if !n.Left.Type.IsInteger() && n.Type.Etype != TIDEAL {
+ yyerror("non-integer len argument in OMAKESLICECOPY")
+ }
+
+ if Isconst(n.Left, CTINT) {
+ if n.Left.Val().U.(*Mpint).Cmp(maxintval[TINT]) > 0 {
+ Fatalf("len for OMAKESLICECOPY too large")
+ }
+ if n.Left.Int64() < 0 {
+ Fatalf("len for OMAKESLICECOPY must be non-negative")
+ }
+ }
+
case OSLICE, OSLICE3:
ok |= ctxExpr
n.Left = typecheck(n.Left, ctxExpr)
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index 84ba528bc9..1e6d913ae6 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -1390,6 +1390,63 @@ opswitch:
n = m
}
+ case OMAKESLICECOPY:
+ if n.Esc == EscNone {
+ Fatalf("OMAKESLICECOPY with EscNone: %v", n)
+ }
+
+ t := n.Type
+ if t.Elem().NotInHeap() {
+ Fatalf("%v is go:notinheap; heap allocation disallowed", t.Elem())
+ }
+
+ length := conv(n.Left, types.Types[TINT])
+ copylen := nod(OLEN, n.Right, nil)
+ copyptr := nod(OSPTR, n.Right, nil)
+
+ if !types.Haspointers(t.Elem()) && n.Bounded() {
+ // When len(to)==len(from) and elements have no pointers:
+ // replace make+copy with runtime.mallocgc+runtime.memmove.
+
+ // We do not check for overflow of len(to)*elem.Width here
+ // since len(from) is an existing checked slice capacity
+ // with same elem.Width for the from slice.
+ size := nod(OMUL, conv(length, types.Types[TUINTPTR]), conv(nodintconst(t.Elem().Width), types.Types[TUINTPTR]))
+
+ // instantiate mallocgc(size uintptr, typ *byte, needszero bool) unsafe.Pointer
+ fn := syslook("mallocgc")
+ sh := nod(OSLICEHEADER, nil, nil)
+ sh.Left = mkcall1(fn, types.Types[TUNSAFEPTR], init, size, nodnil(), nodbool(false))
+ sh.Left.MarkNonNil()
+ sh.List.Set2(length, length)
+ sh.Type = t
+
+ s := temp(t)
+ r := typecheck(nod(OAS, s, sh), ctxStmt)
+ r = walkexpr(r, init)
+ init.Append(r)
+
+ // instantiate memmove(to *any, frm *any, size uintptr)
+ fn = syslook("memmove")
+ fn = substArgTypes(fn, t.Elem(), t.Elem())
+ ncopy := mkcall1(fn, nil, init, nod(OSPTR, s, nil), copyptr, size)
+ ncopy = typecheck(ncopy, ctxStmt)
+ ncopy = walkexpr(ncopy, init)
+ init.Append(ncopy)
+
+ n = s
+ } else { // Replace make+copy with runtime.makeslicecopy.
+ // instantiate makeslicecopy(typ *byte, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer
+ fn := syslook("makeslicecopy")
+ s := nod(OSLICEHEADER, nil, nil)
+ s.Left = mkcall1(fn, types.Types[TUNSAFEPTR], init, typename(t.Elem()), length, copylen, conv(copyptr, types.Types[TUNSAFEPTR]))
+ s.Left.MarkNonNil()
+ s.List.Set2(length, length)
+ s.Type = t
+ n = typecheck(s, ctxExpr)
+ n = walkexpr(n, init)
+ }
+
case ORUNESTR:
a := nodnil()
if n.Esc == EscNone {
@@ -3772,6 +3829,9 @@ func candiscard(n *Node) bool {
// Difficult to tell what sizes are okay.
case OMAKESLICE:
return false
+
+ case OMAKESLICECOPY:
+ return false
}
if !candiscard(n.Left) || !candiscard(n.Right) || !candiscardlist(n.Ninit) || !candiscardlist(n.Nbody) || !candiscardlist(n.List) || !candiscardlist(n.Rlist) {
diff --git a/src/runtime/slice.go b/src/runtime/slice.go
index 4ea4478601..d9949e7939 100644
--- a/src/runtime/slice.go
+++ b/src/runtime/slice.go
@@ -31,6 +31,55 @@ func panicmakeslicecap() {
panic(errorString("makeslice: cap out of range"))
}
+// makeslicecopy allocates a slice of "tolen" elements of type "et",
+// then copies "fromlen" elements of type "et" into that new allocation from "from".
+func makeslicecopy(et *_type, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer {
+ var tomem, copymem uintptr
+ if uintptr(tolen) > uintptr(fromlen) {
+ var overflow bool
+ tomem, overflow = math.MulUintptr(et.size, uintptr(tolen))
+ if overflow || tomem > maxAlloc || tolen < 0 {
+ panicmakeslicelen()
+ }
+ copymem = et.size * uintptr(fromlen)
+ } else {
+ // fromlen is a known good length providing and equal or greater than tolen,
+ // thereby making tolen a good slice length too as from and to slices have the
+ // same element width.
+ tomem = et.size * uintptr(tolen)
+ copymem = tomem
+ }
+
+ var to unsafe.Pointer
+ if et.ptrdata == 0 {
+ to = mallocgc(tomem, nil, false)
+ if copymem < tomem {
+ memclrNoHeapPointers(add(to, copymem), tomem-copymem)
+ }
+ } else {
+ // Note: can't use rawmem (which avoids zeroing of memory), because then GC can scan uninitialized memory.
+ to = mallocgc(tomem, et, true)
+ if writeBarrier.enabled {
+ // Only shade the pointers in old.array since we know the destination slice to
+ // only contains nil pointers because it has been cleared during alloc.
+ bulkBarrierPreWriteSrcOnly(uintptr(to), uintptr(from), copymem)
+ }
+ }
+
+ if raceenabled {
+ callerpc := getcallerpc()
+ pc := funcPC(makeslicecopy)
+ racereadrangepc(from, copymem, callerpc, pc)
+ }
+ if msanenabled {
+ msanread(from, copymem)
+ }
+
+ memmove(to, from, copymem)
+
+ return to
+}
+
func makeslice(et *_type, len, cap int) unsafe.Pointer {
mem, overflow := math.MulUintptr(et.size, uintptr(cap))
if overflow || mem > maxAlloc || len < 0 || len > cap {
diff --git a/src/runtime/slice_test.go b/src/runtime/slice_test.go
index 0463fc70a7..e963a43dd3 100644
--- a/src/runtime/slice_test.go
+++ b/src/runtime/slice_test.go
@@ -10,6 +10,84 @@ import (
const N = 20
+func BenchmarkMakeSliceCopy(b *testing.B) {
+ const length = 32
+ var bytes = make([]byte, 8*length)
+ var ints = make([]int, length)
+ var ptrs = make([]*byte, length)
+ b.Run("mallocmove", func(b *testing.B) {
+ b.Run("Byte", func(b *testing.B) {
+ var x []byte
+ for i := 0; i < b.N; i++ {
+ x = make([]byte, len(bytes))
+ copy(x, bytes)
+ }
+ })
+ b.Run("Int", func(b *testing.B) {
+ var x []int
+ for i := 0; i < b.N; i++ {
+ x = make([]int, len(ints))
+ copy(x, ints)
+ }
+ })
+ b.Run("Ptr", func(b *testing.B) {
+ var x []*byte
+ for i := 0; i < b.N; i++ {
+ x = make([]*byte, len(ptrs))
+ copy(x, ptrs)
+ }
+
+ })
+ })
+ b.Run("makecopy", func(b *testing.B) {
+ b.Run("Byte", func(b *testing.B) {
+ var x []byte
+ for i := 0; i < b.N; i++ {
+ x = make([]byte, 8*length)
+ copy(x, bytes)
+ }
+ })
+ b.Run("Int", func(b *testing.B) {
+ var x []int
+ for i := 0; i < b.N; i++ {
+ x = make([]int, length)
+ copy(x, ints)
+ }
+ })
+ b.Run("Ptr", func(b *testing.B) {
+ var x []*byte
+ for i := 0; i < b.N; i++ {
+ x = make([]*byte, length)
+ copy(x, ptrs)
+ }
+
+ })
+ })
+ b.Run("nilappend", func(b *testing.B) {
+ b.Run("Byte", func(b *testing.B) {
+ var x []byte
+ for i := 0; i < b.N; i++ {
+ x = append([]byte(nil), bytes...)
+ _ = x
+ }
+ })
+ b.Run("Int", func(b *testing.B) {
+ var x []int
+ for i := 0; i < b.N; i++ {
+ x = append([]int(nil), ints...)
+ _ = x
+ }
+ })
+ b.Run("Ptr", func(b *testing.B) {
+ var x []*byte
+ for i := 0; i < b.N; i++ {
+ x = append([]*byte(nil), ptrs...)
+ _ = x
+ }
+ })
+ })
+}
+
type (
struct24 struct{ a, b, c int64 }
struct32 struct{ a, b, c, d int64 }
diff --git a/test/codegen/slices.go b/test/codegen/slices.go
index cf569e27fb..40e857f9f6 100644
--- a/test/codegen/slices.go
+++ b/test/codegen/slices.go
@@ -104,6 +104,189 @@ func SliceExtensionInt64(s []int, l64 int64) []int {
return append(s, make([]int, l64)...)
}
+// ------------------ //
+// Make+Copy //
+// ------------------ //
+
+// Issue #26252 - avoid memclr for make+copy
+
+func SliceMakeCopyLen(s []int) []int {
+ // amd64:`.*runtime\.mallocgc`
+ // amd64:`.*runtime\.memmove`
+ // amd64:-`.*runtime\.makeslice`
+ a := make([]int, len(s))
+ copy(a, s)
+ return a
+}
+
+func SliceMakeCopyLenPtr(s []*int) []*int {
+ // amd64:`.*runtime\.makeslicecopy`
+ // amd64:-`.*runtime\.makeslice\(`
+ // amd64:-`.*runtime\.typedslicecopy
+ a := make([]*int, len(s))
+ copy(a, s)
+ return a
+}
+
+func SliceMakeCopyConst(s []int) []int {
+ // amd64:`.*runtime\.makeslicecopy`
+ // amd64:-`.*runtime\.makeslice\(`
+ // amd64:-`.*runtime\.memmove`
+ a := make([]int, 4)
+ copy(a, s)
+ return a
+}
+
+func SliceMakeCopyConstPtr(s []*int) []*int {
+ // amd64:`.*runtime\.makeslicecopy`
+ // amd64:-`.*runtime\.makeslice\(`
+ // amd64:-`.*runtime\.typedslicecopy
+ a := make([]*int, 4)
+ copy(a, s)
+ return a
+}
+
+func SliceMakeCopyNoOptNoDeref(s []*int) []*int {
+ a := new([]*int)
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ *a = make([]*int, 4)
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.typedslicecopy`
+ copy(*a, s)
+ return *a
+}
+
+func SliceMakeCopyNoOptNoVar(s []*int) []*int {
+ a := make([][]*int, 1)
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ a[0] = make([]*int, 4)
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.typedslicecopy`
+ copy(a[0], s)
+ return a[0]
+}
+
+func SliceMakeCopyNoOptBlank(s []*int) []*int {
+ var a []*int
+ // amd64:-`.*runtime\.makeslicecopy`
+ _ = make([]*int, 4)
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.typedslicecopy`
+ copy(a, s)
+ return a
+}
+
+func SliceMakeCopyNoOptNoMake(s []*int) []*int {
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:-`.*runtime\.objectnew`
+ a := *new([]*int)
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.typedslicecopy`
+ copy(a, s)
+ return a
+}
+
+func SliceMakeCopyNoOptNoHeapAlloc(s []*int) int {
+ // amd64:-`.*runtime\.makeslicecopy`
+ a := make([]*int, 4)
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.typedslicecopy`
+ copy(a, s)
+ return cap(a)
+}
+
+func SliceMakeCopyNoOptNoCap(s []*int) []*int {
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ a := make([]*int, 0, 4)
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.typedslicecopy`
+ copy(a, s)
+ return a
+}
+
+func SliceMakeCopyNoOptNoCopy(s []*int) []*int {
+ copy := func(x, y []*int) {}
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ a := make([]*int, 4)
+ // amd64:-`.*runtime\.makeslicecopy`
+ copy(a, s)
+ return a
+}
+
+func SliceMakeCopyNoOptWrongOrder(s []*int) []*int {
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ a := make([]*int, 4)
+ // amd64:`.*runtime\.typedslicecopy`
+ // amd64:-`.*runtime\.makeslicecopy`
+ copy(s, a)
+ return a
+}
+
+func SliceMakeCopyNoOptWrongAssign(s []*int) []*int {
+ var a []*int
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ s = make([]*int, 4)
+ // amd64:`.*runtime\.typedslicecopy`
+ // amd64:-`.*runtime\.makeslicecopy`
+ copy(a, s)
+ return s
+}
+
+func SliceMakeCopyNoOptCopyLength(s []*int) (int, []*int) {
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ a := make([]*int, 4)
+ // amd64:`.*runtime\.typedslicecopy`
+ // amd64:-`.*runtime\.makeslicecopy`
+ n := copy(a, s)
+ return n, a
+}
+
+func SliceMakeCopyNoOptSelfCopy(s []*int) []*int {
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ a := make([]*int, 4)
+ // amd64:`.*runtime\.typedslicecopy`
+ // amd64:-`.*runtime\.makeslicecopy`
+ copy(a, a)
+ return a
+}
+
+func SliceMakeCopyNoOptTargetReference(s []*int) []*int {
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ a := make([]*int, 4)
+ // amd64:`.*runtime\.typedslicecopy`
+ // amd64:-`.*runtime\.makeslicecopy`
+ copy(a, s[:len(a)])
+ return a
+}
+
+func SliceMakeCopyNoOptCap(s []int) []int {
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ a := make([]int, len(s), 9)
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.memmove`
+ copy(a, s)
+ return a
+}
+
+func SliceMakeCopyNoMemmoveDifferentLen(s []int) []int {
+ // amd64:`.*runtime\.makeslicecopy`
+ // amd64:-`.*runtime\.memmove`
+ a := make([]int, len(s)-1)
+ // amd64:-`.*runtime\.memmove`
+ copy(a, s)
+ return a
+}
+
// ---------------------- //
// Nil check of &s[0] //
// ---------------------- //
diff --git a/test/makeslice.go b/test/makeslice.go
new file mode 100644
index 0000000000..0ffecd7c43
--- /dev/null
+++ b/test/makeslice.go
@@ -0,0 +1,149 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "strings"
+ "unsafe"
+)
+
+func main() {
+ n := -1
+ testInts(uint64(n))
+ testBytes(uint64(n))
+
+ var t *byte
+ if unsafe.Sizeof(t) == 8 {
+ // Test mem > maxAlloc
+ testInts(1 << 59)
+
+ // Test elem.size*cap overflow
+ testInts(1<<63 - 1)
+
+ testInts(1<<64 - 1)
+ testBytes(1<<64 - 1)
+ } else {
+ testInts(1<<31 - 1)
+
+ // Test elem.size*cap overflow
+ testInts(1<<32 - 1)
+ testBytes(1<<32 - 1)
+ }
+}
+
+func shouldPanic(str string, f func()) {
+ defer func() {
+ err := recover()
+ if err == nil {
+ panic("did not panic")
+ }
+ s := err.(error).Error()
+ if !strings.Contains(s, str) {
+ panic("got panic " + s + ", want " + str)
+ }
+ }()
+
+ f()
+}
+
+func testInts(n uint64) {
+ testMakeInts(n)
+ testMakeCopyInts(n)
+ testMakeInAppendInts(n)
+}
+
+func testBytes(n uint64) {
+ testMakeBytes(n)
+ testMakeCopyBytes(n)
+ testMakeInAppendBytes(n)
+}
+
+// Test make panics for given length or capacity n.
+func testMakeInts(n uint64) {
+ type T []int
+ shouldPanic("len out of range", func() { _ = make(T, int(n)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, int(n)) })
+ shouldPanic("len out of range", func() { _ = make(T, uint(n)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, uint(n)) })
+ shouldPanic("len out of range", func() { _ = make(T, int64(n)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, int64(n)) })
+ shouldPanic("len out of range", func() { _ = make(T, uint64(n)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, uint64(n)) })
+}
+
+func testMakeBytes(n uint64) {
+ type T []byte
+ shouldPanic("len out of range", func() { _ = make(T, int(n)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, int(n)) })
+ shouldPanic("len out of range", func() { _ = make(T, uint(n)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, uint(n)) })
+ shouldPanic("len out of range", func() { _ = make(T, int64(n)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, int64(n)) })
+ shouldPanic("len out of range", func() { _ = make(T, uint64(n)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, uint64(n)) })
+}
+
+// Test make+copy panics since the gc compiler optimizes these
+// to runtime.makeslicecopy calls.
+func testMakeCopyInts(n uint64) {
+ type T []int
+ var c = make(T, 8)
+ shouldPanic("len out of range", func() { x := make(T, int(n)); copy(x, c) })
+ shouldPanic("cap out of range", func() { x := make(T, 0, int(n)); copy(x, c) })
+ shouldPanic("len out of range", func() { x := make(T, uint(n)); copy(x, c) })
+ shouldPanic("cap out of range", func() { x := make(T, 0, uint(n)); copy(x, c) })
+ shouldPanic("len out of range", func() { x := make(T, int64(n)); copy(x, c) })
+ shouldPanic("cap out of range", func() { x := make(T, 0, int64(n)); copy(x, c) })
+ shouldPanic("len out of range", func() { x := make(T, uint64(n)); copy(x, c) })
+ shouldPanic("cap out of range", func() { x := make(T, 0, uint64(n)); copy(x, c) })
+}
+
+func testMakeCopyBytes(n uint64) {
+ type T []byte
+ var c = make(T, 8)
+ shouldPanic("len out of range", func() { x := make(T, int(n)); copy(x, c) })
+ shouldPanic("cap out of range", func() { x := make(T, 0, int(n)); copy(x, c) })
+ shouldPanic("len out of range", func() { x := make(T, uint(n)); copy(x, c) })
+ shouldPanic("cap out of range", func() { x := make(T, 0, uint(n)); copy(x, c) })
+ shouldPanic("len out of range", func() { x := make(T, int64(n)); copy(x, c) })
+ shouldPanic("cap out of range", func() { x := make(T, 0, int64(n)); copy(x, c) })
+ shouldPanic("len out of range", func() { x := make(T, uint64(n)); copy(x, c) })
+ shouldPanic("cap out of range", func() { x := make(T, 0, uint64(n)); copy(x, c) })
+}
+
+// Test make in append panics for int slices since the gc compiler optimizes makes in appends.
+func testMakeInAppendInts(n uint64) {
+ type T []int
+ for _, length := range []int{0, 1} {
+ t := make(T, length)
+ shouldPanic("len out of range", func() { _ = append(t, make(T, int(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, int64(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int64(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, uint64(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, uint64(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, int(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, uint(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, uint(n))...) })
+ }
+}
+
+func testMakeInAppendBytes(n uint64) {
+ type T []byte
+ for _, length := range []int{0, 1} {
+ t := make(T, length)
+ shouldPanic("len out of range", func() { _ = append(t, make(T, int(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, uint(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, uint(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, int64(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int64(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, uint64(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, uint64(n))...) })
+ }
+}