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 5package reflectdata 6 7import ( 8 "encoding/binary" 9 "fmt" 10 "os" 11 "sort" 12 "strings" 13 "sync" 14 15 "cmd/compile/internal/base" 16 "cmd/compile/internal/bitvec" 17 "cmd/compile/internal/escape" 18 "cmd/compile/internal/inline" 19 "cmd/compile/internal/ir" 20 "cmd/compile/internal/objw" 21 "cmd/compile/internal/staticdata" 22 "cmd/compile/internal/typebits" 23 "cmd/compile/internal/typecheck" 24 "cmd/compile/internal/types" 25 "cmd/internal/gcprog" 26 "cmd/internal/obj" 27 "cmd/internal/objabi" 28 "cmd/internal/src" 29) 30 31type ptabEntry struct { 32 s *types.Sym 33 t *types.Type 34} 35 36func CountPTabs() int { 37 return len(ptabs) 38} 39 40// runtime interface and reflection data structures 41var ( 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 55type 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. 68const ( 69 BUCKETSIZE = 8 70 MAXKEYSIZE = 128 71 MAXELEMSIZE = 128 72) 73 74func structfieldSize() int { return 3 * types.PtrSize } // Sizeof(runtime.structfield{}) 75func imethodSize() int { return 4 + 4 } // Sizeof(runtime.imethod{}) 76func commonSize() int { return 4*types.PtrSize + 8 + 8 } // Sizeof(runtime._type{}) 77 78func 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 85func 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. 91func 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. 199func 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. 248func 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. 307func 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 apppend 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. 368func 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 401func 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 str := p.Path 414 if p == types.LocalPkg { 415 // Note: myimportpath != "", or else dgopkgpath won't call dimportpath. 416 str = base.Ctxt.Pkgpath 417 } 418 419 s := base.Ctxt.Lookup("type..importpath." + p.Prefix + ".") 420 ot := dnameData(s, 0, str, "", nil, false) 421 objw.Global(s, int32(ot), obj.DUPOK|obj.RODATA) 422 s.Set(obj.AttrContentAddressable, true) 423 p.Pathsym = s 424} 425 426func dgopkgpath(s *obj.LSym, ot int, pkg *types.Pkg) int { 427 if pkg == nil { 428 return objw.Uintptr(s, ot, 0) 429 } 430 431 if pkg == types.LocalPkg && base.Ctxt.Pkgpath == "" { 432 // If we don't know the full import path of the package being compiled 433 // (i.e. -p was not passed on the compiler command line), emit a reference to 434 // type..importpath.""., which the linker will rewrite using the correct import path. 435 // Every package that imports this one directly defines the symbol. 436 // See also https://groups.google.com/forum/#!topic/golang-dev/myb9s53HxGQ. 437 ns := base.Ctxt.Lookup(`type..importpath."".`) 438 return objw.SymPtr(s, ot, ns, 0) 439 } 440 441 dimportpath(pkg) 442 return objw.SymPtr(s, ot, pkg.Pathsym, 0) 443} 444 445// dgopkgpathOff writes an offset relocation in s at offset ot to the pkg path symbol. 446func dgopkgpathOff(s *obj.LSym, ot int, pkg *types.Pkg) int { 447 if pkg == nil { 448 return objw.Uint32(s, ot, 0) 449 } 450 if pkg == types.LocalPkg && base.Ctxt.Pkgpath == "" { 451 // If we don't know the full import path of the package being compiled 452 // (i.e. -p was not passed on the compiler command line), emit a reference to 453 // type..importpath.""., which the linker will rewrite using the correct import path. 454 // Every package that imports this one directly defines the symbol. 455 // See also https://groups.google.com/forum/#!topic/golang-dev/myb9s53HxGQ. 456 ns := base.Ctxt.Lookup(`type..importpath."".`) 457 return objw.SymPtrOff(s, ot, ns) 458 } 459 460 dimportpath(pkg) 461 return objw.SymPtrOff(s, ot, pkg.Pathsym) 462} 463 464// dnameField dumps a reflect.name for a struct field. 465func dnameField(lsym *obj.LSym, ot int, spkg *types.Pkg, ft *types.Field) int { 466 if !types.IsExported(ft.Sym.Name) && ft.Sym.Pkg != spkg { 467 base.Fatalf("package mismatch for %v", ft.Sym) 468 } 469 nsym := dname(ft.Sym.Name, ft.Note, nil, types.IsExported(ft.Sym.Name)) 470 return objw.SymPtr(lsym, ot, nsym, 0) 471} 472 473// dnameData writes the contents of a reflect.name into s at offset ot. 474func dnameData(s *obj.LSym, ot int, name, tag string, pkg *types.Pkg, exported bool) int { 475 if len(name) >= 1<<29 { 476 base.Fatalf("name too long: %d %s...", len(name), name[:1024]) 477 } 478 if len(tag) >= 1<<29 { 479 base.Fatalf("tag too long: %d %s...", len(tag), tag[:1024]) 480 } 481 var nameLen [binary.MaxVarintLen64]byte 482 nameLenLen := binary.PutUvarint(nameLen[:], uint64(len(name))) 483 var tagLen [binary.MaxVarintLen64]byte 484 tagLenLen := binary.PutUvarint(tagLen[:], uint64(len(tag))) 485 486 // Encode name and tag. See reflect/type.go for details. 487 var bits byte 488 l := 1 + nameLenLen + len(name) 489 if exported { 490 bits |= 1 << 0 491 } 492 if len(tag) > 0 { 493 l += tagLenLen + len(tag) 494 bits |= 1 << 1 495 } 496 if pkg != nil { 497 bits |= 1 << 2 498 } 499 b := make([]byte, l) 500 b[0] = bits 501 copy(b[1:], nameLen[:nameLenLen]) 502 copy(b[1+nameLenLen:], name) 503 if len(tag) > 0 { 504 tb := b[1+nameLenLen+len(name):] 505 copy(tb, tagLen[:tagLenLen]) 506 copy(tb[tagLenLen:], tag) 507 } 508 509 ot = int(s.WriteBytes(base.Ctxt, int64(ot), b)) 510 511 if pkg != nil { 512 ot = dgopkgpathOff(s, ot, pkg) 513 } 514 515 return ot 516} 517 518var dnameCount int 519 520// dname creates a reflect.name for a struct field or method. 521func dname(name, tag string, pkg *types.Pkg, exported bool) *obj.LSym { 522 // Write out data as "type.." to signal two things to the 523 // linker, first that when dynamically linking, the symbol 524 // should be moved to a relro section, and second that the 525 // contents should not be decoded as a type. 526 sname := "type..namedata." 527 if pkg == nil { 528 // In the common case, share data with other packages. 529 if name == "" { 530 if exported { 531 sname += "-noname-exported." + tag 532 } else { 533 sname += "-noname-unexported." + tag 534 } 535 } else { 536 if exported { 537 sname += name + "." + tag 538 } else { 539 sname += name + "-" + tag 540 } 541 } 542 } else { 543 sname = fmt.Sprintf(`%s"".%d`, sname, dnameCount) 544 dnameCount++ 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) 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). 559func 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.Rnd(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 592func 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. 610func 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) 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 628func 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 638var 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 674const ( 675 tflagUncommon = 1 << 0 676 tflagExtraStar = 1 << 1 677 tflagNamed = 1 << 2 678 tflagRegularMemory = 1 << 3 679) 680 681var ( 682 memhashvarlen *obj.LSym 683 memequalvarlen *obj.LSym 684) 685 686// dcommontype dumps the contents of a reflect.rtype (runtime._type). 687func 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 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) 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. 799func TrackSym(t *types.Type, f *types.Field) *obj.LSym { 800 return base.PkgLinksym("go.track", t.LinkString()+"."+f.Sym.Name, obj.ABI0) 801} 802 803func 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 818func 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 832func TypeLinksymPrefix(prefix string, t *types.Type) *obj.LSym { 833 return TypeSymPrefix(prefix, t).Linksym() 834} 835 836func TypeLinksymLookup(name string) *obj.LSym { 837 return types.TypeSymLookup(name).Linksym() 838} 839 840func TypeLinksym(t *types.Type) *obj.LSym { 841 return TypeSym(t).Linksym() 842} 843 844func TypePtr(t *types.Type) *ir.AddrExpr { 845 n := ir.NewLinksymExpr(base.Pos, TypeLinksym(t), types.Types[types.TUINT8]) 846 return typecheck.Expr(typecheck.NodAddr(n)).(*ir.AddrExpr) 847} 848 849// ITabLsym returns the LSym representing the itab for concrete type typ implementing 850// interface iface. A dummy tab will be created in the unusual case where typ doesn't 851// implement iface. Normally, this wouldn't happen, because the typechecker would 852// have reported a compile-time error. This situation can only happen when the 853// destination type of a type assert or a type in a type switch is parameterized, so 854// it may sometimes, but not always, be a type that can't implement the specified 855// interface. 856func ITabLsym(typ, iface *types.Type) *obj.LSym { 857 s, existed := ir.Pkgs.Itab.LookupOK(typ.LinkString() + "," + iface.LinkString()) 858 lsym := s.Linksym() 859 860 if !existed { 861 writeITab(lsym, typ, iface, true) 862 } 863 return lsym 864} 865 866// ITabAddr returns an expression representing a pointer to the itab 867// for concrete type typ implementing interface iface. 868func ITabAddr(typ, iface *types.Type) *ir.AddrExpr { 869 s, existed := ir.Pkgs.Itab.LookupOK(typ.LinkString() + "," + iface.LinkString()) 870 lsym := s.Linksym() 871 872 if !existed { 873 writeITab(lsym, typ, iface, false) 874 } 875 876 n := ir.NewLinksymExpr(base.Pos, lsym, types.Types[types.TUINT8]) 877 return typecheck.Expr(typecheck.NodAddr(n)).(*ir.AddrExpr) 878} 879 880// needkeyupdate reports whether map updates with t as a key 881// need the key to be updated. 882func needkeyupdate(t *types.Type) bool { 883 switch t.Kind() { 884 case types.TBOOL, types.TINT, types.TUINT, types.TINT8, types.TUINT8, types.TINT16, types.TUINT16, types.TINT32, types.TUINT32, 885 types.TINT64, types.TUINT64, types.TUINTPTR, types.TPTR, types.TUNSAFEPTR, types.TCHAN: 886 return false 887 888 case types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128, // floats and complex can be +0/-0 889 types.TINTER, 890 types.TSTRING: // strings might have smaller backing stores 891 return true 892 893 case types.TARRAY: 894 return needkeyupdate(t.Elem()) 895 896 case types.TSTRUCT: 897 for _, t1 := range t.Fields().Slice() { 898 if needkeyupdate(t1.Type) { 899 return true 900 } 901 } 902 return false 903 904 default: 905 base.Fatalf("bad type for map key: %v", t) 906 return true 907 } 908} 909 910// hashMightPanic reports whether the hash of a map key of type t might panic. 911func hashMightPanic(t *types.Type) bool { 912 switch t.Kind() { 913 case types.TINTER: 914 return true 915 916 case types.TARRAY: 917 return hashMightPanic(t.Elem()) 918 919 case types.TSTRUCT: 920 for _, t1 := range t.Fields().Slice() { 921 if hashMightPanic(t1.Type) { 922 return true 923 } 924 } 925 return false 926 927 default: 928 return false 929 } 930} 931 932// formalType replaces predeclared aliases with real types. 933// They've been separate internally to make error messages 934// better, but we have to merge them in the reflect tables. 935func formalType(t *types.Type) *types.Type { 936 switch t { 937 case types.AnyType, types.ByteType, types.RuneType: 938 return types.Types[t.Kind()] 939 } 940 return t 941} 942 943func writeType(t *types.Type) *obj.LSym { 944 t = formalType(t) 945 if t.IsUntyped() || t.HasTParam() { 946 base.Fatalf("writeType %v", t) 947 } 948 949 s := types.TypeSym(t) 950 lsym := s.Linksym() 951 if s.Siggen() { 952 return lsym 953 } 954 s.SetSiggen(true) 955 956 // special case (look for runtime below): 957 // when compiling package runtime, 958 // emit the type structures for int, float, etc. 959 tbase := t 960 961 if t.IsPtr() && t.Sym() == nil && t.Elem().Sym() != nil { 962 tbase = t.Elem() 963 } 964 if tbase.Kind() == types.TFORW { 965 base.Fatalf("unresolved defined type: %v", tbase) 966 } 967 968 if !NeedEmit(tbase) { 969 if i := typecheck.BaseTypeIndex(t); i >= 0 { 970 lsym.Pkg = tbase.Sym().Pkg.Prefix 971 lsym.SymIdx = int32(i) 972 lsym.Set(obj.AttrIndexed, true) 973 } 974 975 // TODO(mdempsky): Investigate whether this still happens. 976 // If we know we don't need to emit code for a type, 977 // we should have a link-symbol index for it. 978 // See also TODO in NeedEmit. 979 return lsym 980 } 981 982 ot := 0 983 switch t.Kind() { 984 default: 985 ot = dcommontype(lsym, t) 986 ot = dextratype(lsym, ot, t, 0) 987 988 case types.TARRAY: 989 // ../../../../runtime/type.go:/arrayType 990 s1 := writeType(t.Elem()) 991 t2 := types.NewSlice(t.Elem()) 992 s2 := writeType(t2) 993 ot = dcommontype(lsym, t) 994 ot = objw.SymPtr(lsym, ot, s1, 0) 995 ot = objw.SymPtr(lsym, ot, s2, 0) 996 ot = objw.Uintptr(lsym, ot, uint64(t.NumElem())) 997 ot = dextratype(lsym, ot, t, 0) 998 999 case types.TSLICE: 1000 // ../../../../runtime/type.go:/sliceType 1001 s1 := writeType(t.Elem()) 1002 ot = dcommontype(lsym, t) 1003 ot = objw.SymPtr(lsym, ot, s1, 0) 1004 ot = dextratype(lsym, ot, t, 0) 1005 1006 case types.TCHAN: 1007 // ../../../../runtime/type.go:/chanType 1008 s1 := writeType(t.Elem()) 1009 ot = dcommontype(lsym, t) 1010 ot = objw.SymPtr(lsym, ot, s1, 0) 1011 ot = objw.Uintptr(lsym, ot, uint64(t.ChanDir())) 1012 ot = dextratype(lsym, ot, t, 0) 1013 1014 case types.TFUNC: 1015 for _, t1 := range t.Recvs().Fields().Slice() { 1016 writeType(t1.Type) 1017 } 1018 isddd := false 1019 for _, t1 := range t.Params().Fields().Slice() { 1020 isddd = t1.IsDDD() 1021 writeType(t1.Type) 1022 } 1023 for _, t1 := range t.Results().Fields().Slice() { 1024 writeType(t1.Type) 1025 } 1026 1027 ot = dcommontype(lsym, t) 1028 inCount := t.NumRecvs() + t.NumParams() 1029 outCount := t.NumResults() 1030 if isddd { 1031 outCount |= 1 << 15 1032 } 1033 ot = objw.Uint16(lsym, ot, uint16(inCount)) 1034 ot = objw.Uint16(lsym, ot, uint16(outCount)) 1035 if types.PtrSize == 8 { 1036 ot += 4 // align for *rtype 1037 } 1038 1039 dataAdd := (inCount + t.NumResults()) * types.PtrSize 1040 ot = dextratype(lsym, ot, t, dataAdd) 1041 1042 // Array of rtype pointers follows funcType. 1043 for _, t1 := range t.Recvs().Fields().Slice() { 1044 ot = objw.SymPtr(lsym, ot, writeType(t1.Type), 0) 1045 } 1046 for _, t1 := range t.Params().Fields().Slice() { 1047 ot = objw.SymPtr(lsym, ot, writeType(t1.Type), 0) 1048 } 1049 for _, t1 := range t.Results().Fields().Slice() { 1050 ot = objw.SymPtr(lsym, ot, writeType(t1.Type), 0) 1051 } 1052 1053 case types.TINTER: 1054 m := imethods(t) 1055 n := len(m) 1056 for _, a := range m { 1057 writeType(a.type_) 1058 } 1059 1060 // ../../../../runtime/type.go:/interfaceType 1061 ot = dcommontype(lsym, t) 1062 1063 var tpkg *types.Pkg 1064 if t.Sym() != nil && t != types.Types[t.Kind()] && t != types.ErrorType { 1065 tpkg = t.Sym().Pkg 1066 } 1067 ot = dgopkgpath(lsym, ot, tpkg) 1068 1069 ot = objw.SymPtr(lsym, ot, lsym, ot+3*types.PtrSize+uncommonSize(t)) 1070 ot = objw.Uintptr(lsym, ot, uint64(n)) 1071 ot = objw.Uintptr(lsym, ot, uint64(n)) 1072 dataAdd := imethodSize() * n 1073 ot = dextratype(lsym, ot, t, dataAdd) 1074 1075 for _, a := range m { 1076 // ../../../../runtime/type.go:/imethod 1077 exported := types.IsExported(a.name.Name) 1078 var pkg *types.Pkg 1079 if !exported && a.name.Pkg != tpkg { 1080 pkg = a.name.Pkg 1081 } 1082 nsym := dname(a.name.Name, "", pkg, exported) 1083 1084 ot = objw.SymPtrOff(lsym, ot, nsym) 1085 ot = objw.SymPtrOff(lsym, ot, writeType(a.type_)) 1086 } 1087 1088 // ../../../../runtime/type.go:/mapType 1089 case types.TMAP: 1090 s1 := writeType(t.Key()) 1091 s2 := writeType(t.Elem()) 1092 s3 := writeType(MapBucketType(t)) 1093 hasher := genhash(t.Key()) 1094 1095 ot = dcommontype(lsym, t) 1096 ot = objw.SymPtr(lsym, ot, s1, 0) 1097 ot = objw.SymPtr(lsym, ot, s2, 0) 1098 ot = objw.SymPtr(lsym, ot, s3, 0) 1099 ot = objw.SymPtr(lsym, ot, hasher, 0) 1100 var flags uint32 1101 // Note: flags must match maptype accessors in ../../../../runtime/type.go 1102 // and maptype builder in ../../../../reflect/type.go:MapOf. 1103 if t.Key().Size() > MAXKEYSIZE { 1104 ot = objw.Uint8(lsym, ot, uint8(types.PtrSize)) 1105 flags |= 1 // indirect key 1106 } else { 1107 ot = objw.Uint8(lsym, ot, uint8(t.Key().Size())) 1108 } 1109 1110 if t.Elem().Size() > MAXELEMSIZE { 1111 ot = objw.Uint8(lsym, ot, uint8(types.PtrSize)) 1112 flags |= 2 // indirect value 1113 } else { 1114 ot = objw.Uint8(lsym, ot, uint8(t.Elem().Size())) 1115 } 1116 ot = objw.Uint16(lsym, ot, uint16(MapBucketType(t).Size())) 1117 if types.IsReflexive(t.Key()) { 1118 flags |= 4 // reflexive key 1119 } 1120 if needkeyupdate(t.Key()) { 1121 flags |= 8 // need key update 1122 } 1123 if hashMightPanic(t.Key()) { 1124 flags |= 16 // hash might panic 1125 } 1126 ot = objw.Uint32(lsym, ot, flags) 1127 ot = dextratype(lsym, ot, t, 0) 1128 if u := t.Underlying(); u != t { 1129 // If t is a named map type, also keep the underlying map 1130 // type live in the binary. This is important to make sure that 1131 // a named map and that same map cast to its underlying type via 1132 // reflection, use the same hash function. See issue 37716. 1133 r := obj.Addrel(lsym) 1134 r.Sym = writeType(u) 1135 r.Type = objabi.R_KEEP 1136 } 1137 1138 case types.TPTR: 1139 if t.Elem().Kind() == types.TANY { 1140 // ../../../../runtime/type.go:/UnsafePointerType 1141 ot = dcommontype(lsym, t) 1142 ot = dextratype(lsym, ot, t, 0) 1143 1144 break 1145 } 1146 1147 // ../../../../runtime/type.go:/ptrType 1148 s1 := writeType(t.Elem()) 1149 1150 ot = dcommontype(lsym, t) 1151 ot = objw.SymPtr(lsym, ot, s1, 0) 1152 ot = dextratype(lsym, ot, t, 0) 1153 1154 // ../../../../runtime/type.go:/structType 1155 // for security, only the exported fields. 1156 case types.TSTRUCT: 1157 fields := t.Fields().Slice() 1158 for _, t1 := range fields { 1159 writeType(t1.Type) 1160 } 1161 1162 // All non-exported struct field names within a struct 1163 // type must originate from a single package. By 1164 // identifying and recording that package within the 1165 // struct type descriptor, we can omit that 1166 // information from the field descriptors. 1167 var spkg *types.Pkg 1168 for _, f := range fields { 1169 if !types.IsExported(f.Sym.Name) { 1170 spkg = f.Sym.Pkg 1171 break 1172 } 1173 } 1174 1175 ot = dcommontype(lsym, t) 1176 ot = dgopkgpath(lsym, ot, spkg) 1177 ot = objw.SymPtr(lsym, ot, lsym, ot+3*types.PtrSize+uncommonSize(t)) 1178 ot = objw.Uintptr(lsym, ot, uint64(len(fields))) 1179 ot = objw.Uintptr(lsym, ot, uint64(len(fields))) 1180 1181 dataAdd := len(fields) * structfieldSize() 1182 ot = dextratype(lsym, ot, t, dataAdd) 1183 1184 for _, f := range fields { 1185 // ../../../../runtime/type.go:/structField 1186 ot = dnameField(lsym, ot, spkg, f) 1187 ot = objw.SymPtr(lsym, ot, writeType(f.Type), 0) 1188 offsetAnon := uint64(f.Offset) << 1 1189 if offsetAnon>>1 != uint64(f.Offset) { 1190 base.Fatalf("%v: bad field offset for %s", t, f.Sym.Name) 1191 } 1192 if f.Embedded != 0 { 1193 offsetAnon |= 1 1194 } 1195 ot = objw.Uintptr(lsym, ot, offsetAnon) 1196 } 1197 } 1198 1199 ot = dextratypeData(lsym, ot, t) 1200 objw.Global(lsym, int32(ot), int16(obj.DUPOK|obj.RODATA)) 1201 // Note: DUPOK is required to ensure that we don't end up with more 1202 // than one type descriptor for a given type. 1203 1204 // The linker will leave a table of all the typelinks for 1205 // types in the binary, so the runtime can find them. 1206 // 1207 // When buildmode=shared, all types are in typelinks so the 1208 // runtime can deduplicate type pointers. 1209 keep := base.Ctxt.Flag_dynlink 1210 if !keep && t.Sym() == nil { 1211 // For an unnamed type, we only need the link if the type can 1212 // be created at run time by reflect.PtrTo and similar 1213 // functions. If the type exists in the program, those 1214 // functions must return the existing type structure rather 1215 // than creating a new one. 1216 switch t.Kind() { 1217 case types.TPTR, types.TARRAY, types.TCHAN, types.TFUNC, types.TMAP, types.TSLICE, types.TSTRUCT: 1218 keep = true 1219 } 1220 } 1221 // Do not put Noalg types in typelinks. See issue #22605. 1222 if types.TypeHasNoAlg(t) { 1223 keep = false 1224 } 1225 lsym.Set(obj.AttrMakeTypelink, keep) 1226 1227 return lsym 1228} 1229 1230// InterfaceMethodOffset returns the offset of the i-th method in the interface 1231// type descriptor, ityp. 1232func InterfaceMethodOffset(ityp *types.Type, i int64) int64 { 1233 // interface type descriptor layout is struct { 1234 // _type // commonSize 1235 // pkgpath // 1 word 1236 // []imethod // 3 words (pointing to [...]imethod below) 1237 // uncommontype // uncommonSize 1238 // [...]imethod 1239 // } 1240 // The size of imethod is 8. 1241 return int64(commonSize()+4*types.PtrSize+uncommonSize(ityp)) + i*8 1242} 1243 1244// NeedRuntimeType ensures that a runtime type descriptor is emitted for t. 1245func NeedRuntimeType(t *types.Type) { 1246 if t.HasTParam() { 1247 // Generic types don't really exist at run-time and have no runtime 1248 // type descriptor. But we do write out shape types. 1249 return 1250 } 1251 if _, ok := signatset[t]; !ok { 1252 signatset[t] = struct{}{} 1253 signatslice = append(signatslice, typeAndStr{t: t, short: types.TypeSymName(t), regular: t.String()}) 1254 } 1255} 1256 1257func WriteRuntimeTypes() { 1258 // Process signatslice. Use a loop, as writeType adds 1259 // entries to signatslice while it is being processed. 1260 for len(signatslice) > 0 { 1261 signats := signatslice 1262 // Sort for reproducible builds. 1263 sort.Sort(typesByString(signats)) 1264 for _, ts := range signats { 1265 t := ts.t 1266 writeType(t) 1267 if t.Sym() != nil { 1268 writeType(types.NewPtr(t)) 1269 } 1270 } 1271 signatslice = signatslice[len(signats):] 1272 } 1273 1274 // Emit GC data symbols. 1275 gcsyms := make([]typeAndStr, 0, len(gcsymset)) 1276 for t := range gcsymset { 1277 gcsyms = append(gcsyms, typeAndStr{t: t, short: types.TypeSymName(t), regular: t.String()}) 1278 } 1279 sort.Sort(typesByString(gcsyms)) 1280 for _, ts := range gcsyms { 1281 dgcsym(ts.t, true) 1282 } 1283} 1284 1285// writeITab writes the itab for concrete type typ implementing interface iface. If 1286// allowNonImplement is true, allow the case where typ does not implement iface, and just 1287// create a dummy itab with zeroed-out method entries. 1288func writeITab(lsym *obj.LSym, typ, iface *types.Type, allowNonImplement bool) { 1289 // TODO(mdempsky): Fix methodWrapper, geneq, and genhash (and maybe 1290 // others) to stop clobbering these. 1291 oldpos, oldfn := base.Pos, ir.CurFunc 1292 defer func() { base.Pos, ir.CurFunc = oldpos, oldfn }() 1293 1294 if typ == nil || (typ.IsPtr() && typ.Elem() == nil) || typ.IsUntyped() || iface == nil || !iface.IsInterface() || iface.IsEmptyInterface() { 1295 base.Fatalf("writeITab(%v, %v)", typ, iface) 1296 } 1297 1298 sigs := iface.AllMethods().Slice() 1299 entries := make([]*obj.LSym, 0, len(sigs)) 1300 1301 // both sigs and methods are sorted by name, 1302 // so we can find the intersection in a single pass 1303 for _, m := range methods(typ) { 1304 if m.name == sigs[0].Sym { 1305 entries = append(entries, m.isym) 1306 if m.isym == nil { 1307 panic("NO ISYM") 1308 } 1309 sigs = sigs[1:] 1310 if len(sigs) == 0 { 1311 break 1312 } 1313 } 1314 } 1315 completeItab := len(sigs) == 0 1316 if !allowNonImplement && !completeItab { 1317 base.Fatalf("incomplete itab") 1318 } 1319 1320 // dump empty itab symbol into i.sym 1321 // type itab struct { 1322 // inter *interfacetype 1323 // _type *_type 1324 // hash uint32 1325 // _ [4]byte 1326 // fun [1]uintptr // variable sized 1327 // } 1328 o := objw.SymPtr(lsym, 0, writeType(iface), 0) 1329 o = objw.SymPtr(lsym, o, writeType(typ), 0) 1330 o = objw.Uint32(lsym, o, types.TypeHash(typ)) // copy of type hash 1331 o += 4 // skip unused field 1332 for _, fn := range entries { 1333 if !completeItab { 1334 // If typ doesn't implement iface, make method entries be zero. 1335 o = objw.Uintptr(lsym, o, 0) 1336 } else { 1337 o = objw.SymPtrWeak(lsym, o, fn, 0) // method pointer for each method 1338 } 1339 } 1340 // Nothing writes static itabs, so they are read only. 1341 objw.Global(lsym, int32(o), int16(obj.DUPOK|obj.RODATA)) 1342 lsym.Set(obj.AttrContentAddressable, true) 1343} 1344 1345func WriteTabs() { 1346 // process ptabs 1347 if types.LocalPkg.Name == "main" && len(ptabs) > 0 { 1348 ot := 0 1349 s := base.Ctxt.Lookup("go.plugin.tabs") 1350 for _, p := range ptabs { 1351 // Dump ptab symbol into go.pluginsym package. 1352 // 1353 // type ptab struct { 1354 // name nameOff 1355 // typ typeOff // pointer to symbol 1356 // } 1357 nsym := dname(p.Sym().Name, "", nil, true) 1358 t := p.Type() 1359 if p.Class != ir.PFUNC { 1360 t = types.NewPtr(t) 1361 } 1362 tsym := writeType(t) 1363 ot = objw.SymPtrOff(s, ot, nsym) 1364 ot = objw.SymPtrOff(s, ot, tsym) 1365 // Plugin exports symbols as interfaces. Mark their types 1366 // as UsedInIface. 1367 tsym.Set(obj.AttrUsedInIface, true) 1368 } 1369 objw.Global(s, int32(ot), int16(obj.RODATA)) 1370 1371 ot = 0 1372 s = base.Ctxt.Lookup("go.plugin.exports") 1373 for _, p := range ptabs { 1374 ot = objw.SymPtr(s, ot, p.Linksym(), 0) 1375 } 1376 objw.Global(s, int32(ot), int16(obj.RODATA)) 1377 } 1378} 1379 1380func WriteImportStrings() { 1381 // generate import strings for imported packages 1382 for _, p := range types.ImportedPkgList() { 1383 dimportpath(p) 1384 } 1385} 1386 1387func WriteBasicTypes() { 1388 // do basic types if compiling package runtime. 1389 // they have to be in at least one package, 1390 // and runtime is always loaded implicitly, 1391 // so this is as good as any. 1392 // another possible choice would be package main, 1393 // but using runtime means fewer copies in object files. 1394 if base.Ctxt.Pkgpath == "runtime" { 1395 for i := types.Kind(1); i <= types.TBOOL; i++ { 1396 writeType(types.NewPtr(types.Types[i])) 1397 } 1398 writeType(types.NewPtr(types.Types[types.TSTRING])) 1399 writeType(types.NewPtr(types.Types[types.TUNSAFEPTR])) 1400 if base.Flag.G > 0 { 1401 writeType(types.AnyType) 1402 } 1403 1404 // emit type structs for error and func(error) string. 1405 // The latter is the type of an auto-generated wrapper. 1406 writeType(types.NewPtr(types.ErrorType)) 1407 1408 writeType(types.NewSignature(types.NoPkg, nil, nil, []*types.Field{ 1409 types.NewField(base.Pos, nil, types.ErrorType), 1410 }, []*types.Field{ 1411 types.NewField(base.Pos, nil, types.Types[types.TSTRING]), 1412 })) 1413 1414 // add paths for runtime and main, which 6l imports implicitly. 1415 dimportpath(ir.Pkgs.Runtime) 1416 1417 if base.Flag.Race { 1418 dimportpath(types.NewPkg("runtime/race", "")) 1419 } 1420 if base.Flag.MSan { 1421 dimportpath(types.NewPkg("runtime/msan", "")) 1422 } 1423 if base.Flag.ASan { 1424 dimportpath(types.NewPkg("runtime/asan", "")) 1425 } 1426 1427 dimportpath(types.NewPkg("main", "")) 1428 } 1429} 1430 1431type typeAndStr struct { 1432 t *types.Type 1433 short string // "short" here means NameString 1434 regular string 1435} 1436 1437type typesByString []typeAndStr 1438 1439func (a typesByString) Len() int { return len(a) } 1440func (a typesByString) Less(i, j int) bool { 1441 if a[i].short != a[j].short { 1442 return a[i].short < a[j].short 1443 } 1444 // When the only difference between the types is whether 1445 // they refer to byte or uint8, such as **byte vs **uint8, 1446 // the types' NameStrings can be identical. 1447 // To preserve deterministic sort ordering, sort these by String(). 1448 // 1449 // TODO(mdempsky): This all seems suspect. Using LinkString would 1450 // avoid naming collisions, and there shouldn't be a reason to care 1451 // about "byte" vs "uint8": they share the same runtime type 1452 // descriptor anyway. 1453 if a[i].regular != a[j].regular { 1454 return a[i].regular < a[j].regular 1455 } 1456 // Identical anonymous interfaces defined in different locations 1457 // will be equal for the above checks, but different in DWARF output. 1458 // Sort by source position to ensure deterministic order. 1459 // See issues 27013 and 30202. 1460 if a[i].t.Kind() == types.TINTER && a[i].t.AllMethods().Len() > 0 { 1461 return a[i].t.AllMethods().Index(0).Pos.Before(a[j].t.AllMethods().Index(0).Pos) 1462 } 1463 return false 1464} 1465func (a typesByString) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 1466 1467// maxPtrmaskBytes is the maximum length of a GC ptrmask bitmap, 1468// which holds 1-bit entries describing where pointers are in a given type. 1469// Above this length, the GC information is recorded as a GC program, 1470// which can express repetition compactly. In either form, the 1471// information is used by the runtime to initialize the heap bitmap, 1472// and for large types (like 128 or more words), they are roughly the 1473// same speed. GC programs are never much larger and often more 1474// compact. (If large arrays are involved, they can be arbitrarily 1475// more compact.) 1476// 1477// The cutoff must be large enough that any allocation large enough to 1478// use a GC program is large enough that it does not share heap bitmap 1479// bytes with any other objects, allowing the GC program execution to 1480// assume an aligned start and not use atomic operations. In the current 1481// runtime, this means all malloc size classes larger than the cutoff must 1482// be multiples of four words. On 32-bit systems that's 16 bytes, and 1483// all size classes >= 16 bytes are 16-byte aligned, so no real constraint. 1484// On 64-bit systems, that's 32 bytes, and 32-byte alignment is guaranteed 1485// for size classes >= 256 bytes. On a 64-bit system, 256 bytes allocated 1486// is 32 pointers, the bits for which fit in 4 bytes. So maxPtrmaskBytes 1487// must be >= 4. 1488// 1489// We used to use 16 because the GC programs do have some constant overhead 1490// to get started, and processing 128 pointers seems to be enough to 1491// amortize that overhead well. 1492// 1493// To make sure that the runtime's chansend can call typeBitsBulkBarrier, 1494// we raised the limit to 2048, so that even 32-bit systems are guaranteed to 1495// use bitmaps for objects up to 64 kB in size. 1496// 1497// Also known to reflect/type.go. 1498// 1499const maxPtrmaskBytes = 2048 1500 1501// GCSym returns a data symbol containing GC information for type t, along 1502// with a boolean reporting whether the UseGCProg bit should be set in the 1503// type kind, and the ptrdata field to record in the reflect type information. 1504// GCSym may be called in concurrent backend, so it does not emit the symbol 1505// content. 1506func GCSym(t *types.Type) (lsym *obj.LSym, useGCProg bool, ptrdata int64) { 1507 // Record that we need to emit the GC symbol. 1508 gcsymmu.Lock() 1509 if _, ok := gcsymset[t]; !ok { 1510 gcsymset[t] = struct{}{} 1511 } 1512 gcsymmu.Unlock() 1513 1514 return dgcsym(t, false) 1515} 1516 1517// dgcsym returns a data symbol containing GC information for type t, along 1518// with a boolean reporting whether the UseGCProg bit should be set in the 1519// type kind, and the ptrdata field to record in the reflect type information. 1520// When write is true, it writes the symbol data. 1521func dgcsym(t *types.Type, write bool) (lsym *obj.LSym, useGCProg bool, ptrdata int64) { 1522 ptrdata = types.PtrDataSize(t) 1523 if ptrdata/int64(types.PtrSize) <= maxPtrmaskBytes*8 { 1524 lsym = dgcptrmask(t, write) 1525 return 1526 } 1527 1528 useGCProg = true 1529 lsym, ptrdata = dgcprog(t, write) 1530 return 1531} 1532 1533// dgcptrmask emits and returns the symbol containing a pointer mask for type t. 1534func dgcptrmask(t *types.Type, write bool) *obj.LSym { 1535 ptrmask := make([]byte, (types.PtrDataSize(t)/int64(types.PtrSize)+7)/8) 1536 fillptrmask(t, ptrmask) 1537 p := fmt.Sprintf("runtime.gcbits.%x", ptrmask) 1538 1539 lsym := base.Ctxt.Lookup(p) 1540 if write && !lsym.OnList() { 1541 for i, x := range ptrmask { 1542 objw.Uint8(lsym, i, x) 1543 } 1544 objw.Global(lsym, int32(len(ptrmask)), obj.DUPOK|obj.RODATA|obj.LOCAL) 1545 lsym.Set(obj.AttrContentAddressable, true) 1546 } 1547 return lsym 1548} 1549 1550// fillptrmask fills in ptrmask with 1s corresponding to the 1551// word offsets in t that hold pointers. 1552// ptrmask is assumed to fit at least types.PtrDataSize(t)/PtrSize bits. 1553func fillptrmask(t *types.Type, ptrmask []byte) { 1554 for i := range ptrmask { 1555 ptrmask[i] = 0 1556 } 1557 if !t.HasPointers() { 1558 return 1559 } 1560 1561 vec := bitvec.New(8 * int32(len(ptrmask))) 1562 typebits.Set(t, 0, vec) 1563 1564 nptr := types.PtrDataSize(t) / int64(types.PtrSize) 1565 for i := int64(0); i < nptr; i++ { 1566 if vec.Get(int32(i)) { 1567 ptrmask[i/8] |= 1 << (uint(i) % 8) 1568 } 1569 } 1570} 1571 1572// dgcprog emits and returns the symbol containing a GC program for type t 1573// along with the size of the data described by the program (in the range 1574// [types.PtrDataSize(t), t.Width]). 1575// In practice, the size is types.PtrDataSize(t) except for non-trivial arrays. 1576// For non-trivial arrays, the program describes the full t.Width size. 1577func dgcprog(t *types.Type, write bool) (*obj.LSym, int64) { 1578 types.CalcSize(t) 1579 if t.Size() == types.BADWIDTH { 1580 base.Fatalf("dgcprog: %v badwidth", t) 1581 } 1582 lsym := TypeLinksymPrefix(".gcprog", t) 1583 var p gcProg 1584 p.init(lsym, write) 1585 p.emit(t, 0) 1586 offset := p.w.BitIndex() * int64(types.PtrSize) 1587 p.end() 1588 if ptrdata := types.PtrDataSize(t); offset < ptrdata || offset > t.Size() { 1589 base.Fatalf("dgcprog: %v: offset=%d but ptrdata=%d size=%d", t, offset, ptrdata, t.Size()) 1590 } 1591 return lsym, offset 1592} 1593 1594type gcProg struct { 1595 lsym *obj.LSym 1596 symoff int 1597 w gcprog.Writer 1598 write bool 1599} 1600 1601func (p *gcProg) init(lsym *obj.LSym, write bool) { 1602 p.lsym = lsym 1603 p.write = write && !lsym.OnList() 1604 p.symoff = 4 // first 4 bytes hold program length 1605 if !write { 1606 p.w.Init(func(byte) {}) 1607 return 1608 } 1609 p.w.Init(p.writeByte) 1610 if base.Debug.GCProg > 0 { 1611 fmt.Fprintf(os.Stderr, "compile: start GCProg for %v\n", lsym) 1612 p.w.Debug(os.Stderr) 1613 } 1614} 1615 1616func (p *gcProg) writeByte(x byte) { 1617 p.symoff = objw.Uint8(p.lsym, p.symoff, x) 1618} 1619 1620func (p *gcProg) end() { 1621 p.w.End() 1622 if !p.write { 1623 return 1624 } 1625 objw.Uint32(p.lsym, 0, uint32(p.symoff-4)) 1626 objw.Global(p.lsym, int32(p.symoff), obj.DUPOK|obj.RODATA|obj.LOCAL) 1627 p.lsym.Set(obj.AttrContentAddressable, true) 1628 if base.Debug.GCProg > 0 { 1629 fmt.Fprintf(os.Stderr, "compile: end GCProg for %v\n", p.lsym) 1630 } 1631} 1632 1633func (p *gcProg) emit(t *types.Type, offset int64) { 1634 types.CalcSize(t) 1635 if !t.HasPointers() { 1636 return 1637 } 1638 if t.Size() == int64(types.PtrSize) { 1639 p.w.Ptr(offset / int64(types.PtrSize)) 1640 return 1641 } 1642 switch t.Kind() { 1643 default: 1644 base.Fatalf("gcProg.emit: unexpected type %v", t) 1645 1646 case types.TSTRING: 1647 p.w.Ptr(offset / int64(types.PtrSize)) 1648 1649 case types.TINTER: 1650 // Note: the first word isn't a pointer. See comment in typebits.Set 1651 p.w.Ptr(offset/int64(types.PtrSize) + 1) 1652 1653 case types.TSLICE: 1654 p.w.Ptr(offset / int64(types.PtrSize)) 1655 1656 case types.TARRAY: 1657 if t.NumElem() == 0 { 1658 // should have been handled by haspointers check above 1659 base.Fatalf("gcProg.emit: empty array") 1660 } 1661 1662 // Flatten array-of-array-of-array to just a big array by multiplying counts. 1663 count := t.NumElem() 1664 elem := t.Elem() 1665 for elem.IsArray() { 1666 count *= elem.NumElem() 1667 elem = elem.Elem() 1668 } 1669 1670 if !p.w.ShouldRepeat(elem.Size()/int64(types.PtrSize), count) { 1671 // Cheaper to just emit the bits. 1672 for i := int64(0); i < count; i++ { 1673 p.emit(elem, offset+i*elem.Size()) 1674 } 1675 return 1676 } 1677 p.emit(elem, offset) 1678 p.w.ZeroUntil((offset + elem.Size()) / int64(types.PtrSize)) 1679 p.w.Repeat(elem.Size()/int64(types.PtrSize), count-1) 1680 1681 case types.TSTRUCT: 1682 for _, t1 := range t.Fields().Slice() { 1683 p.emit(t1.Type, offset+t1.Offset) 1684 } 1685 } 1686} 1687 1688// ZeroAddr returns the address of a symbol with at least 1689// size bytes of zeros. 1690func ZeroAddr(size int64) ir.Node { 1691 if size >= 1<<31 { 1692 base.Fatalf("map elem too big %d", size) 1693 } 1694 if ZeroSize < size { 1695 ZeroSize = size 1696 } 1697 lsym := base.PkgLinksym("go.map", "zero", obj.ABI0) 1698 x := ir.NewLinksymExpr(base.Pos, lsym, types.Types[types.TUINT8]) 1699 return typecheck.Expr(typecheck.NodAddr(x)) 1700} 1701 1702func CollectPTabs() { 1703 if !base.Ctxt.Flag_dynlink || types.LocalPkg.Name != "main" { 1704 return 1705 } 1706 for _, exportn := range typecheck.Target.Exports { 1707 s := exportn.Sym() 1708 nn := ir.AsNode(s.Def) 1709 if nn == nil { 1710 continue 1711 } 1712 if nn.Op() != ir.ONAME { 1713 continue 1714 } 1715 n := nn.(*ir.Name) 1716 if !types.IsExported(s.Name) { 1717 continue 1718 } 1719 if s.Pkg.Name != "main" { 1720 continue 1721 } 1722 ptabs = append(ptabs, n) 1723 } 1724} 1725 1726// NeedEmit reports whether typ is a type that we need to emit code 1727// for (e.g., runtime type descriptors, method wrappers). 1728func NeedEmit(typ *types.Type) bool { 1729 // TODO(mdempsky): Export data should keep track of which anonymous 1730 // and instantiated types were emitted, so at least downstream 1731 // packages can skip re-emitting them. 1732 // 1733 // Perhaps we can just generalize the linker-symbol indexing to 1734 // track the index of arbitrary types, not just defined types, and 1735 // use its presence to detect this. The same idea would work for 1736 // instantiated generic functions too. 1737 1738 switch sym := typ.Sym(); { 1739 case sym == nil: 1740 // Anonymous type; possibly never seen before or ever again. 1741 // Need to emit to be safe (however, see TODO above). 1742 return true 1743 1744 case sym.Pkg == types.LocalPkg: 1745 // Local defined type; our responsibility. 1746 return true 1747 1748 case base.Ctxt.Pkgpath == "runtime" && (sym.Pkg == types.BuiltinPkg || sym.Pkg == types.UnsafePkg): 1749 // Package runtime is responsible for including code for builtin 1750 // types (predeclared and package unsafe). 1751 return true 1752 1753 case typ.IsFullyInstantiated(): 1754 // Instantiated type; possibly instantiated with unique type arguments. 1755 // Need to emit to be safe (however, see TODO above). 1756 return true 1757 1758 case typ.HasShape(): 1759 // Shape type; need to emit even though it lives in the .shape package. 1760 // TODO: make sure the linker deduplicates them (see dupok in writeType above). 1761 return true 1762 1763 default: 1764 // Should have been emitted by an imported package. 1765 return false 1766 } 1767} 1768 1769// Generate a wrapper function to convert from 1770// a receiver of type T to a receiver of type U. 1771// That is, 1772// 1773// func (t T) M() { 1774// ... 1775// } 1776// 1777// already exists; this function generates 1778// 1779// func (u U) M() { 1780// u.M() 1781// } 1782// 1783// where the types T and U are such that u.M() is valid 1784// and calls the T.M method. 1785// The resulting function is for use in method tables. 1786// 1787// rcvr - U 1788// method - M func (t T)(), a TFIELD type struct 1789// 1790// Also wraps methods on instantiated generic types for use in itab entries. 1791// For an instantiated generic type G[int], we generate wrappers like: 1792// G[int] pointer shaped: 1793// func (x G[int]) f(arg) { 1794// .inst.G[int].f(dictionary, x, arg) 1795// } 1796// G[int] not pointer shaped: 1797// func (x *G[int]) f(arg) { 1798// .inst.G[int].f(dictionary, *x, arg) 1799// } 1800// These wrappers are always fully stenciled. 1801func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSym { 1802 orig := rcvr 1803 if forItab && !types.IsDirectIface(rcvr) { 1804 rcvr = rcvr.PtrTo() 1805 } 1806 1807 generic := false 1808 // We don't need a dictionary if we are reaching a method (possibly via an 1809 // embedded field) which is an interface method. 1810 if !types.IsInterfaceMethod(method.Type) { 1811 rcvr1 := deref(rcvr) 1812 if len(rcvr1.RParams()) > 0 { 1813 // If rcvr has rparams, remember method as generic, which 1814 // means we need to add a dictionary to the wrapper. 1815 generic = true 1816 if rcvr.HasShape() { 1817 base.Fatalf("method on type instantiated with shapes, rcvr:%+v", rcvr) 1818 } 1819 } 1820 } 1821 1822 newnam := ir.MethodSym(rcvr, method.Sym) 1823 lsym := newnam.Linksym() 1824 if newnam.Siggen() { 1825 return lsym 1826 } 1827 newnam.SetSiggen(true) 1828 1829 // Except in quirks mode, unified IR creates its own wrappers. 1830 if base.Debug.Unified != 0 && base.Debug.UnifiedQuirks == 0 { 1831 return lsym 1832 } 1833 1834 methodrcvr := method.Type.Recv().Type 1835 // For generic methods, we need to generate the wrapper even if the receiver 1836 // types are identical, because we want to add the dictionary. 1837 if !generic && types.Identical(rcvr, methodrcvr) { 1838 return lsym 1839 } 1840 1841 if !NeedEmit(rcvr) || rcvr.IsPtr() && !NeedEmit(rcvr.Elem()) { 1842 return lsym 1843 } 1844 1845 base.Pos = base.AutogeneratedPos 1846 typecheck.DeclContext = ir.PEXTERN 1847 1848 tfn := ir.NewFuncType(base.Pos, 1849 ir.NewField(base.Pos, typecheck.Lookup(".this"), nil, rcvr), 1850 typecheck.NewFuncParams(method.Type.Params(), true), 1851 typecheck.NewFuncParams(method.Type.Results(), false)) 1852 1853 // TODO(austin): SelectorExpr may have created one or more 1854 // ir.Names for these already with a nil Func field. We should 1855 // consolidate these and always attach a Func to the Name. 1856 fn := typecheck.DeclFunc(newnam, tfn) 1857 fn.SetDupok(true) 1858 1859 nthis := ir.AsNode(tfn.Type().Recv().Nname) 1860 1861 indirect := rcvr.IsPtr() && rcvr.Elem() == methodrcvr 1862 1863 // generate nil pointer check for better error 1864 if indirect { 1865 // generating wrapper from *T to T. 1866 n := ir.NewIfStmt(base.Pos, nil, nil, nil) 1867 n.Cond = ir.NewBinaryExpr(base.Pos, ir.OEQ, nthis, typecheck.NodNil()) 1868 call := ir.NewCallExpr(base.Pos, ir.OCALL, typecheck.LookupRuntime("panicwrap"), nil) 1869 n.Body = []ir.Node{call} 1870 fn.Body.Append(n) 1871 } 1872 1873 dot := typecheck.AddImplicitDots(ir.NewSelectorExpr(base.Pos, ir.OXDOT, nthis, method.Sym)) 1874 // generate call 1875 // It's not possible to use a tail call when dynamic linking on ppc64le. The 1876 // bad scenario is when a local call is made to the wrapper: the wrapper will 1877 // call the implementation, which might be in a different module and so set 1878 // the TOC to the appropriate value for that module. But if it returns 1879 // directly to the wrapper's caller, nothing will reset it to the correct 1880 // value for that function. 1881 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 { 1882 call := ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil) 1883 call.Args = ir.ParamNames(tfn.Type()) 1884 call.IsDDD = tfn.Type().IsVariadic() 1885 fn.Body.Append(ir.NewTailCallStmt(base.Pos, call)) 1886 } else { 1887 fn.SetWrapper(true) // ignore frame for panic+recover matching 1888 var call *ir.CallExpr 1889 1890 if generic && dot.X != nthis { 1891 // If there is embedding involved, then we should do the 1892 // normal non-generic embedding wrapper below, which calls 1893 // the wrapper for the real receiver type using dot as an 1894 // argument. There is no need for generic processing (adding 1895 // a dictionary) for this wrapper. 1896 generic = false 1897 } 1898 1899 if generic { 1900 targs := deref(rcvr).RParams() 1901 // The wrapper for an auto-generated pointer/non-pointer 1902 // receiver method should share the same dictionary as the 1903 // corresponding original (user-written) method. 1904 baseOrig := orig 1905 if baseOrig.IsPtr() && !methodrcvr.IsPtr() { 1906 baseOrig = baseOrig.Elem() 1907 } else if !baseOrig.IsPtr() && methodrcvr.IsPtr() { 1908 baseOrig = types.NewPtr(baseOrig) 1909 } 1910 args := []ir.Node{getDictionary(ir.MethodSym(baseOrig, method.Sym), targs)} 1911 if indirect { 1912 args = append(args, ir.NewStarExpr(base.Pos, dot.X)) 1913 } else if methodrcvr.IsPtr() && methodrcvr.Elem() == dot.X.Type() { 1914 // Case where method call is via a non-pointer 1915 // embedded field with a pointer method. 1916 args = append(args, typecheck.NodAddrAt(base.Pos, dot.X)) 1917 } else { 1918 args = append(args, dot.X) 1919 } 1920 args = append(args, ir.ParamNames(tfn.Type())...) 1921 1922 // Target method uses shaped names. 1923 targs2 := make([]*types.Type, len(targs)) 1924 for i, t := range targs { 1925 targs2[i] = typecheck.Shapify(t, i) 1926 } 1927 targs = targs2 1928 1929 sym := typecheck.MakeFuncInstSym(ir.MethodSym(methodrcvr, method.Sym), targs, false, true) 1930 if sym.Def == nil { 1931 // Currently we make sure that we have all the instantiations 1932 // we need by generating them all in ../noder/stencil.go:instantiateMethods 1933 // TODO: maybe there's a better, more incremental way to generate 1934 // only the instantiations we need? 1935 base.Fatalf("instantiation %s not found", sym.Name) 1936 } 1937 target := ir.AsNode(sym.Def) 1938 call = ir.NewCallExpr(base.Pos, ir.OCALL, target, args) 1939 // Fill-in the generic method node that was not filled in 1940 // in instantiateMethod. 1941 method.Nname = fn.Nname 1942 } else { 1943 call = ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil) 1944 call.Args = ir.ParamNames(tfn.Type()) 1945 } 1946 call.IsDDD = tfn.Type().IsVariadic() 1947 if method.Type.NumResults() > 0 { 1948 ret := ir.NewReturnStmt(base.Pos, nil) 1949 ret.Results = []ir.Node{call} 1950 fn.Body.Append(ret) 1951 } else { 1952 fn.Body.Append(call) 1953 } 1954 } 1955 1956 typecheck.FinishFuncBody() 1957 if base.Debug.DclStack != 0 { 1958 types.CheckDclstack() 1959 } 1960 1961 typecheck.Func(fn) 1962 ir.CurFunc = fn 1963 typecheck.Stmts(fn.Body) 1964 1965 if AfterGlobalEscapeAnalysis { 1966 inline.InlineCalls(fn) 1967 escape.Batch([]*ir.Func{fn}, false) 1968 } 1969 1970 ir.CurFunc = nil 1971 typecheck.Target.Decls = append(typecheck.Target.Decls, fn) 1972 1973 return lsym 1974} 1975 1976// AfterGlobalEscapeAnalysis tracks whether package gc has already 1977// performed the main, global escape analysis pass. If so, 1978// methodWrapper takes responsibility for escape analyzing any 1979// generated wrappers. 1980var AfterGlobalEscapeAnalysis bool 1981 1982var ZeroSize int64 1983 1984// MarkTypeUsedInInterface marks that type t is converted to an interface. 1985// This information is used in the linker in dead method elimination. 1986func MarkTypeUsedInInterface(t *types.Type, from *obj.LSym) { 1987 if t.HasShape() { 1988 // Shape types shouldn't be put in interfaces, so we shouldn't ever get here. 1989 base.Fatalf("shape types have no methods %+v", t) 1990 } 1991 tsym := TypeLinksym(t) 1992 // Emit a marker relocation. The linker will know the type is converted 1993 // to an interface if "from" is reachable. 1994 r := obj.Addrel(from) 1995 r.Sym = tsym 1996 r.Type = objabi.R_USEIFACE 1997} 1998 1999// MarkUsedIfaceMethod marks that an interface method is used in the current 2000// function. n is OCALLINTER node. 2001func MarkUsedIfaceMethod(n *ir.CallExpr) { 2002 // skip unnamed functions (func _()) 2003 if ir.CurFunc.LSym == nil { 2004 return 2005 } 2006 dot := n.X.(*ir.SelectorExpr) 2007 ityp := dot.X.Type() 2008 if ityp.HasShape() { 2009 // Here we're calling a method on a generic interface. Something like: 2010 // 2011 // type I[T any] interface { foo() T } 2012 // func f[T any](x I[T]) { 2013 // ... = x.foo() 2014 // } 2015 // f[int](...) 2016 // f[string](...) 2017 // 2018 // In this case, in f we're calling foo on a generic interface. 2019 // Which method could that be? Normally we could match the method 2020 // both by name and by type. But in this case we don't really know 2021 // the type of the method we're calling. It could be func()int 2022 // or func()string. So we match on just the function name, instead 2023 // of both the name and the type used for the non-generic case below. 2024 // TODO: instantiations at least know the shape of the instantiated 2025 // type, and the linker could do more complicated matching using 2026 // some sort of fuzzy shape matching. For now, only use the name 2027 // of the method for matching. 2028 r := obj.Addrel(ir.CurFunc.LSym) 2029 // We use a separate symbol just to tell the linker the method name. 2030 // (The symbol itself is not needed in the final binary.) 2031 r.Sym = staticdata.StringSym(src.NoXPos, dot.Sel.Name) 2032 r.Type = objabi.R_USEGENERICIFACEMETHOD 2033 return 2034 } 2035 2036 tsym := TypeLinksym(ityp) 2037 r := obj.Addrel(ir.CurFunc.LSym) 2038 r.Sym = tsym 2039 // dot.Offset() is the method index * PtrSize (the offset of code pointer 2040 // in itab). 2041 midx := dot.Offset() / int64(types.PtrSize) 2042 r.Add = InterfaceMethodOffset(ityp, midx) 2043 r.Type = objabi.R_USEIFACEMETHOD 2044} 2045 2046// getDictionary returns the dictionary for the given named generic function 2047// or method, with the given type arguments. 2048func getDictionary(gf *types.Sym, targs []*types.Type) ir.Node { 2049 if len(targs) == 0 { 2050 base.Fatalf("%s should have type arguments", gf.Name) 2051 } 2052 for _, t := range targs { 2053 if t.HasShape() { 2054 base.Fatalf("dictionary for %s should only use concrete types: %+v", gf.Name, t) 2055 } 2056 } 2057 2058 sym := typecheck.MakeDictSym(gf, targs, true) 2059 2060 // Dictionary should already have been generated by instantiateMethods(). 2061 if lsym := sym.Linksym(); len(lsym.P) == 0 { 2062 base.Fatalf("Dictionary should have already been generated: %s.%s", sym.Pkg.Path, sym.Name) 2063 } 2064 2065 // Make (or reuse) a node referencing the dictionary symbol. 2066 var n *ir.Name 2067 if sym.Def != nil { 2068 n = sym.Def.(*ir.Name) 2069 } else { 2070 n = typecheck.NewName(sym) 2071 n.SetType(types.Types[types.TUINTPTR]) // should probably be [...]uintptr, but doesn't really matter 2072 n.SetTypecheck(1) 2073 n.Class = ir.PEXTERN 2074 sym.Def = n 2075 } 2076 2077 // Return the address of the dictionary. 2078 np := typecheck.NodAddr(n) 2079 // Note: treat dictionary pointers as uintptrs, so they aren't pointers 2080 // with respect to GC. That saves on stack scanning work, write barriers, etc. 2081 // We can get away with it because dictionaries are global variables. 2082 np.SetType(types.Types[types.TUINTPTR]) 2083 np.SetTypecheck(1) 2084 return np 2085} 2086 2087func deref(t *types.Type) *types.Type { 2088 if t.IsPtr() { 2089 return t.Elem() 2090 } 2091 return t 2092} 2093