diff --git a/src/cmd/addr2line/main.go b/src/cmd/addr2line/main.go index 267f4170a8..018802940b 100644 --- a/src/cmd/addr2line/main.go +++ b/src/cmd/addr2line/main.go @@ -61,6 +61,7 @@ func main() { if err != nil { log.Fatal(err) } + defer f.Close() tab, err := f.PCLineTable() if err != nil { diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go index 325bf4aa0e..4e9f11c8b3 100644 --- a/src/cmd/compile/internal/gc/builtin.go +++ b/src/cmd/compile/internal/gc/builtin.go @@ -51,110 +51,105 @@ var runtimeDecls = [...]struct { {"decoderune", funcTag, 50}, {"countrunes", funcTag, 51}, {"convI2I", funcTag, 52}, - {"convT2E", funcTag, 53}, - {"convT2E16", funcTag, 52}, - {"convT2E32", funcTag, 52}, - {"convT2E64", funcTag, 52}, - {"convT2Estring", funcTag, 52}, - {"convT2Eslice", funcTag, 52}, - {"convT2Enoptr", funcTag, 53}, - {"convT2I", funcTag, 53}, - {"convT2I16", funcTag, 52}, - {"convT2I32", funcTag, 52}, - {"convT2I64", funcTag, 52}, - {"convT2Istring", funcTag, 52}, - {"convT2Islice", funcTag, 52}, - {"convT2Inoptr", funcTag, 53}, + {"convT16", funcTag, 54}, + {"convT32", funcTag, 54}, + {"convT64", funcTag, 54}, + {"convTstring", funcTag, 54}, + {"convTslice", funcTag, 54}, + {"convT2E", funcTag, 55}, + {"convT2Enoptr", funcTag, 55}, + {"convT2I", funcTag, 55}, + {"convT2Inoptr", funcTag, 55}, {"assertE2I", funcTag, 52}, - {"assertE2I2", funcTag, 54}, + {"assertE2I2", funcTag, 56}, {"assertI2I", funcTag, 52}, - {"assertI2I2", funcTag, 54}, - {"panicdottypeE", funcTag, 55}, - {"panicdottypeI", funcTag, 55}, - {"panicnildottype", funcTag, 56}, - {"ifaceeq", funcTag, 59}, - {"efaceeq", funcTag, 59}, - {"fastrand", funcTag, 61}, - {"makemap64", funcTag, 63}, - {"makemap", funcTag, 64}, - {"makemap_small", funcTag, 65}, - {"mapaccess1", funcTag, 66}, - {"mapaccess1_fast32", funcTag, 67}, - {"mapaccess1_fast64", funcTag, 67}, - {"mapaccess1_faststr", funcTag, 67}, - {"mapaccess1_fat", funcTag, 68}, - {"mapaccess2", funcTag, 69}, - {"mapaccess2_fast32", funcTag, 70}, - {"mapaccess2_fast64", funcTag, 70}, - {"mapaccess2_faststr", funcTag, 70}, - {"mapaccess2_fat", funcTag, 71}, - {"mapassign", funcTag, 66}, - {"mapassign_fast32", funcTag, 67}, - {"mapassign_fast32ptr", funcTag, 67}, - {"mapassign_fast64", funcTag, 67}, - {"mapassign_fast64ptr", funcTag, 67}, - {"mapassign_faststr", funcTag, 67}, - {"mapiterinit", funcTag, 72}, - {"mapdelete", funcTag, 72}, - {"mapdelete_fast32", funcTag, 73}, - {"mapdelete_fast64", funcTag, 73}, - {"mapdelete_faststr", funcTag, 73}, - {"mapiternext", funcTag, 74}, - {"mapclear", funcTag, 75}, - {"makechan64", funcTag, 77}, - {"makechan", funcTag, 78}, - {"chanrecv1", funcTag, 80}, - {"chanrecv2", funcTag, 81}, - {"chansend1", funcTag, 83}, + {"assertI2I2", funcTag, 56}, + {"panicdottypeE", funcTag, 57}, + {"panicdottypeI", funcTag, 57}, + {"panicnildottype", funcTag, 58}, + {"ifaceeq", funcTag, 60}, + {"efaceeq", funcTag, 60}, + {"fastrand", funcTag, 62}, + {"makemap64", funcTag, 64}, + {"makemap", funcTag, 65}, + {"makemap_small", funcTag, 66}, + {"mapaccess1", funcTag, 67}, + {"mapaccess1_fast32", funcTag, 68}, + {"mapaccess1_fast64", funcTag, 68}, + {"mapaccess1_faststr", funcTag, 68}, + {"mapaccess1_fat", funcTag, 69}, + {"mapaccess2", funcTag, 70}, + {"mapaccess2_fast32", funcTag, 71}, + {"mapaccess2_fast64", funcTag, 71}, + {"mapaccess2_faststr", funcTag, 71}, + {"mapaccess2_fat", funcTag, 72}, + {"mapassign", funcTag, 67}, + {"mapassign_fast32", funcTag, 68}, + {"mapassign_fast32ptr", funcTag, 68}, + {"mapassign_fast64", funcTag, 68}, + {"mapassign_fast64ptr", funcTag, 68}, + {"mapassign_faststr", funcTag, 68}, + {"mapiterinit", funcTag, 73}, + {"mapdelete", funcTag, 73}, + {"mapdelete_fast32", funcTag, 74}, + {"mapdelete_fast64", funcTag, 74}, + {"mapdelete_faststr", funcTag, 74}, + {"mapiternext", funcTag, 75}, + {"mapclear", funcTag, 76}, + {"makechan64", funcTag, 78}, + {"makechan", funcTag, 79}, + {"chanrecv1", funcTag, 81}, + {"chanrecv2", funcTag, 82}, + {"chansend1", funcTag, 84}, {"closechan", funcTag, 23}, - {"writeBarrier", varTag, 85}, - {"typedmemmove", funcTag, 86}, - {"typedmemclr", funcTag, 87}, - {"typedslicecopy", funcTag, 88}, - {"selectnbsend", funcTag, 89}, - {"selectnbrecv", funcTag, 90}, - {"selectnbrecv2", funcTag, 92}, - {"selectsetpc", funcTag, 56}, - {"selectgo", funcTag, 93}, + {"writeBarrier", varTag, 86}, + {"typedmemmove", funcTag, 87}, + {"typedmemclr", funcTag, 88}, + {"typedslicecopy", funcTag, 89}, + {"selectnbsend", funcTag, 90}, + {"selectnbrecv", funcTag, 91}, + {"selectnbrecv2", funcTag, 93}, + {"selectsetpc", funcTag, 58}, + {"selectgo", funcTag, 94}, {"block", funcTag, 5}, - {"makeslice", funcTag, 94}, - {"makeslice64", funcTag, 95}, - {"growslice", funcTag, 97}, - {"memmove", funcTag, 98}, - {"memclrNoHeapPointers", funcTag, 99}, - {"memclrHasPointers", funcTag, 99}, - {"memequal", funcTag, 100}, - {"memequal8", funcTag, 101}, - {"memequal16", funcTag, 101}, - {"memequal32", funcTag, 101}, - {"memequal64", funcTag, 101}, - {"memequal128", funcTag, 101}, - {"int64div", funcTag, 102}, - {"uint64div", funcTag, 103}, - {"int64mod", funcTag, 102}, - {"uint64mod", funcTag, 103}, - {"float64toint64", funcTag, 104}, - {"float64touint64", funcTag, 105}, - {"float64touint32", funcTag, 106}, - {"int64tofloat64", funcTag, 107}, - {"uint64tofloat64", funcTag, 108}, - {"uint32tofloat64", funcTag, 109}, - {"complex128div", funcTag, 110}, - {"racefuncenter", funcTag, 111}, + {"makeslice", funcTag, 95}, + {"makeslice64", funcTag, 96}, + {"growslice", funcTag, 98}, + {"memmove", funcTag, 99}, + {"memclrNoHeapPointers", funcTag, 100}, + {"memclrHasPointers", funcTag, 100}, + {"memequal", funcTag, 101}, + {"memequal8", funcTag, 102}, + {"memequal16", funcTag, 102}, + {"memequal32", funcTag, 102}, + {"memequal64", funcTag, 102}, + {"memequal128", funcTag, 102}, + {"int64div", funcTag, 103}, + {"uint64div", funcTag, 104}, + {"int64mod", funcTag, 103}, + {"uint64mod", funcTag, 104}, + {"float64toint64", funcTag, 105}, + {"float64touint64", funcTag, 106}, + {"float64touint32", funcTag, 107}, + {"int64tofloat64", funcTag, 108}, + {"uint64tofloat64", funcTag, 109}, + {"uint32tofloat64", funcTag, 110}, + {"complex128div", funcTag, 111}, + {"racefuncenter", funcTag, 112}, {"racefuncenterfp", funcTag, 5}, {"racefuncexit", funcTag, 5}, - {"raceread", funcTag, 111}, - {"racewrite", funcTag, 111}, - {"racereadrange", funcTag, 112}, - {"racewriterange", funcTag, 112}, - {"msanread", funcTag, 112}, - {"msanwrite", funcTag, 112}, + {"raceread", funcTag, 112}, + {"racewrite", funcTag, 112}, + {"racereadrange", funcTag, 113}, + {"racewriterange", funcTag, 113}, + {"msanread", funcTag, 113}, + {"msanwrite", funcTag, 113}, {"support_popcnt", varTag, 11}, {"support_sse41", varTag, 11}, } func runtimeTypes() []*types.Type { - var typs [113]*types.Type + var typs [114]*types.Type typs[0] = types.Bytetype typs[1] = types.NewPtr(typs[0]) typs[2] = types.Types[TANY] @@ -208,65 +203,66 @@ func runtimeTypes() []*types.Type { typs[50] = functype(nil, []*Node{anonfield(typs[21]), anonfield(typs[32])}, []*Node{anonfield(typs[40]), anonfield(typs[32])}) typs[51] = functype(nil, []*Node{anonfield(typs[21])}, []*Node{anonfield(typs[32])}) typs[52] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2])}) - typs[53] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, []*Node{anonfield(typs[2])}) - typs[54] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2]), anonfield(typs[11])}) - typs[55] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil) - typs[56] = functype(nil, []*Node{anonfield(typs[1])}, nil) - typs[57] = types.NewPtr(typs[47]) - typs[58] = types.Types[TUNSAFEPTR] - typs[59] = functype(nil, []*Node{anonfield(typs[57]), anonfield(typs[58]), anonfield(typs[58])}, []*Node{anonfield(typs[11])}) - typs[60] = types.Types[TUINT32] - typs[61] = functype(nil, nil, []*Node{anonfield(typs[60])}) - typs[62] = types.NewMap(typs[2], typs[2]) - typs[63] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*Node{anonfield(typs[62])}) - typs[64] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[3])}, []*Node{anonfield(typs[62])}) - typs[65] = functype(nil, nil, []*Node{anonfield(typs[62])}) - typs[66] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[3])}, []*Node{anonfield(typs[3])}) - typs[67] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[2])}, []*Node{anonfield(typs[3])}) - typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])}) - typs[69] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[11])}) - typs[70] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[11])}) - typs[71] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[11])}) - typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[3])}, nil) - typs[73] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62]), anonfield(typs[2])}, nil) - typs[74] = functype(nil, []*Node{anonfield(typs[3])}, nil) - typs[75] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[62])}, nil) - typs[76] = types.NewChan(typs[2], types.Cboth) - typs[77] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[76])}) - typs[78] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[76])}) - typs[79] = types.NewChan(typs[2], types.Crecv) - typs[80] = functype(nil, []*Node{anonfield(typs[79]), anonfield(typs[3])}, nil) - typs[81] = functype(nil, []*Node{anonfield(typs[79]), anonfield(typs[3])}, []*Node{anonfield(typs[11])}) - typs[82] = types.NewChan(typs[2], types.Csend) - typs[83] = functype(nil, []*Node{anonfield(typs[82]), anonfield(typs[3])}, nil) - typs[84] = types.NewArray(typs[0], 3) - typs[85] = tostruct([]*Node{namedfield("enabled", typs[11]), namedfield("pad", typs[84]), namedfield("needed", typs[11]), namedfield("cgo", typs[11]), namedfield("alignme", typs[17])}) - typs[86] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil) - typs[87] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil) - typs[88] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2]), anonfield(typs[2])}, []*Node{anonfield(typs[32])}) - typs[89] = functype(nil, []*Node{anonfield(typs[82]), anonfield(typs[3])}, []*Node{anonfield(typs[11])}) - typs[90] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[79])}, []*Node{anonfield(typs[11])}) - typs[91] = types.NewPtr(typs[11]) - typs[92] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[91]), anonfield(typs[79])}, []*Node{anonfield(typs[11])}) - typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[32]), anonfield(typs[11])}) - typs[94] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[58])}) - typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[58])}) - typs[96] = types.NewSlice(typs[2]) - typs[97] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[96]), anonfield(typs[32])}, []*Node{anonfield(typs[96])}) - typs[98] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, nil) - typs[99] = functype(nil, []*Node{anonfield(typs[58]), anonfield(typs[47])}, nil) - typs[100] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, []*Node{anonfield(typs[11])}) - typs[101] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[11])}) - typs[102] = functype(nil, []*Node{anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[15])}) - typs[103] = functype(nil, []*Node{anonfield(typs[17]), anonfield(typs[17])}, []*Node{anonfield(typs[17])}) - typs[104] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[15])}) - typs[105] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[17])}) - typs[106] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[60])}) - typs[107] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[13])}) - typs[108] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[13])}) - typs[109] = functype(nil, []*Node{anonfield(typs[60])}, []*Node{anonfield(typs[13])}) - typs[110] = functype(nil, []*Node{anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[19])}) - typs[111] = functype(nil, []*Node{anonfield(typs[47])}, nil) - typs[112] = functype(nil, []*Node{anonfield(typs[47]), anonfield(typs[47])}, nil) + typs[53] = types.Types[TUNSAFEPTR] + typs[54] = functype(nil, []*Node{anonfield(typs[2])}, []*Node{anonfield(typs[53])}) + typs[55] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, []*Node{anonfield(typs[2])}) + typs[56] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2]), anonfield(typs[11])}) + typs[57] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil) + typs[58] = functype(nil, []*Node{anonfield(typs[1])}, nil) + typs[59] = types.NewPtr(typs[47]) + typs[60] = functype(nil, []*Node{anonfield(typs[59]), anonfield(typs[53]), anonfield(typs[53])}, []*Node{anonfield(typs[11])}) + typs[61] = types.Types[TUINT32] + typs[62] = functype(nil, nil, []*Node{anonfield(typs[61])}) + typs[63] = types.NewMap(typs[2], typs[2]) + typs[64] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*Node{anonfield(typs[63])}) + typs[65] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[3])}, []*Node{anonfield(typs[63])}) + typs[66] = functype(nil, nil, []*Node{anonfield(typs[63])}) + typs[67] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[3])}, []*Node{anonfield(typs[3])}) + typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[2])}, []*Node{anonfield(typs[3])}) + typs[69] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])}) + typs[70] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[11])}) + typs[71] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[11])}) + typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[11])}) + typs[73] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[3])}, nil) + typs[74] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[2])}, nil) + typs[75] = functype(nil, []*Node{anonfield(typs[3])}, nil) + typs[76] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[63])}, nil) + typs[77] = types.NewChan(typs[2], types.Cboth) + typs[78] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[77])}) + typs[79] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[77])}) + typs[80] = types.NewChan(typs[2], types.Crecv) + typs[81] = functype(nil, []*Node{anonfield(typs[80]), anonfield(typs[3])}, nil) + typs[82] = functype(nil, []*Node{anonfield(typs[80]), anonfield(typs[3])}, []*Node{anonfield(typs[11])}) + typs[83] = types.NewChan(typs[2], types.Csend) + typs[84] = functype(nil, []*Node{anonfield(typs[83]), anonfield(typs[3])}, nil) + typs[85] = types.NewArray(typs[0], 3) + typs[86] = tostruct([]*Node{namedfield("enabled", typs[11]), namedfield("pad", typs[85]), namedfield("needed", typs[11]), namedfield("cgo", typs[11]), namedfield("alignme", typs[17])}) + typs[87] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil) + typs[88] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil) + typs[89] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2]), anonfield(typs[2])}, []*Node{anonfield(typs[32])}) + typs[90] = functype(nil, []*Node{anonfield(typs[83]), anonfield(typs[3])}, []*Node{anonfield(typs[11])}) + typs[91] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[80])}, []*Node{anonfield(typs[11])}) + typs[92] = types.NewPtr(typs[11]) + typs[93] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[92]), anonfield(typs[80])}, []*Node{anonfield(typs[11])}) + typs[94] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[32]), anonfield(typs[11])}) + typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[53])}) + typs[96] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[53])}) + typs[97] = types.NewSlice(typs[2]) + typs[98] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[97]), anonfield(typs[32])}, []*Node{anonfield(typs[97])}) + typs[99] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, nil) + typs[100] = functype(nil, []*Node{anonfield(typs[53]), anonfield(typs[47])}, nil) + typs[101] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, []*Node{anonfield(typs[11])}) + typs[102] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[11])}) + typs[103] = functype(nil, []*Node{anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[15])}) + typs[104] = functype(nil, []*Node{anonfield(typs[17]), anonfield(typs[17])}, []*Node{anonfield(typs[17])}) + typs[105] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[15])}) + typs[106] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[17])}) + typs[107] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[61])}) + typs[108] = functype(nil, []*Node{anonfield(typs[15])}, []*Node{anonfield(typs[13])}) + typs[109] = functype(nil, []*Node{anonfield(typs[17])}, []*Node{anonfield(typs[13])}) + typs[110] = functype(nil, []*Node{anonfield(typs[61])}, []*Node{anonfield(typs[13])}) + typs[111] = functype(nil, []*Node{anonfield(typs[19]), anonfield(typs[19])}, []*Node{anonfield(typs[19])}) + typs[112] = functype(nil, []*Node{anonfield(typs[47])}, nil) + typs[113] = functype(nil, []*Node{anonfield(typs[47]), anonfield(typs[47])}, nil) return typs[:] } diff --git a/src/cmd/compile/internal/gc/builtin/runtime.go b/src/cmd/compile/internal/gc/builtin/runtime.go index e6d174bc4b..1eaf332e50 100644 --- a/src/cmd/compile/internal/gc/builtin/runtime.go +++ b/src/cmd/compile/internal/gc/builtin/runtime.go @@ -61,23 +61,23 @@ func slicestringcopy(to any, fr any) int func decoderune(string, int) (retv rune, retk int) func countrunes(string) int -// interface conversions +// Non-empty-interface to non-empty-interface conversion. func convI2I(typ *byte, elem any) (ret any) +// Specialized type-to-interface conversion. +// These return only a data pointer. +func convT16(val any) unsafe.Pointer // val must be uint16-like (same size and alignment as a uint16) +func convT32(val any) unsafe.Pointer // val must be uint32-like (same size and alignment as a uint32) +func convT64(val any) unsafe.Pointer // val must be uint64-like (same size and alignment as a uint64 and contains no pointers) +func convTstring(val any) unsafe.Pointer // val must be a string +func convTslice(val any) unsafe.Pointer // val must be a slice + +// Type to empty-interface conversion. func convT2E(typ *byte, elem *any) (ret any) -func convT2E16(typ *byte, val any) (ret any) -func convT2E32(typ *byte, val any) (ret any) -func convT2E64(typ *byte, val any) (ret any) -func convT2Estring(typ *byte, val any) (ret any) // val must be a string -func convT2Eslice(typ *byte, val any) (ret any) // val must be a slice func convT2Enoptr(typ *byte, elem *any) (ret any) +// Type to non-empty-interface conversion. func convT2I(tab *byte, elem *any) (ret any) -func convT2I16(tab *byte, val any) (ret any) -func convT2I32(tab *byte, val any) (ret any) -func convT2I64(tab *byte, val any) (ret any) -func convT2Istring(tab *byte, val any) (ret any) // val must be a string -func convT2Islice(tab *byte, val any) (ret any) // val must be a slice func convT2Inoptr(tab *byte, elem *any) (ret any) // interface type assertions x.(T) diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 49a4e05d99..78142d3bf8 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -491,13 +491,17 @@ func Main(archInit func(*Arch)) { // Phase 1: const, type, and names and types of funcs. // This will gather all the information about types // and methods but doesn't depend on any of it. + // + // We also defer type alias declarations until phase 2 + // to avoid cycles like #18640. + // TODO(gri) Remove this again once we have a fix for #25838. defercheckwidth() // Don't use range--typecheck can add closures to xtop. timings.Start("fe", "typecheck", "top1") for i := 0; i < len(xtop); i++ { n := xtop[i] - if op := n.Op; op != ODCL && op != OAS && op != OAS2 { + if op := n.Op; op != ODCL && op != OAS && op != OAS2 && (op != ODCLTYPE || !n.Left.Name.Param.Alias) { xtop[i] = typecheck(n, Etop) } } @@ -509,7 +513,7 @@ func Main(archInit func(*Arch)) { timings.Start("fe", "typecheck", "top2") for i := 0; i < len(xtop); i++ { n := xtop[i] - if op := n.Op; op == ODCL || op == OAS || op == OAS2 { + if op := n.Op; op == ODCL || op == OAS || op == OAS2 || op == ODCLTYPE && n.Left.Name.Param.Alias { xtop[i] = typecheck(n, Etop) } } diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go index 415d3cd594..50b741358f 100644 --- a/src/cmd/compile/internal/gc/reflect.go +++ b/src/cmd/compile/internal/gc/reflect.go @@ -812,7 +812,7 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int { sptrWeak := true var sptr *obj.LSym - if !t.IsPtr() || t.PtrBase != nil { + if !t.IsPtr() || t.IsPtrElem() { tptr := types.NewPtr(t) if t.Sym != nil || methods(tptr) != nil { sptrWeak = false diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index be11a9841f..06dd176b37 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -255,8 +255,16 @@ func typecheck(n *Node, top int) (res *Node) { // since it would expand indefinitely when aliases // are substituted. cycle := cycleFor(n) - for _, n := range cycle { - if n.Name != nil && !n.Name.Param.Alias { + for _, n1 := range cycle { + if n1.Name != nil && !n1.Name.Param.Alias { + // Cycle is ok. But if n is an alias type and doesn't + // have a type yet, we have a recursive type declaration + // with aliases that we can't handle properly yet. + // Report an error rather than crashing later. + if n.Name != nil && n.Name.Param.Alias && n.Type == nil { + lineno = n.Pos + Fatalf("cannot handle alias type declaration (issue #25838): %v", n) + } lineno = lno return n } @@ -3671,8 +3679,7 @@ func copytype(n *Node, t *types.Type) { embedlineno := n.Type.ForwardType().Embedlineno l := n.Type.ForwardType().Copyto - ptrBase := n.Type.PtrBase - sliceOf := n.Type.SliceOf + cache := n.Type.Cache // TODO(mdempsky): Fix Type rekinding. *n.Type = *t @@ -3693,8 +3700,7 @@ func copytype(n *Node, t *types.Type) { t.Nod = asTypesNode(n) t.SetDeferwidth(false) - t.PtrBase = ptrBase - t.SliceOf = sliceOf + t.Cache = cache // Propagate go:notinheap pragma from the Name to the Type. if n.Name != nil && n.Name.Param != nil && n.Name.Param.Pragma&NotInHeap != 0 { diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 0e07efa0d9..fd484a6472 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -384,41 +384,31 @@ func convFuncName(from, to *types.Type) (fnname string, needsaddr bool) { tkind := to.Tie() switch from.Tie() { case 'I': - switch tkind { - case 'I': + if tkind == 'I' { return "convI2I", false } case 'T': + switch { + case from.Size() == 2 && from.Align == 2: + return "convT16", false + case from.Size() == 4 && from.Align == 4 && !types.Haspointers(from): + return "convT32", false + case from.Size() == 8 && from.Align == types.Types[TUINT64].Align && !types.Haspointers(from): + return "convT64", false + case from.IsString(): + return "convTstring", false + case from.IsSlice(): + return "convTslice", false + } + switch tkind { case 'E': - switch { - case from.Size() == 2 && from.Align == 2: - return "convT2E16", false - case from.Size() == 4 && from.Align == 4 && !types.Haspointers(from): - return "convT2E32", false - case from.Size() == 8 && from.Align == types.Types[TUINT64].Align && !types.Haspointers(from): - return "convT2E64", false - case from.IsString(): - return "convT2Estring", false - case from.IsSlice(): - return "convT2Eslice", false - case !types.Haspointers(from): + if !types.Haspointers(from) { return "convT2Enoptr", true } return "convT2E", true case 'I': - switch { - case from.Size() == 2 && from.Align == 2: - return "convT2I16", false - case from.Size() == 4 && from.Align == 4 && !types.Haspointers(from): - return "convT2I32", false - case from.Size() == 8 && from.Align == types.Types[TUINT64].Align && !types.Haspointers(from): - return "convT2I64", false - case from.IsString(): - return "convT2Istring", false - case from.IsSlice(): - return "convT2Islice", false - case !types.Haspointers(from): + if !types.Haspointers(from) { return "convT2Inoptr", true } return "convT2I", true @@ -925,6 +915,34 @@ opswitch: break } + fnname, needsaddr := convFuncName(n.Left.Type, n.Type) + + if !needsaddr && !n.Left.Type.IsInterface() { + // Use a specialized conversion routine that only returns a data pointer. + // ptr = convT2X(val) + // e = iface{typ/tab, ptr} + fn := syslook(fnname) + dowidth(n.Left.Type) + fn = substArgTypes(fn, n.Left.Type) + dowidth(fn.Type) + call := nod(OCALL, fn, nil) + call.List.Set1(n.Left) + call = typecheck(call, Erv) + call = walkexpr(call, init) + call = safeexpr(call, init) + var tab *Node + if n.Type.IsEmptyInterface() { + tab = typename(n.Left.Type) + } else { + tab = itabname(n.Left.Type, n.Type) + } + e := nod(OEFACE, tab, call) + e.Type = n.Type + e.SetTypecheck(1) + n = e + break + } + var ll []*Node if n.Type.IsEmptyInterface() { if !n.Left.Type.IsInterface() { @@ -938,7 +956,6 @@ opswitch: } } - fnname, needsaddr := convFuncName(n.Left.Type, n.Type) v := n.Left if needsaddr { // Types of large or unknown size are passed by reference. diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index ed5bce861e..17d7cb3414 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -542,7 +542,7 @@ func disjoint(p1 *Value, n1 int64, p2 *Value, n2 int64) bool { } baseAndOffset := func(ptr *Value) (base *Value, offset int64) { base, offset = ptr, 0 - if base.Op == OpOffPtr { + for base.Op == OpOffPtr { offset += base.AuxInt base = base.Args[0] } diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 39f4d2aa7b..45355e5798 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -149,8 +149,11 @@ type Type struct { Nod *Node // canonical OTYPE node Orig *Type // original type (type literal or predefined type) - SliceOf *Type - PtrBase *Type + // Cache of composite types, with this type being the element type. + Cache struct { + ptr *Type // *T, or nil + slice *Type // []T, or nil + } Sym *Sym // symbol containing name, for named types Vargen int32 // unique name for OTYPE/ONAME @@ -488,7 +491,7 @@ func NewArray(elem *Type, bound int64) *Type { // NewSlice returns the slice Type with element type elem. func NewSlice(elem *Type) *Type { - if t := elem.SliceOf; t != nil { + if t := elem.Cache.slice; t != nil { if t.Elem() != elem { Fatalf("elem mismatch") } @@ -497,7 +500,7 @@ func NewSlice(elem *Type) *Type { t := New(TSLICE) t.Extra = Slice{Elem: elem} - elem.SliceOf = t + elem.Cache.slice = t return t } @@ -551,7 +554,7 @@ func NewPtr(elem *Type) *Type { Fatalf("NewPtr: pointer to elem Type is nil") } - if t := elem.PtrBase; t != nil { + if t := elem.Cache.ptr; t != nil { if t.Elem() != elem { Fatalf("NewPtr: elem mismatch") } @@ -563,7 +566,7 @@ func NewPtr(elem *Type) *Type { t.Width = int64(Widthptr) t.Align = uint8(Widthptr) if NewPtrCacheEnabled { - elem.PtrBase = t + elem.Cache.ptr = t } return t } @@ -662,23 +665,18 @@ func SubstAny(t *Type, types *[]*Type) *Type { } case TSTRUCT: + // Make a copy of all fields, including ones whose type does not change. + // This prevents aliasing across functions, which can lead to later + // fields getting their Offset incorrectly overwritten. fields := t.FieldSlice() - var nfs []*Field + nfs := make([]*Field, len(fields)) for i, f := range fields { nft := SubstAny(f.Type, types) - if nft == f.Type { - continue - } - if nfs == nil { - nfs = append([]*Field(nil), fields...) - } nfs[i] = f.Copy() nfs[i].Type = nft } - if nfs != nil { - t = t.copy() - t.SetFields(nfs) - } + t = t.copy() + t.SetFields(nfs) } return t @@ -1258,6 +1256,11 @@ func (t *Type) IsPtr() bool { return t.Etype == TPTR } +// IsPtrElem reports whether t is the element of a pointer (to t). +func (t *Type) IsPtrElem() bool { + return t.Cache.ptr != nil +} + // IsUnsafePtr reports whether t is an unsafe pointer. func (t *Type) IsUnsafePtr() bool { return t.Etype == TUNSAFEPTR diff --git a/src/cmd/trace/main.go b/src/cmd/trace/main.go index a33d2f4679..2f71a3d4bd 100644 --- a/src/cmd/trace/main.go +++ b/src/cmd/trace/main.go @@ -189,7 +189,7 @@ var templMain = template.Must(template.New("").Parse(`
{{if $}} {{range $e := $}} - View trace ({{$e.Name}})