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,11 +319,82 @@ 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. func (o *Order) edge() { if Debug_libfuzzer == 0 { @@ -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))...) }) + } +}