github.com/bir3/gocompiler@v0.3.205/src/cmd/compile/internal/reflectdata/reflect.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package reflectdata 6 7 import ( 8 "encoding/binary" 9 "fmt" 10 "os" 11 "sort" 12 "strings" 13 "sync" 14 15 "github.com/bir3/gocompiler/src/cmd/compile/internal/base" 16 "github.com/bir3/gocompiler/src/cmd/compile/internal/bitvec" 17 "github.com/bir3/gocompiler/src/cmd/compile/internal/compare" 18 "github.com/bir3/gocompiler/src/cmd/compile/internal/escape" 19 "github.com/bir3/gocompiler/src/cmd/compile/internal/inline" 20 "github.com/bir3/gocompiler/src/cmd/compile/internal/ir" 21 "github.com/bir3/gocompiler/src/cmd/compile/internal/objw" 22 "github.com/bir3/gocompiler/src/cmd/compile/internal/typebits" 23 "github.com/bir3/gocompiler/src/cmd/compile/internal/typecheck" 24 "github.com/bir3/gocompiler/src/cmd/compile/internal/types" 25 "github.com/bir3/gocompiler/src/cmd/internal/gcprog" 26 "github.com/bir3/gocompiler/src/cmd/internal/obj" 27 "github.com/bir3/gocompiler/src/cmd/internal/objabi" 28 "github.com/bir3/gocompiler/src/cmd/internal/src" 29 ) 30 31 type ptabEntry struct { 32 s *types.Sym 33 t *types.Type 34 } 35 36 func CountPTabs() int { 37 return len(ptabs) 38 } 39 40 // runtime interface and reflection data structures 41 var ( 42 // protects signatset and signatslice 43 signatmu sync.Mutex 44 // Tracking which types need runtime type descriptor 45 signatset = make(map[*types.Type]struct{}) 46 // Queue of types wait to be generated runtime type descriptor 47 signatslice []typeAndStr 48 49 gcsymmu sync.Mutex // protects gcsymset and gcsymslice 50 gcsymset = make(map[*types.Type]struct{}) 51 52 ptabs []*ir.Name 53 ) 54 55 type typeSig struct { 56 name *types.Sym 57 isym *obj.LSym 58 tsym *obj.LSym 59 type_ *types.Type 60 mtype *types.Type 61 } 62 63 // Builds a type representing a Bucket structure for 64 // the given map type. This type is not visible to users - 65 // we include only enough information to generate a correct GC 66 // program for it. 67 // Make sure this stays in sync with runtime/map.go. 68 const ( 69 BUCKETSIZE = 8 70 MAXKEYSIZE = 128 71 MAXELEMSIZE = 128 72 ) 73 74 func structfieldSize() int { return 3 * types.PtrSize } // Sizeof(runtime.structfield{}) 75 func imethodSize() int { return 4 + 4 } // Sizeof(runtime.imethod{}) 76 func commonSize() int { return 4*types.PtrSize + 8 + 8 } // Sizeof(runtime._type{}) 77 78 func uncommonSize(t *types.Type) int { // Sizeof(runtime.uncommontype{}) 79 if t.Sym() == nil && len(methods(t)) == 0 { 80 return 0 81 } 82 return 4 + 2 + 2 + 4 + 4 83 } 84 85 func makefield(name string, t *types.Type) *types.Field { 86 sym := (*types.Pkg)(nil).Lookup(name) 87 return types.NewField(src.NoXPos, sym, t) 88 } 89 90 // MapBucketType makes the map bucket type given the type of the map. 91 func MapBucketType(t *types.Type) *types.Type { 92 if t.MapType().Bucket != nil { 93 return t.MapType().Bucket 94 } 95 96 keytype := t.Key() 97 elemtype := t.Elem() 98 types.CalcSize(keytype) 99 types.CalcSize(elemtype) 100 if keytype.Size() > MAXKEYSIZE { 101 keytype = types.NewPtr(keytype) 102 } 103 if elemtype.Size() > MAXELEMSIZE { 104 elemtype = types.NewPtr(elemtype) 105 } 106 107 field := make([]*types.Field, 0, 5) 108 109 // The first field is: uint8 topbits[BUCKETSIZE]. 110 arr := types.NewArray(types.Types[types.TUINT8], BUCKETSIZE) 111 field = append(field, makefield("topbits", arr)) 112 113 arr = types.NewArray(keytype, BUCKETSIZE) 114 arr.SetNoalg(true) 115 keys := makefield("keys", arr) 116 field = append(field, keys) 117 118 arr = types.NewArray(elemtype, BUCKETSIZE) 119 arr.SetNoalg(true) 120 elems := makefield("elems", arr) 121 field = append(field, elems) 122 123 // If keys and elems have no pointers, the map implementation 124 // can keep a list of overflow pointers on the side so that 125 // buckets can be marked as having no pointers. 126 // Arrange for the bucket to have no pointers by changing 127 // the type of the overflow field to uintptr in this case. 128 // See comment on hmap.overflow in runtime/map.go. 129 otyp := types.Types[types.TUNSAFEPTR] 130 if !elemtype.HasPointers() && !keytype.HasPointers() { 131 otyp = types.Types[types.TUINTPTR] 132 } 133 overflow := makefield("overflow", otyp) 134 field = append(field, overflow) 135 136 // link up fields 137 bucket := types.NewStruct(types.NoPkg, field[:]) 138 bucket.SetNoalg(true) 139 types.CalcSize(bucket) 140 141 // Check invariants that map code depends on. 142 if !types.IsComparable(t.Key()) { 143 base.Fatalf("unsupported map key type for %v", t) 144 } 145 if BUCKETSIZE < 8 { 146 base.Fatalf("bucket size too small for proper alignment") 147 } 148 if uint8(keytype.Alignment()) > BUCKETSIZE { 149 base.Fatalf("key align too big for %v", t) 150 } 151 if uint8(elemtype.Alignment()) > BUCKETSIZE { 152 base.Fatalf("elem align too big for %v", t) 153 } 154 if keytype.Size() > MAXKEYSIZE { 155 base.Fatalf("key size to large for %v", t) 156 } 157 if elemtype.Size() > MAXELEMSIZE { 158 base.Fatalf("elem size to large for %v", t) 159 } 160 if t.Key().Size() > MAXKEYSIZE && !keytype.IsPtr() { 161 base.Fatalf("key indirect incorrect for %v", t) 162 } 163 if t.Elem().Size() > MAXELEMSIZE && !elemtype.IsPtr() { 164 base.Fatalf("elem indirect incorrect for %v", t) 165 } 166 if keytype.Size()%keytype.Alignment() != 0 { 167 base.Fatalf("key size not a multiple of key align for %v", t) 168 } 169 if elemtype.Size()%elemtype.Alignment() != 0 { 170 base.Fatalf("elem size not a multiple of elem align for %v", t) 171 } 172 if uint8(bucket.Alignment())%uint8(keytype.Alignment()) != 0 { 173 base.Fatalf("bucket align not multiple of key align %v", t) 174 } 175 if uint8(bucket.Alignment())%uint8(elemtype.Alignment()) != 0 { 176 base.Fatalf("bucket align not multiple of elem align %v", t) 177 } 178 if keys.Offset%keytype.Alignment() != 0 { 179 base.Fatalf("bad alignment of keys in bmap for %v", t) 180 } 181 if elems.Offset%elemtype.Alignment() != 0 { 182 base.Fatalf("bad alignment of elems in bmap for %v", t) 183 } 184 185 // Double-check that overflow field is final memory in struct, 186 // with no padding at end. 187 if overflow.Offset != bucket.Size()-int64(types.PtrSize) { 188 base.Fatalf("bad offset of overflow in bmap for %v", t) 189 } 190 191 t.MapType().Bucket = bucket 192 193 bucket.StructType().Map = t 194 return bucket 195 } 196 197 // MapType builds a type representing a Hmap structure for the given map type. 198 // Make sure this stays in sync with runtime/map.go. 199 func MapType(t *types.Type) *types.Type { 200 if t.MapType().Hmap != nil { 201 return t.MapType().Hmap 202 } 203 204 bmap := MapBucketType(t) 205 206 // build a struct: 207 // type hmap struct { 208 // count int 209 // flags uint8 210 // B uint8 211 // noverflow uint16 212 // hash0 uint32 213 // buckets *bmap 214 // oldbuckets *bmap 215 // nevacuate uintptr 216 // extra unsafe.Pointer // *mapextra 217 // } 218 // must match runtime/map.go:hmap. 219 fields := []*types.Field{ 220 makefield("count", types.Types[types.TINT]), 221 makefield("flags", types.Types[types.TUINT8]), 222 makefield("B", types.Types[types.TUINT8]), 223 makefield("noverflow", types.Types[types.TUINT16]), 224 makefield("hash0", types.Types[types.TUINT32]), // Used in walk.go for OMAKEMAP. 225 makefield("buckets", types.NewPtr(bmap)), // Used in walk.go for OMAKEMAP. 226 makefield("oldbuckets", types.NewPtr(bmap)), 227 makefield("nevacuate", types.Types[types.TUINTPTR]), 228 makefield("extra", types.Types[types.TUNSAFEPTR]), 229 } 230 231 hmap := types.NewStruct(types.NoPkg, fields) 232 hmap.SetNoalg(true) 233 types.CalcSize(hmap) 234 235 // The size of hmap should be 48 bytes on 64 bit 236 // and 28 bytes on 32 bit platforms. 237 if size := int64(8 + 5*types.PtrSize); hmap.Size() != size { 238 base.Fatalf("hmap size not correct: got %d, want %d", hmap.Size(), size) 239 } 240 241 t.MapType().Hmap = hmap 242 hmap.StructType().Map = t 243 return hmap 244 } 245 246 // MapIterType builds a type representing an Hiter structure for the given map type. 247 // Make sure this stays in sync with runtime/map.go. 248 func MapIterType(t *types.Type) *types.Type { 249 if t.MapType().Hiter != nil { 250 return t.MapType().Hiter 251 } 252 253 hmap := MapType(t) 254 bmap := MapBucketType(t) 255 256 // build a struct: 257 // type hiter struct { 258 // key *Key 259 // elem *Elem 260 // t unsafe.Pointer // *MapType 261 // h *hmap 262 // buckets *bmap 263 // bptr *bmap 264 // overflow unsafe.Pointer // *[]*bmap 265 // oldoverflow unsafe.Pointer // *[]*bmap 266 // startBucket uintptr 267 // offset uint8 268 // wrapped bool 269 // B uint8 270 // i uint8 271 // bucket uintptr 272 // checkBucket uintptr 273 // } 274 // must match runtime/map.go:hiter. 275 fields := []*types.Field{ 276 makefield("key", types.NewPtr(t.Key())), // Used in range.go for TMAP. 277 makefield("elem", types.NewPtr(t.Elem())), // Used in range.go for TMAP. 278 makefield("t", types.Types[types.TUNSAFEPTR]), 279 makefield("h", types.NewPtr(hmap)), 280 makefield("buckets", types.NewPtr(bmap)), 281 makefield("bptr", types.NewPtr(bmap)), 282 makefield("overflow", types.Types[types.TUNSAFEPTR]), 283 makefield("oldoverflow", types.Types[types.TUNSAFEPTR]), 284 makefield("startBucket", types.Types[types.TUINTPTR]), 285 makefield("offset", types.Types[types.TUINT8]), 286 makefield("wrapped", types.Types[types.TBOOL]), 287 makefield("B", types.Types[types.TUINT8]), 288 makefield("i", types.Types[types.TUINT8]), 289 makefield("bucket", types.Types[types.TUINTPTR]), 290 makefield("checkBucket", types.Types[types.TUINTPTR]), 291 } 292 293 // build iterator struct holding the above fields 294 hiter := types.NewStruct(types.NoPkg, fields) 295 hiter.SetNoalg(true) 296 types.CalcSize(hiter) 297 if hiter.Size() != int64(12*types.PtrSize) { 298 base.Fatalf("hash_iter size not correct %d %d", hiter.Size(), 12*types.PtrSize) 299 } 300 t.MapType().Hiter = hiter 301 hiter.StructType().Map = t 302 return hiter 303 } 304 305 // methods returns the methods of the non-interface type t, sorted by name. 306 // Generates stub functions as needed. 307 func methods(t *types.Type) []*typeSig { 308 if t.HasShape() { 309 // Shape types have no methods. 310 return nil 311 } 312 // method type 313 mt := types.ReceiverBaseType(t) 314 315 if mt == nil { 316 return nil 317 } 318 typecheck.CalcMethods(mt) 319 320 // make list of methods for t, 321 // generating code if necessary. 322 var ms []*typeSig 323 for _, f := range mt.AllMethods().Slice() { 324 if f.Sym == nil { 325 base.Fatalf("method with no sym on %v", mt) 326 } 327 if !f.IsMethod() { 328 base.Fatalf("non-method on %v method %v %v", mt, f.Sym, f) 329 } 330 if f.Type.Recv() == nil { 331 base.Fatalf("receiver with no type on %v method %v %v", mt, f.Sym, f) 332 } 333 if f.Nointerface() && !t.IsFullyInstantiated() { 334 // Skip creating method wrappers if f is nointerface. But, if 335 // t is an instantiated type, we still have to call 336 // methodWrapper, because methodWrapper generates the actual 337 // generic method on the type as well. 338 continue 339 } 340 341 // get receiver type for this particular method. 342 // if pointer receiver but non-pointer t and 343 // this is not an embedded pointer inside a struct, 344 // method does not apply. 345 if !types.IsMethodApplicable(t, f) { 346 continue 347 } 348 349 sig := &typeSig{ 350 name: f.Sym, 351 isym: methodWrapper(t, f, true), 352 tsym: methodWrapper(t, f, false), 353 type_: typecheck.NewMethodType(f.Type, t), 354 mtype: typecheck.NewMethodType(f.Type, nil), 355 } 356 if f.Nointerface() { 357 // In the case of a nointerface method on an instantiated 358 // type, don't actually append the typeSig. 359 continue 360 } 361 ms = append(ms, sig) 362 } 363 364 return ms 365 } 366 367 // imethods returns the methods of the interface type t, sorted by name. 368 func imethods(t *types.Type) []*typeSig { 369 var methods []*typeSig 370 for _, f := range t.AllMethods().Slice() { 371 if f.Type.Kind() != types.TFUNC || f.Sym == nil { 372 continue 373 } 374 if f.Sym.IsBlank() { 375 base.Fatalf("unexpected blank symbol in interface method set") 376 } 377 if n := len(methods); n > 0 { 378 last := methods[n-1] 379 if !last.name.Less(f.Sym) { 380 base.Fatalf("sigcmp vs sortinter %v %v", last.name, f.Sym) 381 } 382 } 383 384 sig := &typeSig{ 385 name: f.Sym, 386 mtype: f.Type, 387 type_: typecheck.NewMethodType(f.Type, nil), 388 } 389 methods = append(methods, sig) 390 391 // NOTE(rsc): Perhaps an oversight that 392 // IfaceType.Method is not in the reflect data. 393 // Generate the method body, so that compiled 394 // code can refer to it. 395 methodWrapper(t, f, false) 396 } 397 398 return methods 399 } 400 401 func dimportpath(p *types.Pkg) { 402 if p.Pathsym != nil { 403 return 404 } 405 406 // If we are compiling the runtime package, there are two runtime packages around 407 // -- localpkg and Pkgs.Runtime. We don't want to produce import path symbols for 408 // both of them, so just produce one for localpkg. 409 if base.Ctxt.Pkgpath == "runtime" && p == ir.Pkgs.Runtime { 410 return 411 } 412 413 s := base.Ctxt.Lookup("type:.importpath." + p.Prefix + ".") 414 ot := dnameData(s, 0, p.Path, "", nil, false, false) 415 objw.Global(s, int32(ot), obj.DUPOK|obj.RODATA) 416 s.Set(obj.AttrContentAddressable, true) 417 p.Pathsym = s 418 } 419 420 func dgopkgpath(s *obj.LSym, ot int, pkg *types.Pkg) int { 421 if pkg == nil { 422 return objw.Uintptr(s, ot, 0) 423 } 424 425 if pkg == types.LocalPkg && base.Ctxt.Pkgpath == "" { 426 // If we don't know the full import path of the package being compiled 427 // (i.e. -p was not passed on the compiler command line), emit a reference to 428 // type:.importpath.""., which the linker will rewrite using the correct import path. 429 // Every package that imports this one directly defines the symbol. 430 // See also https://groups.google.com/forum/#!topic/golang-dev/myb9s53HxGQ. 431 ns := base.Ctxt.Lookup(`type:.importpath."".`) 432 return objw.SymPtr(s, ot, ns, 0) 433 } 434 435 dimportpath(pkg) 436 return objw.SymPtr(s, ot, pkg.Pathsym, 0) 437 } 438 439 // dgopkgpathOff writes an offset relocation in s at offset ot to the pkg path symbol. 440 func dgopkgpathOff(s *obj.LSym, ot int, pkg *types.Pkg) int { 441 if pkg == nil { 442 return objw.Uint32(s, ot, 0) 443 } 444 if pkg == types.LocalPkg && base.Ctxt.Pkgpath == "" { 445 // If we don't know the full import path of the package being compiled 446 // (i.e. -p was not passed on the compiler command line), emit a reference to 447 // type:.importpath.""., which the linker will rewrite using the correct import path. 448 // Every package that imports this one directly defines the symbol. 449 // See also https://groups.google.com/forum/#!topic/golang-dev/myb9s53HxGQ. 450 ns := base.Ctxt.Lookup(`type:.importpath."".`) 451 return objw.SymPtrOff(s, ot, ns) 452 } 453 454 dimportpath(pkg) 455 return objw.SymPtrOff(s, ot, pkg.Pathsym) 456 } 457 458 // dnameField dumps a reflect.name for a struct field. 459 func dnameField(lsym *obj.LSym, ot int, spkg *types.Pkg, ft *types.Field) int { 460 if !types.IsExported(ft.Sym.Name) && ft.Sym.Pkg != spkg { 461 base.Fatalf("package mismatch for %v", ft.Sym) 462 } 463 nsym := dname(ft.Sym.Name, ft.Note, nil, types.IsExported(ft.Sym.Name), ft.Embedded != 0) 464 return objw.SymPtr(lsym, ot, nsym, 0) 465 } 466 467 // dnameData writes the contents of a reflect.name into s at offset ot. 468 func dnameData(s *obj.LSym, ot int, name, tag string, pkg *types.Pkg, exported, embedded bool) int { 469 if len(name) >= 1<<29 { 470 base.Fatalf("name too long: %d %s...", len(name), name[:1024]) 471 } 472 if len(tag) >= 1<<29 { 473 base.Fatalf("tag too long: %d %s...", len(tag), tag[:1024]) 474 } 475 var nameLen [binary.MaxVarintLen64]byte 476 nameLenLen := binary.PutUvarint(nameLen[:], uint64(len(name))) 477 var tagLen [binary.MaxVarintLen64]byte 478 tagLenLen := binary.PutUvarint(tagLen[:], uint64(len(tag))) 479 480 // Encode name and tag. See reflect/type.go for details. 481 var bits byte 482 l := 1 + nameLenLen + len(name) 483 if exported { 484 bits |= 1 << 0 485 } 486 if len(tag) > 0 { 487 l += tagLenLen + len(tag) 488 bits |= 1 << 1 489 } 490 if pkg != nil { 491 bits |= 1 << 2 492 } 493 if embedded { 494 bits |= 1 << 3 495 } 496 b := make([]byte, l) 497 b[0] = bits 498 copy(b[1:], nameLen[:nameLenLen]) 499 copy(b[1+nameLenLen:], name) 500 if len(tag) > 0 { 501 tb := b[1+nameLenLen+len(name):] 502 copy(tb, tagLen[:tagLenLen]) 503 copy(tb[tagLenLen:], tag) 504 } 505 506 ot = int(s.WriteBytes(base.Ctxt, int64(ot), b)) 507 508 if pkg != nil { 509 ot = dgopkgpathOff(s, ot, pkg) 510 } 511 512 return ot 513 } 514 515 var dnameCount int 516 517 // dname creates a reflect.name for a struct field or method. 518 func dname(name, tag string, pkg *types.Pkg, exported, embedded bool) *obj.LSym { 519 // Write out data as "type:." to signal two things to the 520 // linker, first that when dynamically linking, the symbol 521 // should be moved to a relro section, and second that the 522 // contents should not be decoded as a type. 523 sname := "type:.namedata." 524 if pkg == nil { 525 // In the common case, share data with other packages. 526 if name == "" { 527 if exported { 528 sname += "-noname-exported." + tag 529 } else { 530 sname += "-noname-unexported." + tag 531 } 532 } else { 533 if exported { 534 sname += name + "." + tag 535 } else { 536 sname += name + "-" + tag 537 } 538 } 539 } else { 540 sname = fmt.Sprintf(`%s"".%d`, sname, dnameCount) 541 dnameCount++ 542 } 543 if embedded { 544 sname += ".embedded" 545 } 546 s := base.Ctxt.Lookup(sname) 547 if len(s.P) > 0 { 548 return s 549 } 550 ot := dnameData(s, 0, name, tag, pkg, exported, embedded) 551 objw.Global(s, int32(ot), obj.DUPOK|obj.RODATA) 552 s.Set(obj.AttrContentAddressable, true) 553 return s 554 } 555 556 // dextratype dumps the fields of a runtime.uncommontype. 557 // dataAdd is the offset in bytes after the header where the 558 // backing array of the []method field is written (by dextratypeData). 559 func dextratype(lsym *obj.LSym, ot int, t *types.Type, dataAdd int) int { 560 m := methods(t) 561 if t.Sym() == nil && len(m) == 0 { 562 return ot 563 } 564 noff := int(types.RoundUp(int64(ot), int64(types.PtrSize))) 565 if noff != ot { 566 base.Fatalf("unexpected alignment in dextratype for %v", t) 567 } 568 569 for _, a := range m { 570 writeType(a.type_) 571 } 572 573 ot = dgopkgpathOff(lsym, ot, typePkg(t)) 574 575 dataAdd += uncommonSize(t) 576 mcount := len(m) 577 if mcount != int(uint16(mcount)) { 578 base.Fatalf("too many methods on %v: %d", t, mcount) 579 } 580 xcount := sort.Search(mcount, func(i int) bool { return !types.IsExported(m[i].name.Name) }) 581 if dataAdd != int(uint32(dataAdd)) { 582 base.Fatalf("methods are too far away on %v: %d", t, dataAdd) 583 } 584 585 ot = objw.Uint16(lsym, ot, uint16(mcount)) 586 ot = objw.Uint16(lsym, ot, uint16(xcount)) 587 ot = objw.Uint32(lsym, ot, uint32(dataAdd)) 588 ot = objw.Uint32(lsym, ot, 0) 589 return ot 590 } 591 592 func typePkg(t *types.Type) *types.Pkg { 593 tsym := t.Sym() 594 if tsym == nil { 595 switch t.Kind() { 596 case types.TARRAY, types.TSLICE, types.TPTR, types.TCHAN: 597 if t.Elem() != nil { 598 tsym = t.Elem().Sym() 599 } 600 } 601 } 602 if tsym != nil && tsym.Pkg != types.BuiltinPkg { 603 return tsym.Pkg 604 } 605 return nil 606 } 607 608 // dextratypeData dumps the backing array for the []method field of 609 // runtime.uncommontype. 610 func dextratypeData(lsym *obj.LSym, ot int, t *types.Type) int { 611 for _, a := range methods(t) { 612 // ../../../../runtime/type.go:/method 613 exported := types.IsExported(a.name.Name) 614 var pkg *types.Pkg 615 if !exported && a.name.Pkg != typePkg(t) { 616 pkg = a.name.Pkg 617 } 618 nsym := dname(a.name.Name, "", pkg, exported, false) 619 620 ot = objw.SymPtrOff(lsym, ot, nsym) 621 ot = dmethodptrOff(lsym, ot, writeType(a.mtype)) 622 ot = dmethodptrOff(lsym, ot, a.isym) 623 ot = dmethodptrOff(lsym, ot, a.tsym) 624 } 625 return ot 626 } 627 628 func dmethodptrOff(s *obj.LSym, ot int, x *obj.LSym) int { 629 objw.Uint32(s, ot, 0) 630 r := obj.Addrel(s) 631 r.Off = int32(ot) 632 r.Siz = 4 633 r.Sym = x 634 r.Type = objabi.R_METHODOFF 635 return ot + 4 636 } 637 638 var kinds = []int{ 639 types.TINT: objabi.KindInt, 640 types.TUINT: objabi.KindUint, 641 types.TINT8: objabi.KindInt8, 642 types.TUINT8: objabi.KindUint8, 643 types.TINT16: objabi.KindInt16, 644 types.TUINT16: objabi.KindUint16, 645 types.TINT32: objabi.KindInt32, 646 types.TUINT32: objabi.KindUint32, 647 types.TINT64: objabi.KindInt64, 648 types.TUINT64: objabi.KindUint64, 649 types.TUINTPTR: objabi.KindUintptr, 650 types.TFLOAT32: objabi.KindFloat32, 651 types.TFLOAT64: objabi.KindFloat64, 652 types.TBOOL: objabi.KindBool, 653 types.TSTRING: objabi.KindString, 654 types.TPTR: objabi.KindPtr, 655 types.TSTRUCT: objabi.KindStruct, 656 types.TINTER: objabi.KindInterface, 657 types.TCHAN: objabi.KindChan, 658 types.TMAP: objabi.KindMap, 659 types.TARRAY: objabi.KindArray, 660 types.TSLICE: objabi.KindSlice, 661 types.TFUNC: objabi.KindFunc, 662 types.TCOMPLEX64: objabi.KindComplex64, 663 types.TCOMPLEX128: objabi.KindComplex128, 664 types.TUNSAFEPTR: objabi.KindUnsafePointer, 665 } 666 667 // tflag is documented in reflect/type.go. 668 // 669 // tflag values must be kept in sync with copies in: 670 // - cmd/compile/internal/reflectdata/reflect.go 671 // - cmd/link/internal/ld/decodesym.go 672 // - reflect/type.go 673 // - runtime/type.go 674 const ( 675 tflagUncommon = 1 << 0 676 tflagExtraStar = 1 << 1 677 tflagNamed = 1 << 2 678 tflagRegularMemory = 1 << 3 679 ) 680 681 var ( 682 memhashvarlen *obj.LSym 683 memequalvarlen *obj.LSym 684 ) 685 686 // dcommontype dumps the contents of a reflect.rtype (runtime._type). 687 func dcommontype(lsym *obj.LSym, t *types.Type) int { 688 types.CalcSize(t) 689 eqfunc := geneq(t) 690 691 sptrWeak := true 692 var sptr *obj.LSym 693 if !t.IsPtr() || t.IsPtrElem() { 694 tptr := types.NewPtr(t) 695 if t.Sym() != nil || methods(tptr) != nil { 696 sptrWeak = false 697 } 698 sptr = writeType(tptr) 699 } 700 701 gcsym, useGCProg, ptrdata := dgcsym(t, true) 702 delete(gcsymset, t) 703 704 // ../../../../reflect/type.go:/^type.rtype 705 // actual type structure 706 // type rtype struct { 707 // size uintptr 708 // ptrdata uintptr 709 // hash uint32 710 // tflag tflag 711 // align uint8 712 // fieldAlign uint8 713 // kind uint8 714 // equal func(unsafe.Pointer, unsafe.Pointer) bool 715 // gcdata *byte 716 // str nameOff 717 // ptrToThis typeOff 718 // } 719 ot := 0 720 ot = objw.Uintptr(lsym, ot, uint64(t.Size())) 721 ot = objw.Uintptr(lsym, ot, uint64(ptrdata)) 722 ot = objw.Uint32(lsym, ot, types.TypeHash(t)) 723 724 var tflag uint8 725 if uncommonSize(t) != 0 { 726 tflag |= tflagUncommon 727 } 728 if t.Sym() != nil && t.Sym().Name != "" { 729 tflag |= tflagNamed 730 } 731 if compare.IsRegularMemory(t) { 732 tflag |= tflagRegularMemory 733 } 734 735 exported := false 736 p := t.NameString() 737 // If we're writing out type T, 738 // we are very likely to write out type *T as well. 739 // Use the string "*T"[1:] for "T", so that the two 740 // share storage. This is a cheap way to reduce the 741 // amount of space taken up by reflect strings. 742 if !strings.HasPrefix(p, "*") { 743 p = "*" + p 744 tflag |= tflagExtraStar 745 if t.Sym() != nil { 746 exported = types.IsExported(t.Sym().Name) 747 } 748 } else { 749 if t.Elem() != nil && t.Elem().Sym() != nil { 750 exported = types.IsExported(t.Elem().Sym().Name) 751 } 752 } 753 754 ot = objw.Uint8(lsym, ot, tflag) 755 756 // runtime (and common sense) expects alignment to be a power of two. 757 i := int(uint8(t.Alignment())) 758 759 if i == 0 { 760 i = 1 761 } 762 if i&(i-1) != 0 { 763 base.Fatalf("invalid alignment %d for %v", uint8(t.Alignment()), t) 764 } 765 ot = objw.Uint8(lsym, ot, uint8(t.Alignment())) // align 766 ot = objw.Uint8(lsym, ot, uint8(t.Alignment())) // fieldAlign 767 768 i = kinds[t.Kind()] 769 if types.IsDirectIface(t) { 770 i |= objabi.KindDirectIface 771 } 772 if useGCProg { 773 i |= objabi.KindGCProg 774 } 775 ot = objw.Uint8(lsym, ot, uint8(i)) // kind 776 if eqfunc != nil { 777 ot = objw.SymPtr(lsym, ot, eqfunc, 0) // equality function 778 } else { 779 ot = objw.Uintptr(lsym, ot, 0) // type we can't do == with 780 } 781 ot = objw.SymPtr(lsym, ot, gcsym, 0) // gcdata 782 783 nsym := dname(p, "", nil, exported, false) 784 ot = objw.SymPtrOff(lsym, ot, nsym) // str 785 // ptrToThis 786 if sptr == nil { 787 ot = objw.Uint32(lsym, ot, 0) 788 } else if sptrWeak { 789 ot = objw.SymPtrWeakOff(lsym, ot, sptr) 790 } else { 791 ot = objw.SymPtrOff(lsym, ot, sptr) 792 } 793 794 return ot 795 } 796 797 // TrackSym returns the symbol for tracking use of field/method f, assumed 798 // to be a member of struct/interface type t. 799 func TrackSym(t *types.Type, f *types.Field) *obj.LSym { 800 return base.PkgLinksym("go:track", t.LinkString()+"."+f.Sym.Name, obj.ABI0) 801 } 802 803 func TypeSymPrefix(prefix string, t *types.Type) *types.Sym { 804 p := prefix + "." + t.LinkString() 805 s := types.TypeSymLookup(p) 806 807 // This function is for looking up type-related generated functions 808 // (e.g. eq and hash). Make sure they are indeed generated. 809 signatmu.Lock() 810 NeedRuntimeType(t) 811 signatmu.Unlock() 812 813 //print("algsym: %s -> %+S\n", p, s); 814 815 return s 816 } 817 818 func TypeSym(t *types.Type) *types.Sym { 819 if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() { 820 base.Fatalf("TypeSym %v", t) 821 } 822 if t.Kind() == types.TFUNC && t.Recv() != nil { 823 base.Fatalf("misuse of method type: %v", t) 824 } 825 s := types.TypeSym(t) 826 signatmu.Lock() 827 NeedRuntimeType(t) 828 signatmu.Unlock() 829 return s 830 } 831 832 func TypeLinksymPrefix(prefix string, t *types.Type) *obj.LSym { 833 return TypeSymPrefix(prefix, t).Linksym() 834 } 835 836 func TypeLinksymLookup(name string) *obj.LSym { 837 return types.TypeSymLookup(name).Linksym() 838 } 839 840 func TypeLinksym(t *types.Type) *obj.LSym { 841 return TypeSym(t).Linksym() 842 } 843 844 // Deprecated: Use TypePtrAt instead. 845 func TypePtr(t *types.Type) *ir.AddrExpr { 846 return TypePtrAt(base.Pos, t) 847 } 848 849 // TypePtrAt returns an expression that evaluates to the 850 // *runtime._type value for t. 851 func TypePtrAt(pos src.XPos, t *types.Type) *ir.AddrExpr { 852 return typecheck.LinksymAddr(pos, TypeLinksym(t), types.Types[types.TUINT8]) 853 } 854 855 // ITabLsym returns the LSym representing the itab for concrete type typ implementing 856 // interface iface. A dummy tab will be created in the unusual case where typ doesn't 857 // implement iface. Normally, this wouldn't happen, because the typechecker would 858 // have reported a compile-time error. This situation can only happen when the 859 // destination type of a type assert or a type in a type switch is parameterized, so 860 // it may sometimes, but not always, be a type that can't implement the specified 861 // interface. 862 func ITabLsym(typ, iface *types.Type) *obj.LSym { 863 s, existed := ir.Pkgs.Itab.LookupOK(typ.LinkString() + "," + iface.LinkString()) 864 lsym := s.Linksym() 865 866 if !existed { 867 writeITab(lsym, typ, iface, true) 868 } 869 return lsym 870 } 871 872 // Deprecated: Use ITabAddrAt instead. 873 func ITabAddr(typ, iface *types.Type) *ir.AddrExpr { 874 return ITabAddrAt(base.Pos, typ, iface) 875 } 876 877 // ITabAddrAt returns an expression that evaluates to the 878 // *runtime.itab value for concrete type typ implementing interface 879 // iface. 880 func ITabAddrAt(pos src.XPos, typ, iface *types.Type) *ir.AddrExpr { 881 s, existed := ir.Pkgs.Itab.LookupOK(typ.LinkString() + "," + iface.LinkString()) 882 lsym := s.Linksym() 883 884 if !existed { 885 writeITab(lsym, typ, iface, false) 886 } 887 888 return typecheck.LinksymAddr(pos, lsym, types.Types[types.TUINT8]) 889 } 890 891 // needkeyupdate reports whether map updates with t as a key 892 // need the key to be updated. 893 func needkeyupdate(t *types.Type) bool { 894 switch t.Kind() { 895 case types.TBOOL, types.TINT, types.TUINT, types.TINT8, types.TUINT8, types.TINT16, types.TUINT16, types.TINT32, types.TUINT32, 896 types.TINT64, types.TUINT64, types.TUINTPTR, types.TPTR, types.TUNSAFEPTR, types.TCHAN: 897 return false 898 899 case types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128, // floats and complex can be +0/-0 900 types.TINTER, 901 types.TSTRING: // strings might have smaller backing stores 902 return true 903 904 case types.TARRAY: 905 return needkeyupdate(t.Elem()) 906 907 case types.TSTRUCT: 908 for _, t1 := range t.Fields().Slice() { 909 if needkeyupdate(t1.Type) { 910 return true 911 } 912 } 913 return false 914 915 default: 916 base.Fatalf("bad type for map key: %v", t) 917 return true 918 } 919 } 920 921 // hashMightPanic reports whether the hash of a map key of type t might panic. 922 func hashMightPanic(t *types.Type) bool { 923 switch t.Kind() { 924 case types.TINTER: 925 return true 926 927 case types.TARRAY: 928 return hashMightPanic(t.Elem()) 929 930 case types.TSTRUCT: 931 for _, t1 := range t.Fields().Slice() { 932 if hashMightPanic(t1.Type) { 933 return true 934 } 935 } 936 return false 937 938 default: 939 return false 940 } 941 } 942 943 // formalType replaces predeclared aliases with real types. 944 // They've been separate internally to make error messages 945 // better, but we have to merge them in the reflect tables. 946 func formalType(t *types.Type) *types.Type { 947 switch t { 948 case types.AnyType, types.ByteType, types.RuneType: 949 return types.Types[t.Kind()] 950 } 951 return t 952 } 953 954 func writeType(t *types.Type) *obj.LSym { 955 t = formalType(t) 956 if t.IsUntyped() || t.HasTParam() { 957 base.Fatalf("writeType %v", t) 958 } 959 960 s := types.TypeSym(t) 961 lsym := s.Linksym() 962 if s.Siggen() { 963 return lsym 964 } 965 s.SetSiggen(true) 966 967 // special case (look for runtime below): 968 // when compiling package runtime, 969 // emit the type structures for int, float, etc. 970 tbase := t 971 972 if t.IsPtr() && t.Sym() == nil && t.Elem().Sym() != nil { 973 tbase = t.Elem() 974 } 975 if tbase.Kind() == types.TFORW { 976 base.Fatalf("unresolved defined type: %v", tbase) 977 } 978 979 if !NeedEmit(tbase) { 980 if i := typecheck.BaseTypeIndex(t); i >= 0 { 981 lsym.Pkg = tbase.Sym().Pkg.Prefix 982 lsym.SymIdx = int32(i) 983 lsym.Set(obj.AttrIndexed, true) 984 } 985 986 // TODO(mdempsky): Investigate whether this still happens. 987 // If we know we don't need to emit code for a type, 988 // we should have a link-symbol index for it. 989 // See also TODO in NeedEmit. 990 return lsym 991 } 992 993 ot := 0 994 switch t.Kind() { 995 default: 996 ot = dcommontype(lsym, t) 997 ot = dextratype(lsym, ot, t, 0) 998 999 case types.TARRAY: 1000 // ../../../../runtime/type.go:/arrayType 1001 s1 := writeType(t.Elem()) 1002 t2 := types.NewSlice(t.Elem()) 1003 s2 := writeType(t2) 1004 ot = dcommontype(lsym, t) 1005 ot = objw.SymPtr(lsym, ot, s1, 0) 1006 ot = objw.SymPtr(lsym, ot, s2, 0) 1007 ot = objw.Uintptr(lsym, ot, uint64(t.NumElem())) 1008 ot = dextratype(lsym, ot, t, 0) 1009 1010 case types.TSLICE: 1011 // ../../../../runtime/type.go:/sliceType 1012 s1 := writeType(t.Elem()) 1013 ot = dcommontype(lsym, t) 1014 ot = objw.SymPtr(lsym, ot, s1, 0) 1015 ot = dextratype(lsym, ot, t, 0) 1016 1017 case types.TCHAN: 1018 // ../../../../runtime/type.go:/chanType 1019 s1 := writeType(t.Elem()) 1020 ot = dcommontype(lsym, t) 1021 ot = objw.SymPtr(lsym, ot, s1, 0) 1022 ot = objw.Uintptr(lsym, ot, uint64(t.ChanDir())) 1023 ot = dextratype(lsym, ot, t, 0) 1024 1025 case types.TFUNC: 1026 for _, t1 := range t.Recvs().Fields().Slice() { 1027 writeType(t1.Type) 1028 } 1029 isddd := false 1030 for _, t1 := range t.Params().Fields().Slice() { 1031 isddd = t1.IsDDD() 1032 writeType(t1.Type) 1033 } 1034 for _, t1 := range t.Results().Fields().Slice() { 1035 writeType(t1.Type) 1036 } 1037 1038 ot = dcommontype(lsym, t) 1039 inCount := t.NumRecvs() + t.NumParams() 1040 outCount := t.NumResults() 1041 if isddd { 1042 outCount |= 1 << 15 1043 } 1044 ot = objw.Uint16(lsym, ot, uint16(inCount)) 1045 ot = objw.Uint16(lsym, ot, uint16(outCount)) 1046 if types.PtrSize == 8 { 1047 ot += 4 // align for *rtype 1048 } 1049 1050 dataAdd := (inCount + t.NumResults()) * types.PtrSize 1051 ot = dextratype(lsym, ot, t, dataAdd) 1052 1053 // Array of rtype pointers follows funcType. 1054 for _, t1 := range t.Recvs().Fields().Slice() { 1055 ot = objw.SymPtr(lsym, ot, writeType(t1.Type), 0) 1056 } 1057 for _, t1 := range t.Params().Fields().Slice() { 1058 ot = objw.SymPtr(lsym, ot, writeType(t1.Type), 0) 1059 } 1060 for _, t1 := range t.Results().Fields().Slice() { 1061 ot = objw.SymPtr(lsym, ot, writeType(t1.Type), 0) 1062 } 1063 1064 case types.TINTER: 1065 m := imethods(t) 1066 n := len(m) 1067 for _, a := range m { 1068 writeType(a.type_) 1069 } 1070 1071 // ../../../../runtime/type.go:/interfaceType 1072 ot = dcommontype(lsym, t) 1073 1074 var tpkg *types.Pkg 1075 if t.Sym() != nil && t != types.Types[t.Kind()] && t != types.ErrorType { 1076 tpkg = t.Sym().Pkg 1077 } 1078 ot = dgopkgpath(lsym, ot, tpkg) 1079 1080 ot = objw.SymPtr(lsym, ot, lsym, ot+3*types.PtrSize+uncommonSize(t)) 1081 ot = objw.Uintptr(lsym, ot, uint64(n)) 1082 ot = objw.Uintptr(lsym, ot, uint64(n)) 1083 dataAdd := imethodSize() * n 1084 ot = dextratype(lsym, ot, t, dataAdd) 1085 1086 for _, a := range m { 1087 // ../../../../runtime/type.go:/imethod 1088 exported := types.IsExported(a.name.Name) 1089 var pkg *types.Pkg 1090 if !exported && a.name.Pkg != tpkg { 1091 pkg = a.name.Pkg 1092 } 1093 nsym := dname(a.name.Name, "", pkg, exported, false) 1094 1095 ot = objw.SymPtrOff(lsym, ot, nsym) 1096 ot = objw.SymPtrOff(lsym, ot, writeType(a.type_)) 1097 } 1098 1099 // ../../../../runtime/type.go:/mapType 1100 case types.TMAP: 1101 s1 := writeType(t.Key()) 1102 s2 := writeType(t.Elem()) 1103 s3 := writeType(MapBucketType(t)) 1104 hasher := genhash(t.Key()) 1105 1106 ot = dcommontype(lsym, t) 1107 ot = objw.SymPtr(lsym, ot, s1, 0) 1108 ot = objw.SymPtr(lsym, ot, s2, 0) 1109 ot = objw.SymPtr(lsym, ot, s3, 0) 1110 ot = objw.SymPtr(lsym, ot, hasher, 0) 1111 var flags uint32 1112 // Note: flags must match maptype accessors in ../../../../runtime/type.go 1113 // and maptype builder in ../../../../reflect/type.go:MapOf. 1114 if t.Key().Size() > MAXKEYSIZE { 1115 ot = objw.Uint8(lsym, ot, uint8(types.PtrSize)) 1116 flags |= 1 // indirect key 1117 } else { 1118 ot = objw.Uint8(lsym, ot, uint8(t.Key().Size())) 1119 } 1120 1121 if t.Elem().Size() > MAXELEMSIZE { 1122 ot = objw.Uint8(lsym, ot, uint8(types.PtrSize)) 1123 flags |= 2 // indirect value 1124 } else { 1125 ot = objw.Uint8(lsym, ot, uint8(t.Elem().Size())) 1126 } 1127 ot = objw.Uint16(lsym, ot, uint16(MapBucketType(t).Size())) 1128 if types.IsReflexive(t.Key()) { 1129 flags |= 4 // reflexive key 1130 } 1131 if needkeyupdate(t.Key()) { 1132 flags |= 8 // need key update 1133 } 1134 if hashMightPanic(t.Key()) { 1135 flags |= 16 // hash might panic 1136 } 1137 ot = objw.Uint32(lsym, ot, flags) 1138 ot = dextratype(lsym, ot, t, 0) 1139 if u := t.Underlying(); u != t { 1140 // If t is a named map type, also keep the underlying map 1141 // type live in the binary. This is important to make sure that 1142 // a named map and that same map cast to its underlying type via 1143 // reflection, use the same hash function. See issue 37716. 1144 r := obj.Addrel(lsym) 1145 r.Sym = writeType(u) 1146 r.Type = objabi.R_KEEP 1147 } 1148 1149 case types.TPTR: 1150 if t.Elem().Kind() == types.TANY { 1151 // ../../../../runtime/type.go:/UnsafePointerType 1152 ot = dcommontype(lsym, t) 1153 ot = dextratype(lsym, ot, t, 0) 1154 1155 break 1156 } 1157 1158 // ../../../../runtime/type.go:/ptrType 1159 s1 := writeType(t.Elem()) 1160 1161 ot = dcommontype(lsym, t) 1162 ot = objw.SymPtr(lsym, ot, s1, 0) 1163 ot = dextratype(lsym, ot, t, 0) 1164 1165 // ../../../../runtime/type.go:/structType 1166 // for security, only the exported fields. 1167 case types.TSTRUCT: 1168 fields := t.Fields().Slice() 1169 for _, t1 := range fields { 1170 writeType(t1.Type) 1171 } 1172 1173 // All non-exported struct field names within a struct 1174 // type must originate from a single package. By 1175 // identifying and recording that package within the 1176 // struct type descriptor, we can omit that 1177 // information from the field descriptors. 1178 var spkg *types.Pkg 1179 for _, f := range fields { 1180 if !types.IsExported(f.Sym.Name) { 1181 spkg = f.Sym.Pkg 1182 break 1183 } 1184 } 1185 1186 ot = dcommontype(lsym, t) 1187 ot = dgopkgpath(lsym, ot, spkg) 1188 ot = objw.SymPtr(lsym, ot, lsym, ot+3*types.PtrSize+uncommonSize(t)) 1189 ot = objw.Uintptr(lsym, ot, uint64(len(fields))) 1190 ot = objw.Uintptr(lsym, ot, uint64(len(fields))) 1191 1192 dataAdd := len(fields) * structfieldSize() 1193 ot = dextratype(lsym, ot, t, dataAdd) 1194 1195 for _, f := range fields { 1196 // ../../../../runtime/type.go:/structField 1197 ot = dnameField(lsym, ot, spkg, f) 1198 ot = objw.SymPtr(lsym, ot, writeType(f.Type), 0) 1199 ot = objw.Uintptr(lsym, ot, uint64(f.Offset)) 1200 } 1201 } 1202 1203 // Note: DUPOK is required to ensure that we don't end up with more 1204 // than one type descriptor for a given type, if the type descriptor 1205 // can be defined in multiple packages, that is, unnamed types, 1206 // instantiated types and shape types. 1207 dupok := 0 1208 if tbase.Sym() == nil || tbase.IsFullyInstantiated() || tbase.HasShape() { 1209 dupok = obj.DUPOK 1210 } 1211 1212 ot = dextratypeData(lsym, ot, t) 1213 objw.Global(lsym, int32(ot), int16(dupok|obj.RODATA)) 1214 1215 // The linker will leave a table of all the typelinks for 1216 // types in the binary, so the runtime can find them. 1217 // 1218 // When buildmode=shared, all types are in typelinks so the 1219 // runtime can deduplicate type pointers. 1220 keep := base.Ctxt.Flag_dynlink 1221 if !keep && t.Sym() == nil { 1222 // For an unnamed type, we only need the link if the type can 1223 // be created at run time by reflect.PtrTo and similar 1224 // functions. If the type exists in the program, those 1225 // functions must return the existing type structure rather 1226 // than creating a new one. 1227 switch t.Kind() { 1228 case types.TPTR, types.TARRAY, types.TCHAN, types.TFUNC, types.TMAP, types.TSLICE, types.TSTRUCT: 1229 keep = true 1230 } 1231 } 1232 // Do not put Noalg types in typelinks. See issue #22605. 1233 if types.TypeHasNoAlg(t) { 1234 keep = false 1235 } 1236 lsym.Set(obj.AttrMakeTypelink, keep) 1237 1238 return lsym 1239 } 1240 1241 // InterfaceMethodOffset returns the offset of the i-th method in the interface 1242 // type descriptor, ityp. 1243 func InterfaceMethodOffset(ityp *types.Type, i int64) int64 { 1244 // interface type descriptor layout is struct { 1245 // _type // commonSize 1246 // pkgpath // 1 word 1247 // []imethod // 3 words (pointing to [...]imethod below) 1248 // uncommontype // uncommonSize 1249 // [...]imethod 1250 // } 1251 // The size of imethod is 8. 1252 return int64(commonSize()+4*types.PtrSize+uncommonSize(ityp)) + i*8 1253 } 1254 1255 // NeedRuntimeType ensures that a runtime type descriptor is emitted for t. 1256 func NeedRuntimeType(t *types.Type) { 1257 if t.HasTParam() { 1258 // Generic types don't really exist at run-time and have no runtime 1259 // type descriptor. But we do write out shape types. 1260 return 1261 } 1262 if _, ok := signatset[t]; !ok { 1263 signatset[t] = struct{}{} 1264 signatslice = append(signatslice, typeAndStr{t: t, short: types.TypeSymName(t), regular: t.String()}) 1265 } 1266 } 1267 1268 func WriteRuntimeTypes() { 1269 // Process signatslice. Use a loop, as writeType adds 1270 // entries to signatslice while it is being processed. 1271 for len(signatslice) > 0 { 1272 signats := signatslice 1273 // Sort for reproducible builds. 1274 sort.Sort(typesByString(signats)) 1275 for _, ts := range signats { 1276 t := ts.t 1277 writeType(t) 1278 if t.Sym() != nil { 1279 writeType(types.NewPtr(t)) 1280 } 1281 } 1282 signatslice = signatslice[len(signats):] 1283 } 1284 1285 // Emit GC data symbols. 1286 gcsyms := make([]typeAndStr, 0, len(gcsymset)) 1287 for t := range gcsymset { 1288 gcsyms = append(gcsyms, typeAndStr{t: t, short: types.TypeSymName(t), regular: t.String()}) 1289 } 1290 sort.Sort(typesByString(gcsyms)) 1291 for _, ts := range gcsyms { 1292 dgcsym(ts.t, true) 1293 } 1294 } 1295 1296 // writeITab writes the itab for concrete type typ implementing interface iface. If 1297 // allowNonImplement is true, allow the case where typ does not implement iface, and just 1298 // create a dummy itab with zeroed-out method entries. 1299 func writeITab(lsym *obj.LSym, typ, iface *types.Type, allowNonImplement bool) { 1300 // TODO(mdempsky): Fix methodWrapper, geneq, and genhash (and maybe 1301 // others) to stop clobbering these. 1302 oldpos, oldfn := base.Pos, ir.CurFunc 1303 defer func() { base.Pos, ir.CurFunc = oldpos, oldfn }() 1304 1305 if typ == nil || (typ.IsPtr() && typ.Elem() == nil) || typ.IsUntyped() || iface == nil || !iface.IsInterface() || iface.IsEmptyInterface() { 1306 base.Fatalf("writeITab(%v, %v)", typ, iface) 1307 } 1308 1309 sigs := iface.AllMethods().Slice() 1310 entries := make([]*obj.LSym, 0, len(sigs)) 1311 1312 // both sigs and methods are sorted by name, 1313 // so we can find the intersection in a single pass 1314 for _, m := range methods(typ) { 1315 if m.name == sigs[0].Sym { 1316 entries = append(entries, m.isym) 1317 if m.isym == nil { 1318 panic("NO ISYM") 1319 } 1320 sigs = sigs[1:] 1321 if len(sigs) == 0 { 1322 break 1323 } 1324 } 1325 } 1326 completeItab := len(sigs) == 0 1327 if !allowNonImplement && !completeItab { 1328 base.Fatalf("incomplete itab") 1329 } 1330 1331 // dump empty itab symbol into i.sym 1332 // type itab struct { 1333 // inter *interfacetype 1334 // _type *_type 1335 // hash uint32 // copy of _type.hash. Used for type switches. 1336 // _ [4]byte 1337 // fun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter. 1338 // } 1339 o := objw.SymPtr(lsym, 0, writeType(iface), 0) 1340 o = objw.SymPtr(lsym, o, writeType(typ), 0) 1341 o = objw.Uint32(lsym, o, types.TypeHash(typ)) // copy of type hash 1342 o += 4 // skip unused field 1343 if !completeItab { 1344 // If typ doesn't implement iface, make method entries be zero. 1345 o = objw.Uintptr(lsym, o, 0) 1346 entries = entries[:0] 1347 } 1348 for _, fn := range entries { 1349 o = objw.SymPtrWeak(lsym, o, fn, 0) // method pointer for each method 1350 } 1351 // Nothing writes static itabs, so they are read only. 1352 objw.Global(lsym, int32(o), int16(obj.DUPOK|obj.RODATA)) 1353 lsym.Set(obj.AttrContentAddressable, true) 1354 } 1355 1356 func WriteTabs() { 1357 // process ptabs 1358 if types.LocalPkg.Name == "main" && len(ptabs) > 0 { 1359 ot := 0 1360 s := base.Ctxt.Lookup("go:plugin.tabs") 1361 for _, p := range ptabs { 1362 // Dump ptab symbol into go.pluginsym package. 1363 // 1364 // type ptab struct { 1365 // name nameOff 1366 // typ typeOff // pointer to symbol 1367 // } 1368 nsym := dname(p.Sym().Name, "", nil, true, false) 1369 t := p.Type() 1370 if p.Class != ir.PFUNC { 1371 t = types.NewPtr(t) 1372 } 1373 tsym := writeType(t) 1374 ot = objw.SymPtrOff(s, ot, nsym) 1375 ot = objw.SymPtrOff(s, ot, tsym) 1376 // Plugin exports symbols as interfaces. Mark their types 1377 // as UsedInIface. 1378 tsym.Set(obj.AttrUsedInIface, true) 1379 } 1380 objw.Global(s, int32(ot), int16(obj.RODATA)) 1381 1382 ot = 0 1383 s = base.Ctxt.Lookup("go:plugin.exports") 1384 for _, p := range ptabs { 1385 ot = objw.SymPtr(s, ot, p.Linksym(), 0) 1386 } 1387 objw.Global(s, int32(ot), int16(obj.RODATA)) 1388 } 1389 } 1390 1391 func WriteImportStrings() { 1392 // generate import strings for imported packages 1393 for _, p := range types.ImportedPkgList() { 1394 dimportpath(p) 1395 } 1396 } 1397 1398 // writtenByWriteBasicTypes reports whether typ is written by WriteBasicTypes. 1399 // WriteBasicTypes always writes pointer types; any pointer has been stripped off typ already. 1400 func writtenByWriteBasicTypes(typ *types.Type) bool { 1401 if typ.Sym() == nil && typ.Kind() == types.TFUNC { 1402 f := typ.FuncType() 1403 // func(error) string 1404 if f.Receiver.NumFields() == 0 && f.TParams.NumFields() == 0 && 1405 f.Params.NumFields() == 1 && f.Results.NumFields() == 1 && 1406 f.Params.FieldType(0) == types.ErrorType && 1407 f.Results.FieldType(0) == types.Types[types.TSTRING] { 1408 return true 1409 } 1410 } 1411 1412 // Now we have left the basic types plus any and error, plus slices of them. 1413 // Strip the slice. 1414 if typ.Sym() == nil && typ.IsSlice() { 1415 typ = typ.Elem() 1416 } 1417 1418 // Basic types. 1419 sym := typ.Sym() 1420 if sym != nil && (sym.Pkg == types.BuiltinPkg || sym.Pkg == types.UnsafePkg) { 1421 return true 1422 } 1423 // any or error 1424 return (sym == nil && typ.IsEmptyInterface()) || typ == types.ErrorType 1425 } 1426 1427 func WriteBasicTypes() { 1428 // do basic types if compiling package runtime. 1429 // they have to be in at least one package, 1430 // and runtime is always loaded implicitly, 1431 // so this is as good as any. 1432 // another possible choice would be package main, 1433 // but using runtime means fewer copies in object files. 1434 // The code here needs to be in sync with writtenByWriteBasicTypes above. 1435 if base.Ctxt.Pkgpath == "runtime" { 1436 // Note: always write NewPtr(t) because NeedEmit's caller strips the pointer. 1437 var list []*types.Type 1438 for i := types.Kind(1); i <= types.TBOOL; i++ { 1439 list = append(list, types.Types[i]) 1440 } 1441 list = append(list, 1442 types.Types[types.TSTRING], 1443 types.Types[types.TUNSAFEPTR], 1444 types.AnyType, 1445 types.ErrorType) 1446 for _, t := range list { 1447 writeType(types.NewPtr(t)) 1448 writeType(types.NewPtr(types.NewSlice(t))) 1449 } 1450 1451 // emit type for func(error) string, 1452 // which is the type of an auto-generated wrapper. 1453 writeType(types.NewPtr(types.NewSignature(types.NoPkg, nil, nil, []*types.Field{ 1454 types.NewField(base.Pos, nil, types.ErrorType), 1455 }, []*types.Field{ 1456 types.NewField(base.Pos, nil, types.Types[types.TSTRING]), 1457 }))) 1458 1459 // add paths for runtime and main, which 6l imports implicitly. 1460 dimportpath(ir.Pkgs.Runtime) 1461 1462 if base.Flag.Race { 1463 dimportpath(types.NewPkg("runtime/race", "")) 1464 } 1465 if base.Flag.MSan { 1466 dimportpath(types.NewPkg("runtime/msan", "")) 1467 } 1468 if base.Flag.ASan { 1469 dimportpath(types.NewPkg("runtime/asan", "")) 1470 } 1471 1472 dimportpath(types.NewPkg("main", "")) 1473 } 1474 } 1475 1476 type typeAndStr struct { 1477 t *types.Type 1478 short string // "short" here means TypeSymName 1479 regular string 1480 } 1481 1482 type typesByString []typeAndStr 1483 1484 func (a typesByString) Len() int { return len(a) } 1485 func (a typesByString) Less(i, j int) bool { 1486 // put named types before unnamed types 1487 if a[i].t.Sym() != nil && a[j].t.Sym() == nil { 1488 return true 1489 } 1490 if a[i].t.Sym() == nil && a[j].t.Sym() != nil { 1491 return false 1492 } 1493 1494 if a[i].short != a[j].short { 1495 return a[i].short < a[j].short 1496 } 1497 // When the only difference between the types is whether 1498 // they refer to byte or uint8, such as **byte vs **uint8, 1499 // the types' NameStrings can be identical. 1500 // To preserve deterministic sort ordering, sort these by String(). 1501 // 1502 // TODO(mdempsky): This all seems suspect. Using LinkString would 1503 // avoid naming collisions, and there shouldn't be a reason to care 1504 // about "byte" vs "uint8": they share the same runtime type 1505 // descriptor anyway. 1506 if a[i].regular != a[j].regular { 1507 return a[i].regular < a[j].regular 1508 } 1509 // Identical anonymous interfaces defined in different locations 1510 // will be equal for the above checks, but different in DWARF output. 1511 // Sort by source position to ensure deterministic order. 1512 // See issues 27013 and 30202. 1513 if a[i].t.Kind() == types.TINTER && a[i].t.AllMethods().Len() > 0 { 1514 return a[i].t.AllMethods().Index(0).Pos.Before(a[j].t.AllMethods().Index(0).Pos) 1515 } 1516 return false 1517 } 1518 func (a typesByString) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 1519 1520 // maxPtrmaskBytes is the maximum length of a GC ptrmask bitmap, 1521 // which holds 1-bit entries describing where pointers are in a given type. 1522 // Above this length, the GC information is recorded as a GC program, 1523 // which can express repetition compactly. In either form, the 1524 // information is used by the runtime to initialize the heap bitmap, 1525 // and for large types (like 128 or more words), they are roughly the 1526 // same speed. GC programs are never much larger and often more 1527 // compact. (If large arrays are involved, they can be arbitrarily 1528 // more compact.) 1529 // 1530 // The cutoff must be large enough that any allocation large enough to 1531 // use a GC program is large enough that it does not share heap bitmap 1532 // bytes with any other objects, allowing the GC program execution to 1533 // assume an aligned start and not use atomic operations. In the current 1534 // runtime, this means all malloc size classes larger than the cutoff must 1535 // be multiples of four words. On 32-bit systems that's 16 bytes, and 1536 // all size classes >= 16 bytes are 16-byte aligned, so no real constraint. 1537 // On 64-bit systems, that's 32 bytes, and 32-byte alignment is guaranteed 1538 // for size classes >= 256 bytes. On a 64-bit system, 256 bytes allocated 1539 // is 32 pointers, the bits for which fit in 4 bytes. So maxPtrmaskBytes 1540 // must be >= 4. 1541 // 1542 // We used to use 16 because the GC programs do have some constant overhead 1543 // to get started, and processing 128 pointers seems to be enough to 1544 // amortize that overhead well. 1545 // 1546 // To make sure that the runtime's chansend can call typeBitsBulkBarrier, 1547 // we raised the limit to 2048, so that even 32-bit systems are guaranteed to 1548 // use bitmaps for objects up to 64 kB in size. 1549 // 1550 // Also known to reflect/type.go. 1551 const maxPtrmaskBytes = 2048 1552 1553 // GCSym returns a data symbol containing GC information for type t, along 1554 // with a boolean reporting whether the UseGCProg bit should be set in the 1555 // type kind, and the ptrdata field to record in the reflect type information. 1556 // GCSym may be called in concurrent backend, so it does not emit the symbol 1557 // content. 1558 func GCSym(t *types.Type) (lsym *obj.LSym, useGCProg bool, ptrdata int64) { 1559 // Record that we need to emit the GC symbol. 1560 gcsymmu.Lock() 1561 if _, ok := gcsymset[t]; !ok { 1562 gcsymset[t] = struct{}{} 1563 } 1564 gcsymmu.Unlock() 1565 1566 return dgcsym(t, false) 1567 } 1568 1569 // dgcsym returns a data symbol containing GC information for type t, along 1570 // with a boolean reporting whether the UseGCProg bit should be set in the 1571 // type kind, and the ptrdata field to record in the reflect type information. 1572 // When write is true, it writes the symbol data. 1573 func dgcsym(t *types.Type, write bool) (lsym *obj.LSym, useGCProg bool, ptrdata int64) { 1574 ptrdata = types.PtrDataSize(t) 1575 if ptrdata/int64(types.PtrSize) <= maxPtrmaskBytes*8 { 1576 lsym = dgcptrmask(t, write) 1577 return 1578 } 1579 1580 useGCProg = true 1581 lsym, ptrdata = dgcprog(t, write) 1582 return 1583 } 1584 1585 // dgcptrmask emits and returns the symbol containing a pointer mask for type t. 1586 func dgcptrmask(t *types.Type, write bool) *obj.LSym { 1587 // Bytes we need for the ptrmask. 1588 n := (types.PtrDataSize(t)/int64(types.PtrSize) + 7) / 8 1589 // Runtime wants ptrmasks padded to a multiple of uintptr in size. 1590 n = (n + int64(types.PtrSize) - 1) &^ (int64(types.PtrSize) - 1) 1591 ptrmask := make([]byte, n) 1592 fillptrmask(t, ptrmask) 1593 p := fmt.Sprintf("runtime.gcbits.%x", ptrmask) 1594 1595 lsym := base.Ctxt.Lookup(p) 1596 if write && !lsym.OnList() { 1597 for i, x := range ptrmask { 1598 objw.Uint8(lsym, i, x) 1599 } 1600 objw.Global(lsym, int32(len(ptrmask)), obj.DUPOK|obj.RODATA|obj.LOCAL) 1601 lsym.Set(obj.AttrContentAddressable, true) 1602 } 1603 return lsym 1604 } 1605 1606 // fillptrmask fills in ptrmask with 1s corresponding to the 1607 // word offsets in t that hold pointers. 1608 // ptrmask is assumed to fit at least types.PtrDataSize(t)/PtrSize bits. 1609 func fillptrmask(t *types.Type, ptrmask []byte) { 1610 for i := range ptrmask { 1611 ptrmask[i] = 0 1612 } 1613 if !t.HasPointers() { 1614 return 1615 } 1616 1617 vec := bitvec.New(8 * int32(len(ptrmask))) 1618 typebits.Set(t, 0, vec) 1619 1620 nptr := types.PtrDataSize(t) / int64(types.PtrSize) 1621 for i := int64(0); i < nptr; i++ { 1622 if vec.Get(int32(i)) { 1623 ptrmask[i/8] |= 1 << (uint(i) % 8) 1624 } 1625 } 1626 } 1627 1628 // dgcprog emits and returns the symbol containing a GC program for type t 1629 // along with the size of the data described by the program (in the range 1630 // [types.PtrDataSize(t), t.Width]). 1631 // In practice, the size is types.PtrDataSize(t) except for non-trivial arrays. 1632 // For non-trivial arrays, the program describes the full t.Width size. 1633 func dgcprog(t *types.Type, write bool) (*obj.LSym, int64) { 1634 types.CalcSize(t) 1635 if t.Size() == types.BADWIDTH { 1636 base.Fatalf("dgcprog: %v badwidth", t) 1637 } 1638 lsym := TypeLinksymPrefix(".gcprog", t) 1639 var p gcProg 1640 p.init(lsym, write) 1641 p.emit(t, 0) 1642 offset := p.w.BitIndex() * int64(types.PtrSize) 1643 p.end() 1644 if ptrdata := types.PtrDataSize(t); offset < ptrdata || offset > t.Size() { 1645 base.Fatalf("dgcprog: %v: offset=%d but ptrdata=%d size=%d", t, offset, ptrdata, t.Size()) 1646 } 1647 return lsym, offset 1648 } 1649 1650 type gcProg struct { 1651 lsym *obj.LSym 1652 symoff int 1653 w gcprog.Writer 1654 write bool 1655 } 1656 1657 func (p *gcProg) init(lsym *obj.LSym, write bool) { 1658 p.lsym = lsym 1659 p.write = write && !lsym.OnList() 1660 p.symoff = 4 // first 4 bytes hold program length 1661 if !write { 1662 p.w.Init(func(byte) {}) 1663 return 1664 } 1665 p.w.Init(p.writeByte) 1666 if base.Debug.GCProg > 0 { 1667 fmt.Fprintf(os.Stderr, "compile: start GCProg for %v\n", lsym) 1668 p.w.Debug(os.Stderr) 1669 } 1670 } 1671 1672 func (p *gcProg) writeByte(x byte) { 1673 p.symoff = objw.Uint8(p.lsym, p.symoff, x) 1674 } 1675 1676 func (p *gcProg) end() { 1677 p.w.End() 1678 if !p.write { 1679 return 1680 } 1681 objw.Uint32(p.lsym, 0, uint32(p.symoff-4)) 1682 objw.Global(p.lsym, int32(p.symoff), obj.DUPOK|obj.RODATA|obj.LOCAL) 1683 p.lsym.Set(obj.AttrContentAddressable, true) 1684 if base.Debug.GCProg > 0 { 1685 fmt.Fprintf(os.Stderr, "compile: end GCProg for %v\n", p.lsym) 1686 } 1687 } 1688 1689 func (p *gcProg) emit(t *types.Type, offset int64) { 1690 types.CalcSize(t) 1691 if !t.HasPointers() { 1692 return 1693 } 1694 if t.Size() == int64(types.PtrSize) { 1695 p.w.Ptr(offset / int64(types.PtrSize)) 1696 return 1697 } 1698 switch t.Kind() { 1699 default: 1700 base.Fatalf("gcProg.emit: unexpected type %v", t) 1701 1702 case types.TSTRING: 1703 p.w.Ptr(offset / int64(types.PtrSize)) 1704 1705 case types.TINTER: 1706 // Note: the first word isn't a pointer. See comment in typebits.Set 1707 p.w.Ptr(offset/int64(types.PtrSize) + 1) 1708 1709 case types.TSLICE: 1710 p.w.Ptr(offset / int64(types.PtrSize)) 1711 1712 case types.TARRAY: 1713 if t.NumElem() == 0 { 1714 // should have been handled by haspointers check above 1715 base.Fatalf("gcProg.emit: empty array") 1716 } 1717 1718 // Flatten array-of-array-of-array to just a big array by multiplying counts. 1719 count := t.NumElem() 1720 elem := t.Elem() 1721 for elem.IsArray() { 1722 count *= elem.NumElem() 1723 elem = elem.Elem() 1724 } 1725 1726 if !p.w.ShouldRepeat(elem.Size()/int64(types.PtrSize), count) { 1727 // Cheaper to just emit the bits. 1728 for i := int64(0); i < count; i++ { 1729 p.emit(elem, offset+i*elem.Size()) 1730 } 1731 return 1732 } 1733 p.emit(elem, offset) 1734 p.w.ZeroUntil((offset + elem.Size()) / int64(types.PtrSize)) 1735 p.w.Repeat(elem.Size()/int64(types.PtrSize), count-1) 1736 1737 case types.TSTRUCT: 1738 for _, t1 := range t.Fields().Slice() { 1739 p.emit(t1.Type, offset+t1.Offset) 1740 } 1741 } 1742 } 1743 1744 // ZeroAddr returns the address of a symbol with at least 1745 // size bytes of zeros. 1746 func ZeroAddr(size int64) ir.Node { 1747 if size >= 1<<31 { 1748 base.Fatalf("map elem too big %d", size) 1749 } 1750 if ZeroSize < size { 1751 ZeroSize = size 1752 } 1753 lsym := base.PkgLinksym("go:map", "zero", obj.ABI0) 1754 x := ir.NewLinksymExpr(base.Pos, lsym, types.Types[types.TUINT8]) 1755 return typecheck.Expr(typecheck.NodAddr(x)) 1756 } 1757 1758 func CollectPTabs() { 1759 if !base.Ctxt.Flag_dynlink || types.LocalPkg.Name != "main" { 1760 return 1761 } 1762 for _, exportn := range typecheck.Target.Exports { 1763 s := exportn.Sym() 1764 nn := ir.AsNode(s.Def) 1765 if nn == nil { 1766 continue 1767 } 1768 if nn.Op() != ir.ONAME { 1769 continue 1770 } 1771 n := nn.(*ir.Name) 1772 if !types.IsExported(s.Name) { 1773 continue 1774 } 1775 if s.Pkg.Name != "main" { 1776 continue 1777 } 1778 if n.Type().HasTParam() { 1779 continue // skip generic functions (#52937) 1780 } 1781 ptabs = append(ptabs, n) 1782 } 1783 } 1784 1785 // NeedEmit reports whether typ is a type that we need to emit code 1786 // for (e.g., runtime type descriptors, method wrappers). 1787 func NeedEmit(typ *types.Type) bool { 1788 // TODO(mdempsky): Export data should keep track of which anonymous 1789 // and instantiated types were emitted, so at least downstream 1790 // packages can skip re-emitting them. 1791 // 1792 // Perhaps we can just generalize the linker-symbol indexing to 1793 // track the index of arbitrary types, not just defined types, and 1794 // use its presence to detect this. The same idea would work for 1795 // instantiated generic functions too. 1796 1797 switch sym := typ.Sym(); { 1798 case writtenByWriteBasicTypes(typ): 1799 return base.Ctxt.Pkgpath == "runtime" 1800 1801 case sym == nil: 1802 // Anonymous type; possibly never seen before or ever again. 1803 // Need to emit to be safe (however, see TODO above). 1804 return true 1805 1806 case sym.Pkg == types.LocalPkg: 1807 // Local defined type; our responsibility. 1808 return true 1809 1810 case typ.IsFullyInstantiated(): 1811 // Instantiated type; possibly instantiated with unique type arguments. 1812 // Need to emit to be safe (however, see TODO above). 1813 return true 1814 1815 case typ.HasShape(): 1816 // Shape type; need to emit even though it lives in the .shape package. 1817 // TODO: make sure the linker deduplicates them (see dupok in writeType above). 1818 return true 1819 1820 default: 1821 // Should have been emitted by an imported package. 1822 return false 1823 } 1824 } 1825 1826 // Generate a wrapper function to convert from 1827 // a receiver of type T to a receiver of type U. 1828 // That is, 1829 // 1830 // func (t T) M() { 1831 // ... 1832 // } 1833 // 1834 // already exists; this function generates 1835 // 1836 // func (u U) M() { 1837 // u.M() 1838 // } 1839 // 1840 // where the types T and U are such that u.M() is valid 1841 // and calls the T.M method. 1842 // The resulting function is for use in method tables. 1843 // 1844 // rcvr - U 1845 // method - M func (t T)(), a TFIELD type struct 1846 // 1847 // Also wraps methods on instantiated generic types for use in itab entries. 1848 // For an instantiated generic type G[int], we generate wrappers like: 1849 // G[int] pointer shaped: 1850 // 1851 // func (x G[int]) f(arg) { 1852 // .inst.G[int].f(dictionary, x, arg) 1853 // } 1854 // 1855 // G[int] not pointer shaped: 1856 // 1857 // func (x *G[int]) f(arg) { 1858 // .inst.G[int].f(dictionary, *x, arg) 1859 // } 1860 // 1861 // These wrappers are always fully stenciled. 1862 func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSym { 1863 orig := rcvr 1864 if forItab && !types.IsDirectIface(rcvr) { 1865 rcvr = rcvr.PtrTo() 1866 } 1867 1868 generic := false 1869 // We don't need a dictionary if we are reaching a method (possibly via an 1870 // embedded field) which is an interface method. 1871 if !types.IsInterfaceMethod(method.Type) { 1872 rcvr1 := deref(rcvr) 1873 if len(rcvr1.RParams()) > 0 { 1874 // If rcvr has rparams, remember method as generic, which 1875 // means we need to add a dictionary to the wrapper. 1876 generic = true 1877 if rcvr.HasShape() { 1878 base.Fatalf("method on type instantiated with shapes, rcvr:%+v", rcvr) 1879 } 1880 } 1881 } 1882 1883 newnam := ir.MethodSym(rcvr, method.Sym) 1884 lsym := newnam.Linksym() 1885 1886 // Unified IR creates its own wrappers. 1887 if base.Debug.Unified != 0 { 1888 return lsym 1889 } 1890 1891 if newnam.Siggen() { 1892 return lsym 1893 } 1894 newnam.SetSiggen(true) 1895 1896 methodrcvr := method.Type.Recv().Type 1897 // For generic methods, we need to generate the wrapper even if the receiver 1898 // types are identical, because we want to add the dictionary. 1899 if !generic && types.Identical(rcvr, methodrcvr) { 1900 return lsym 1901 } 1902 1903 if !NeedEmit(rcvr) || rcvr.IsPtr() && !NeedEmit(rcvr.Elem()) { 1904 return lsym 1905 } 1906 1907 base.Pos = base.AutogeneratedPos 1908 typecheck.DeclContext = ir.PEXTERN 1909 1910 // TODO(austin): SelectorExpr may have created one or more 1911 // ir.Names for these already with a nil Func field. We should 1912 // consolidate these and always attach a Func to the Name. 1913 fn := typecheck.DeclFunc(newnam, ir.NewField(base.Pos, typecheck.Lookup(".this"), rcvr), 1914 typecheck.NewFuncParams(method.Type.Params(), true), 1915 typecheck.NewFuncParams(method.Type.Results(), false)) 1916 1917 fn.SetDupok(true) 1918 1919 nthis := ir.AsNode(fn.Type().Recv().Nname) 1920 1921 indirect := rcvr.IsPtr() && rcvr.Elem() == methodrcvr 1922 1923 // generate nil pointer check for better error 1924 if indirect { 1925 // generating wrapper from *T to T. 1926 n := ir.NewIfStmt(base.Pos, nil, nil, nil) 1927 n.Cond = ir.NewBinaryExpr(base.Pos, ir.OEQ, nthis, typecheck.NodNil()) 1928 call := ir.NewCallExpr(base.Pos, ir.OCALL, typecheck.LookupRuntime("panicwrap"), nil) 1929 n.Body = []ir.Node{call} 1930 fn.Body.Append(n) 1931 } 1932 1933 dot := typecheck.AddImplicitDots(ir.NewSelectorExpr(base.Pos, ir.OXDOT, nthis, method.Sym)) 1934 // generate call 1935 // It's not possible to use a tail call when dynamic linking on ppc64le. The 1936 // bad scenario is when a local call is made to the wrapper: the wrapper will 1937 // call the implementation, which might be in a different module and so set 1938 // the TOC to the appropriate value for that module. But if it returns 1939 // directly to the wrapper's caller, nothing will reset it to the correct 1940 // value for that function. 1941 var call *ir.CallExpr 1942 if !base.Flag.Cfg.Instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !types.IsInterfaceMethod(method.Type) && !(base.Ctxt.Arch.Name == "ppc64le" && base.Ctxt.Flag_dynlink) && !generic { 1943 call = ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil) 1944 call.Args = ir.ParamNames(fn.Type()) 1945 call.IsDDD = fn.Type().IsVariadic() 1946 fn.Body.Append(ir.NewTailCallStmt(base.Pos, call)) 1947 } else { 1948 fn.SetWrapper(true) // ignore frame for panic+recover matching 1949 1950 if generic && dot.X != nthis { 1951 // If there is embedding involved, then we should do the 1952 // normal non-generic embedding wrapper below, which calls 1953 // the wrapper for the real receiver type using dot as an 1954 // argument. There is no need for generic processing (adding 1955 // a dictionary) for this wrapper. 1956 generic = false 1957 } 1958 1959 if generic { 1960 targs := deref(rcvr).RParams() 1961 // The wrapper for an auto-generated pointer/non-pointer 1962 // receiver method should share the same dictionary as the 1963 // corresponding original (user-written) method. 1964 baseOrig := orig 1965 if baseOrig.IsPtr() && !methodrcvr.IsPtr() { 1966 baseOrig = baseOrig.Elem() 1967 } else if !baseOrig.IsPtr() && methodrcvr.IsPtr() { 1968 baseOrig = types.NewPtr(baseOrig) 1969 } 1970 args := []ir.Node{getDictionary(ir.MethodSym(baseOrig, method.Sym), targs)} 1971 if indirect { 1972 args = append(args, ir.NewStarExpr(base.Pos, dot.X)) 1973 } else if methodrcvr.IsPtr() && methodrcvr.Elem() == dot.X.Type() { 1974 // Case where method call is via a non-pointer 1975 // embedded field with a pointer method. 1976 args = append(args, typecheck.NodAddrAt(base.Pos, dot.X)) 1977 } else { 1978 args = append(args, dot.X) 1979 } 1980 args = append(args, ir.ParamNames(fn.Type())...) 1981 1982 // Target method uses shaped names. 1983 targs2 := make([]*types.Type, len(targs)) 1984 origRParams := deref(orig).OrigType().RParams() 1985 for i, t := range targs { 1986 targs2[i] = typecheck.Shapify(t, i, origRParams[i]) 1987 } 1988 targs = targs2 1989 1990 sym := typecheck.MakeFuncInstSym(ir.MethodSym(methodrcvr, method.Sym), targs, false, true) 1991 if sym.Def == nil { 1992 // Currently we make sure that we have all the 1993 // instantiations we need by generating them all in 1994 // ../noder/stencil.go:instantiateMethods 1995 // Extra instantiations because of an inlined function 1996 // should have been exported, and so available via 1997 // Resolve. 1998 in := typecheck.Resolve(ir.NewIdent(src.NoXPos, sym)) 1999 if in.Op() == ir.ONONAME { 2000 base.Fatalf("instantiation %s not found", sym.Name) 2001 } 2002 sym = in.Sym() 2003 } 2004 target := ir.AsNode(sym.Def) 2005 call = ir.NewCallExpr(base.Pos, ir.OCALL, target, args) 2006 // Fill-in the generic method node that was not filled in 2007 // in instantiateMethod. 2008 method.Nname = fn.Nname 2009 } else { 2010 call = ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil) 2011 call.Args = ir.ParamNames(fn.Type()) 2012 } 2013 call.IsDDD = fn.Type().IsVariadic() 2014 if method.Type.NumResults() > 0 { 2015 ret := ir.NewReturnStmt(base.Pos, nil) 2016 ret.Results = []ir.Node{call} 2017 fn.Body.Append(ret) 2018 } else { 2019 fn.Body.Append(call) 2020 } 2021 } 2022 2023 typecheck.FinishFuncBody() 2024 if base.Debug.DclStack != 0 { 2025 types.CheckDclstack() 2026 } 2027 2028 typecheck.Func(fn) 2029 ir.CurFunc = fn 2030 typecheck.Stmts(fn.Body) 2031 2032 if AfterGlobalEscapeAnalysis { 2033 // Inlining the method may reveal closures, which require walking all function bodies 2034 // to decide whether to capture free variables by value or by ref. So we only do inline 2035 // if the method do not contain any closures, otherwise, the escape analysis may make 2036 // dead variables resurrected, and causing liveness analysis confused, see issue #53702. 2037 var canInline bool 2038 switch x := call.X.(type) { 2039 case *ir.Name: 2040 canInline = len(x.Func.Closures) == 0 2041 case *ir.SelectorExpr: 2042 if x.Op() == ir.OMETHEXPR { 2043 canInline = x.FuncName().Func != nil && len(x.FuncName().Func.Closures) == 0 2044 } 2045 } 2046 if canInline { 2047 // TODO(prattmic): plumb PGO. 2048 inline.InlineCalls(fn, nil) 2049 } 2050 escape.Batch([]*ir.Func{fn}, false) 2051 } 2052 2053 ir.CurFunc = nil 2054 typecheck.Target.Decls = append(typecheck.Target.Decls, fn) 2055 2056 return lsym 2057 } 2058 2059 // AfterGlobalEscapeAnalysis tracks whether package gc has already 2060 // performed the main, global escape analysis pass. If so, 2061 // methodWrapper takes responsibility for escape analyzing any 2062 // generated wrappers. 2063 var AfterGlobalEscapeAnalysis bool 2064 2065 var ZeroSize int64 2066 2067 // MarkTypeUsedInInterface marks that type t is converted to an interface. 2068 // This information is used in the linker in dead method elimination. 2069 func MarkTypeUsedInInterface(t *types.Type, from *obj.LSym) { 2070 if t.HasShape() { 2071 // Shape types shouldn't be put in interfaces, so we shouldn't ever get here. 2072 base.Fatalf("shape types have no methods %+v", t) 2073 } 2074 tsym := TypeLinksym(t) 2075 // Emit a marker relocation. The linker will know the type is converted 2076 // to an interface if "from" is reachable. 2077 r := obj.Addrel(from) 2078 r.Sym = tsym 2079 r.Type = objabi.R_USEIFACE 2080 } 2081 2082 // MarkUsedIfaceMethod marks that an interface method is used in the current 2083 // function. n is OCALLINTER node. 2084 func MarkUsedIfaceMethod(n *ir.CallExpr) { 2085 // skip unnamed functions (func _()) 2086 if ir.CurFunc.LSym == nil { 2087 return 2088 } 2089 dot := n.X.(*ir.SelectorExpr) 2090 ityp := dot.X.Type() 2091 if ityp.HasShape() { 2092 // Here we're calling a method on a generic interface. Something like: 2093 // 2094 // type I[T any] interface { foo() T } 2095 // func f[T any](x I[T]) { 2096 // ... = x.foo() 2097 // } 2098 // f[int](...) 2099 // f[string](...) 2100 // 2101 // In this case, in f we're calling foo on a generic interface. 2102 // Which method could that be? Normally we could match the method 2103 // both by name and by type. But in this case we don't really know 2104 // the type of the method we're calling. It could be func()int 2105 // or func()string. So we match on just the function name, instead 2106 // of both the name and the type used for the non-generic case below. 2107 // TODO: instantiations at least know the shape of the instantiated 2108 // type, and the linker could do more complicated matching using 2109 // some sort of fuzzy shape matching. For now, only use the name 2110 // of the method for matching. 2111 r := obj.Addrel(ir.CurFunc.LSym) 2112 // We use a separate symbol just to tell the linker the method name. 2113 // (The symbol itself is not needed in the final binary. Do not use 2114 // staticdata.StringSym, which creates a content addessable symbol, 2115 // which may have trailing zero bytes. This symbol doesn't need to 2116 // be deduplicated anyway.) 2117 name := dot.Sel.Name 2118 var nameSym obj.LSym 2119 nameSym.WriteString(base.Ctxt, 0, len(name), name) 2120 objw.Global(&nameSym, int32(len(name)), obj.RODATA) 2121 r.Sym = &nameSym 2122 r.Type = objabi.R_USEGENERICIFACEMETHOD 2123 return 2124 } 2125 2126 tsym := TypeLinksym(ityp) 2127 r := obj.Addrel(ir.CurFunc.LSym) 2128 r.Sym = tsym 2129 // dot.Offset() is the method index * PtrSize (the offset of code pointer 2130 // in itab). 2131 midx := dot.Offset() / int64(types.PtrSize) 2132 r.Add = InterfaceMethodOffset(ityp, midx) 2133 r.Type = objabi.R_USEIFACEMETHOD 2134 } 2135 2136 // getDictionary returns the dictionary for the given named generic function 2137 // or method, with the given type arguments. 2138 func getDictionary(gf *types.Sym, targs []*types.Type) ir.Node { 2139 if len(targs) == 0 { 2140 base.Fatalf("%s should have type arguments", gf.Name) 2141 } 2142 for _, t := range targs { 2143 if t.HasShape() { 2144 base.Fatalf("dictionary for %s should only use concrete types: %+v", gf.Name, t) 2145 } 2146 } 2147 2148 sym := typecheck.MakeDictSym(gf, targs, true) 2149 2150 // Dictionary should already have been generated by instantiateMethods(). 2151 // Extra dictionaries needed because of an inlined function should have been 2152 // exported, and so available via Resolve. 2153 if lsym := sym.Linksym(); len(lsym.P) == 0 { 2154 in := typecheck.Resolve(ir.NewIdent(src.NoXPos, sym)) 2155 if in.Op() == ir.ONONAME { 2156 base.Fatalf("Dictionary should have already been generated: %s.%s", sym.Pkg.Path, sym.Name) 2157 } 2158 sym = in.Sym() 2159 } 2160 2161 // Make (or reuse) a node referencing the dictionary symbol. 2162 var n *ir.Name 2163 if sym.Def != nil { 2164 n = sym.Def.(*ir.Name) 2165 } else { 2166 n = typecheck.NewName(sym) 2167 n.SetType(types.Types[types.TUINTPTR]) // should probably be [...]uintptr, but doesn't really matter 2168 n.SetTypecheck(1) 2169 n.Class = ir.PEXTERN 2170 sym.Def = n 2171 } 2172 2173 // Return the address of the dictionary. 2174 np := typecheck.NodAddr(n) 2175 // Note: treat dictionary pointers as uintptrs, so they aren't pointers 2176 // with respect to GC. That saves on stack scanning work, write barriers, etc. 2177 // We can get away with it because dictionaries are global variables. 2178 np.SetType(types.Types[types.TUINTPTR]) 2179 np.SetTypecheck(1) 2180 return np 2181 } 2182 2183 func deref(t *types.Type) *types.Type { 2184 if t.IsPtr() { 2185 return t.Elem() 2186 } 2187 return t 2188 }