github.com/bir3/gocompiler@v0.3.205/src/cmd/compile/internal/noder/writer.go (about) 1 // Copyright 2021 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 noder 6 7 import ( 8 "fmt" 9 "github.com/bir3/gocompiler/src/internal/pkgbits" 10 11 "github.com/bir3/gocompiler/src/cmd/compile/internal/base" 12 "github.com/bir3/gocompiler/src/cmd/compile/internal/ir" 13 "github.com/bir3/gocompiler/src/cmd/compile/internal/syntax" 14 "github.com/bir3/gocompiler/src/cmd/compile/internal/types" 15 "github.com/bir3/gocompiler/src/cmd/compile/internal/types2" 16 ) 17 18 // This file implements the Unified IR package writer and defines the 19 // Unified IR export data format. 20 // 21 // Low-level coding details (e.g., byte-encoding of individual 22 // primitive values, or handling element bitstreams and 23 // cross-references) are handled by internal/pkgbits, so here we only 24 // concern ourselves with higher-level worries like mapping Go 25 // language constructs into elements. 26 27 // There are two central types in the writing process: the "writer" 28 // type handles writing out individual elements, while the "pkgWriter" 29 // type keeps track of which elements have already been created. 30 // 31 // For each sort of "thing" (e.g., position, package, object, type) 32 // that can be written into the export data, there are generally 33 // several methods that work together: 34 // 35 // - writer.thing handles writing out a *use* of a thing, which often 36 // means writing a relocation to that thing's encoded index. 37 // 38 // - pkgWriter.thingIdx handles reserving an index for a thing, and 39 // writing out any elements needed for the thing. 40 // 41 // - writer.doThing handles writing out the *definition* of a thing, 42 // which in general is a mix of low-level coding primitives (e.g., 43 // ints and strings) or uses of other things. 44 // 45 // A design goal of Unified IR is to have a single, canonical writer 46 // implementation, but multiple reader implementations each tailored 47 // to their respective needs. For example, within cmd/compile's own 48 // backend, inlining is implemented largely by just re-running the 49 // function body reading code. 50 51 // TODO(mdempsky): Add an importer for Unified IR to the x/tools repo, 52 // and better document the file format boundary between public and 53 // private data. 54 55 // A pkgWriter constructs Unified IR export data from the results of 56 // running the types2 type checker on a Go compilation unit. 57 type pkgWriter struct { 58 pkgbits.PkgEncoder 59 60 m posMap 61 curpkg *types2.Package 62 info *types2.Info 63 64 // Indices for previously written syntax and types2 things. 65 66 posBasesIdx map[*syntax.PosBase]pkgbits.Index 67 pkgsIdx map[*types2.Package]pkgbits.Index 68 typsIdx map[types2.Type]pkgbits.Index 69 objsIdx map[types2.Object]pkgbits.Index 70 71 // Maps from types2.Objects back to their syntax.Decl. 72 73 funDecls map[*types2.Func]*syntax.FuncDecl 74 typDecls map[*types2.TypeName]typeDeclGen 75 76 // linknames maps package-scope objects to their linker symbol name, 77 // if specified by a //go:linkname directive. 78 linknames map[types2.Object]string 79 80 // cgoPragmas accumulates any //go:cgo_* pragmas that need to be 81 // passed through to cmd/link. 82 cgoPragmas [][]string 83 } 84 85 // newPkgWriter returns an initialized pkgWriter for the specified 86 // package. 87 func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info) *pkgWriter { 88 return &pkgWriter{ 89 PkgEncoder: pkgbits.NewPkgEncoder(base.Debug.SyncFrames), 90 91 m: m, 92 curpkg: pkg, 93 info: info, 94 95 pkgsIdx: make(map[*types2.Package]pkgbits.Index), 96 objsIdx: make(map[types2.Object]pkgbits.Index), 97 typsIdx: make(map[types2.Type]pkgbits.Index), 98 99 posBasesIdx: make(map[*syntax.PosBase]pkgbits.Index), 100 101 funDecls: make(map[*types2.Func]*syntax.FuncDecl), 102 typDecls: make(map[*types2.TypeName]typeDeclGen), 103 104 linknames: make(map[types2.Object]string), 105 } 106 } 107 108 // errorf reports a user error about thing p. 109 func (pw *pkgWriter) errorf(p poser, msg string, args ...interface{}) { 110 base.ErrorfAt(pw.m.pos(p), msg, args...) 111 } 112 113 // fatalf reports an internal compiler error about thing p. 114 func (pw *pkgWriter) fatalf(p poser, msg string, args ...interface{}) { 115 base.FatalfAt(pw.m.pos(p), msg, args...) 116 } 117 118 // unexpected reports a fatal error about a thing of unexpected 119 // dynamic type. 120 func (pw *pkgWriter) unexpected(what string, p poser) { 121 pw.fatalf(p, "unexpected %s: %v (%T)", what, p, p) 122 } 123 124 func (pw *pkgWriter) typeAndValue(x syntax.Expr) syntax.TypeAndValue { 125 tv := x.GetTypeInfo() 126 if tv.Type == nil { 127 pw.fatalf(x, "missing Types entry: %v", syntax.String(x)) 128 } 129 return tv 130 } 131 func (pw *pkgWriter) maybeTypeAndValue(x syntax.Expr) (syntax.TypeAndValue, bool) { 132 tv := x.GetTypeInfo() 133 return tv, tv.Type != nil 134 } 135 136 // typeOf returns the Type of the given value expression. 137 func (pw *pkgWriter) typeOf(expr syntax.Expr) types2.Type { 138 tv := pw.typeAndValue(expr) 139 if !tv.IsValue() { 140 pw.fatalf(expr, "expected value: %v", syntax.String(expr)) 141 } 142 return tv.Type 143 } 144 145 // A writer provides APIs for writing out an individual element. 146 type writer struct { 147 p *pkgWriter 148 149 pkgbits.Encoder 150 151 // sig holds the signature for the current function body, if any. 152 sig *types2.Signature 153 154 // TODO(mdempsky): We should be able to prune localsIdx whenever a 155 // scope closes, and then maybe we can just use the same map for 156 // storing the TypeParams too (as their TypeName instead). 157 158 // localsIdx tracks any local variables declared within this 159 // function body. It's unused for writing out non-body things. 160 localsIdx map[*types2.Var]int 161 162 // closureVars tracks any free variables that are referenced by this 163 // function body. It's unused for writing out non-body things. 164 closureVars []posVar 165 closureVarsIdx map[*types2.Var]int // index of previously seen free variables 166 167 dict *writerDict 168 169 // derived tracks whether the type being written out references any 170 // type parameters. It's unused for writing non-type things. 171 derived bool 172 } 173 174 // A writerDict tracks types and objects that are used by a declaration. 175 type writerDict struct { 176 implicits []*types2.TypeName 177 178 // derived is a slice of type indices for computing derived types 179 // (i.e., types that depend on the declaration's type parameters). 180 derived []derivedInfo 181 182 // derivedIdx maps a Type to its corresponding index within the 183 // derived slice, if present. 184 derivedIdx map[types2.Type]pkgbits.Index 185 186 // These slices correspond to entries in the runtime dictionary. 187 typeParamMethodExprs []writerMethodExprInfo 188 subdicts []objInfo 189 rtypes []typeInfo 190 itabs []itabInfo 191 } 192 193 type itabInfo struct { 194 typ typeInfo 195 iface typeInfo 196 } 197 198 // typeParamIndex returns the index of the given type parameter within 199 // the dictionary. This may differ from typ.Index() when there are 200 // implicit type parameters due to defined types declared within a 201 // generic function or method. 202 func (dict *writerDict) typeParamIndex(typ *types2.TypeParam) int { 203 for idx, implicit := range dict.implicits { 204 if implicit.Type().(*types2.TypeParam) == typ { 205 return idx 206 } 207 } 208 209 return len(dict.implicits) + typ.Index() 210 } 211 212 // A derivedInfo represents a reference to an encoded generic Go type. 213 type derivedInfo struct { 214 idx pkgbits.Index 215 needed bool // TODO(mdempsky): Remove. 216 } 217 218 // A typeInfo represents a reference to an encoded Go type. 219 // 220 // If derived is true, then the typeInfo represents a generic Go type 221 // that contains type parameters. In this case, idx is an index into 222 // the readerDict.derived{,Types} arrays. 223 // 224 // Otherwise, the typeInfo represents a non-generic Go type, and idx 225 // is an index into the reader.typs array instead. 226 type typeInfo struct { 227 idx pkgbits.Index 228 derived bool 229 } 230 231 // An objInfo represents a reference to an encoded, instantiated (if 232 // applicable) Go object. 233 type objInfo struct { 234 idx pkgbits.Index // index for the generic function declaration 235 explicits []typeInfo // info for the type arguments 236 } 237 238 // A selectorInfo represents a reference to an encoded field or method 239 // name (i.e., objects that can only be accessed using selector 240 // expressions). 241 type selectorInfo struct { 242 pkgIdx pkgbits.Index 243 nameIdx pkgbits.Index 244 } 245 246 // anyDerived reports whether any of info's explicit type arguments 247 // are derived types. 248 func (info objInfo) anyDerived() bool { 249 for _, explicit := range info.explicits { 250 if explicit.derived { 251 return true 252 } 253 } 254 return false 255 } 256 257 // equals reports whether info and other represent the same Go object 258 // (i.e., same base object and identical type arguments, if any). 259 func (info objInfo) equals(other objInfo) bool { 260 if info.idx != other.idx { 261 return false 262 } 263 assert(len(info.explicits) == len(other.explicits)) 264 for i, targ := range info.explicits { 265 if targ != other.explicits[i] { 266 return false 267 } 268 } 269 return true 270 } 271 272 type writerMethodExprInfo struct { 273 typeParamIdx int 274 methodInfo selectorInfo 275 } 276 277 // typeParamMethodExprIdx returns the index where the given encoded 278 // method expression function pointer appears within this dictionary's 279 // type parameters method expressions section, adding it if necessary. 280 func (dict *writerDict) typeParamMethodExprIdx(typeParamIdx int, methodInfo selectorInfo) int { 281 newInfo := writerMethodExprInfo{typeParamIdx, methodInfo} 282 283 for idx, oldInfo := range dict.typeParamMethodExprs { 284 if oldInfo == newInfo { 285 return idx 286 } 287 } 288 289 idx := len(dict.typeParamMethodExprs) 290 dict.typeParamMethodExprs = append(dict.typeParamMethodExprs, newInfo) 291 return idx 292 } 293 294 // subdictIdx returns the index where the given encoded object's 295 // runtime dictionary appears within this dictionary's subdictionary 296 // section, adding it if necessary. 297 func (dict *writerDict) subdictIdx(newInfo objInfo) int { 298 for idx, oldInfo := range dict.subdicts { 299 if oldInfo.equals(newInfo) { 300 return idx 301 } 302 } 303 304 idx := len(dict.subdicts) 305 dict.subdicts = append(dict.subdicts, newInfo) 306 return idx 307 } 308 309 // rtypeIdx returns the index where the given encoded type's 310 // *runtime._type value appears within this dictionary's rtypes 311 // section, adding it if necessary. 312 func (dict *writerDict) rtypeIdx(newInfo typeInfo) int { 313 for idx, oldInfo := range dict.rtypes { 314 if oldInfo == newInfo { 315 return idx 316 } 317 } 318 319 idx := len(dict.rtypes) 320 dict.rtypes = append(dict.rtypes, newInfo) 321 return idx 322 } 323 324 // itabIdx returns the index where the given encoded type pair's 325 // *runtime.itab value appears within this dictionary's itabs section, 326 // adding it if necessary. 327 func (dict *writerDict) itabIdx(typInfo, ifaceInfo typeInfo) int { 328 newInfo := itabInfo{typInfo, ifaceInfo} 329 330 for idx, oldInfo := range dict.itabs { 331 if oldInfo == newInfo { 332 return idx 333 } 334 } 335 336 idx := len(dict.itabs) 337 dict.itabs = append(dict.itabs, newInfo) 338 return idx 339 } 340 341 func (pw *pkgWriter) newWriter(k pkgbits.RelocKind, marker pkgbits.SyncMarker) *writer { 342 return &writer{ 343 Encoder: pw.NewEncoder(k, marker), 344 p: pw, 345 } 346 } 347 348 // @@@ Positions 349 350 // pos writes the position of p into the element bitstream. 351 func (w *writer) pos(p poser) { 352 w.Sync(pkgbits.SyncPos) 353 pos := p.Pos() 354 355 // TODO(mdempsky): Track down the remaining cases here and fix them. 356 if !w.Bool(pos.IsKnown()) { 357 return 358 } 359 360 // TODO(mdempsky): Delta encoding. 361 w.posBase(pos.Base()) 362 w.Uint(pos.Line()) 363 w.Uint(pos.Col()) 364 } 365 366 // posBase writes a reference to the given PosBase into the element 367 // bitstream. 368 func (w *writer) posBase(b *syntax.PosBase) { 369 w.Reloc(pkgbits.RelocPosBase, w.p.posBaseIdx(b)) 370 } 371 372 // posBaseIdx returns the index for the given PosBase. 373 func (pw *pkgWriter) posBaseIdx(b *syntax.PosBase) pkgbits.Index { 374 if idx, ok := pw.posBasesIdx[b]; ok { 375 return idx 376 } 377 378 w := pw.newWriter(pkgbits.RelocPosBase, pkgbits.SyncPosBase) 379 w.p.posBasesIdx[b] = w.Idx 380 381 w.String(trimFilename(b)) 382 383 if !w.Bool(b.IsFileBase()) { 384 w.pos(b) 385 w.Uint(b.Line()) 386 w.Uint(b.Col()) 387 } 388 389 return w.Flush() 390 } 391 392 // @@@ Packages 393 394 // pkg writes a use of the given Package into the element bitstream. 395 func (w *writer) pkg(pkg *types2.Package) { 396 w.pkgRef(w.p.pkgIdx(pkg)) 397 } 398 399 func (w *writer) pkgRef(idx pkgbits.Index) { 400 w.Sync(pkgbits.SyncPkg) 401 w.Reloc(pkgbits.RelocPkg, idx) 402 } 403 404 // pkgIdx returns the index for the given package, adding it to the 405 // package export data if needed. 406 func (pw *pkgWriter) pkgIdx(pkg *types2.Package) pkgbits.Index { 407 if idx, ok := pw.pkgsIdx[pkg]; ok { 408 return idx 409 } 410 411 w := pw.newWriter(pkgbits.RelocPkg, pkgbits.SyncPkgDef) 412 pw.pkgsIdx[pkg] = w.Idx 413 414 // The universe and package unsafe need to be handled specially by 415 // importers anyway, so we serialize them using just their package 416 // path. This ensures that readers don't confuse them for 417 // user-defined packages. 418 switch pkg { 419 case nil: // universe 420 w.String("builtin") // same package path used by godoc 421 case types2.Unsafe: 422 w.String("unsafe") 423 default: 424 // TODO(mdempsky): Write out pkg.Path() for curpkg too. 425 var path string 426 if pkg != w.p.curpkg { 427 path = pkg.Path() 428 } 429 base.Assertf(path != "builtin" && path != "unsafe", "unexpected path for user-defined package: %q", path) 430 w.String(path) 431 w.String(pkg.Name()) 432 433 w.Len(len(pkg.Imports())) 434 for _, imp := range pkg.Imports() { 435 w.pkg(imp) 436 } 437 } 438 439 return w.Flush() 440 } 441 442 // @@@ Types 443 444 var ( 445 anyTypeName = types2.Universe.Lookup("any").(*types2.TypeName) 446 comparableTypeName = types2.Universe.Lookup("comparable").(*types2.TypeName) 447 runeTypeName = types2.Universe.Lookup("rune").(*types2.TypeName) 448 ) 449 450 // typ writes a use of the given type into the bitstream. 451 func (w *writer) typ(typ types2.Type) { 452 w.typInfo(w.p.typIdx(typ, w.dict)) 453 } 454 455 // typInfo writes a use of the given type (specified as a typeInfo 456 // instead) into the bitstream. 457 func (w *writer) typInfo(info typeInfo) { 458 w.Sync(pkgbits.SyncType) 459 if w.Bool(info.derived) { 460 w.Len(int(info.idx)) 461 w.derived = true 462 } else { 463 w.Reloc(pkgbits.RelocType, info.idx) 464 } 465 } 466 467 // typIdx returns the index where the export data description of type 468 // can be read back in. If no such index exists yet, it's created. 469 // 470 // typIdx also reports whether typ is a derived type; that is, whether 471 // its identity depends on type parameters. 472 func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo { 473 if idx, ok := pw.typsIdx[typ]; ok { 474 return typeInfo{idx: idx, derived: false} 475 } 476 if dict != nil { 477 if idx, ok := dict.derivedIdx[typ]; ok { 478 return typeInfo{idx: idx, derived: true} 479 } 480 } 481 482 w := pw.newWriter(pkgbits.RelocType, pkgbits.SyncTypeIdx) 483 w.dict = dict 484 485 switch typ := typ.(type) { 486 default: 487 base.Fatalf("unexpected type: %v (%T)", typ, typ) 488 489 case *types2.Basic: 490 switch kind := typ.Kind(); { 491 case kind == types2.Invalid: 492 base.Fatalf("unexpected types2.Invalid") 493 494 case types2.Typ[kind] == typ: 495 w.Code(pkgbits.TypeBasic) 496 w.Len(int(kind)) 497 498 default: 499 // Handle "byte" and "rune" as references to their TypeNames. 500 obj := types2.Universe.Lookup(typ.Name()) 501 assert(obj.Type() == typ) 502 503 w.Code(pkgbits.TypeNamed) 504 w.obj(obj, nil) 505 } 506 507 case *types2.Named: 508 obj, targs := splitNamed(typ) 509 510 // Defined types that are declared within a generic function (and 511 // thus have implicit type parameters) are always derived types. 512 if w.p.hasImplicitTypeParams(obj) { 513 w.derived = true 514 } 515 516 w.Code(pkgbits.TypeNamed) 517 w.obj(obj, targs) 518 519 case *types2.TypeParam: 520 w.derived = true 521 w.Code(pkgbits.TypeTypeParam) 522 w.Len(w.dict.typeParamIndex(typ)) 523 524 case *types2.Array: 525 w.Code(pkgbits.TypeArray) 526 w.Uint64(uint64(typ.Len())) 527 w.typ(typ.Elem()) 528 529 case *types2.Chan: 530 w.Code(pkgbits.TypeChan) 531 w.Len(int(typ.Dir())) 532 w.typ(typ.Elem()) 533 534 case *types2.Map: 535 w.Code(pkgbits.TypeMap) 536 w.typ(typ.Key()) 537 w.typ(typ.Elem()) 538 539 case *types2.Pointer: 540 w.Code(pkgbits.TypePointer) 541 w.typ(typ.Elem()) 542 543 case *types2.Signature: 544 base.Assertf(typ.TypeParams() == nil, "unexpected type params: %v", typ) 545 w.Code(pkgbits.TypeSignature) 546 w.signature(typ) 547 548 case *types2.Slice: 549 w.Code(pkgbits.TypeSlice) 550 w.typ(typ.Elem()) 551 552 case *types2.Struct: 553 w.Code(pkgbits.TypeStruct) 554 w.structType(typ) 555 556 case *types2.Interface: 557 // Handle "any" as reference to its TypeName. 558 if typ == anyTypeName.Type() { 559 w.Code(pkgbits.TypeNamed) 560 w.obj(anyTypeName, nil) 561 break 562 } 563 564 w.Code(pkgbits.TypeInterface) 565 w.interfaceType(typ) 566 567 case *types2.Union: 568 w.Code(pkgbits.TypeUnion) 569 w.unionType(typ) 570 } 571 572 if w.derived { 573 idx := pkgbits.Index(len(dict.derived)) 574 dict.derived = append(dict.derived, derivedInfo{idx: w.Flush()}) 575 dict.derivedIdx[typ] = idx 576 return typeInfo{idx: idx, derived: true} 577 } 578 579 pw.typsIdx[typ] = w.Idx 580 return typeInfo{idx: w.Flush(), derived: false} 581 } 582 583 func (w *writer) structType(typ *types2.Struct) { 584 w.Len(typ.NumFields()) 585 for i := 0; i < typ.NumFields(); i++ { 586 f := typ.Field(i) 587 w.pos(f) 588 w.selector(f) 589 w.typ(f.Type()) 590 w.String(typ.Tag(i)) 591 w.Bool(f.Embedded()) 592 } 593 } 594 595 func (w *writer) unionType(typ *types2.Union) { 596 w.Len(typ.Len()) 597 for i := 0; i < typ.Len(); i++ { 598 t := typ.Term(i) 599 w.Bool(t.Tilde()) 600 w.typ(t.Type()) 601 } 602 } 603 604 func (w *writer) interfaceType(typ *types2.Interface) { 605 // If typ has no embedded types but it's not a basic interface, then 606 // the natural description we write out below will fail to 607 // reconstruct it. 608 if typ.NumEmbeddeds() == 0 && !typ.IsMethodSet() { 609 // Currently, this can only happen for the underlying Interface of 610 // "comparable", which is needed to handle type declarations like 611 // "type C comparable". 612 assert(typ == comparableTypeName.Type().(*types2.Named).Underlying()) 613 614 // Export as "interface{ comparable }". 615 w.Len(0) // NumExplicitMethods 616 w.Len(1) // NumEmbeddeds 617 w.Bool(false) // IsImplicit 618 w.typ(comparableTypeName.Type()) // EmbeddedType(0) 619 return 620 } 621 622 w.Len(typ.NumExplicitMethods()) 623 w.Len(typ.NumEmbeddeds()) 624 625 if typ.NumExplicitMethods() == 0 && typ.NumEmbeddeds() == 1 { 626 w.Bool(typ.IsImplicit()) 627 } else { 628 // Implicit interfaces always have 0 explicit methods and 1 629 // embedded type, so we skip writing out the implicit flag 630 // otherwise as a space optimization. 631 assert(!typ.IsImplicit()) 632 } 633 634 for i := 0; i < typ.NumExplicitMethods(); i++ { 635 m := typ.ExplicitMethod(i) 636 sig := m.Type().(*types2.Signature) 637 assert(sig.TypeParams() == nil) 638 639 w.pos(m) 640 w.selector(m) 641 w.signature(sig) 642 } 643 644 for i := 0; i < typ.NumEmbeddeds(); i++ { 645 w.typ(typ.EmbeddedType(i)) 646 } 647 } 648 649 func (w *writer) signature(sig *types2.Signature) { 650 w.Sync(pkgbits.SyncSignature) 651 w.params(sig.Params()) 652 w.params(sig.Results()) 653 w.Bool(sig.Variadic()) 654 } 655 656 func (w *writer) params(typ *types2.Tuple) { 657 w.Sync(pkgbits.SyncParams) 658 w.Len(typ.Len()) 659 for i := 0; i < typ.Len(); i++ { 660 w.param(typ.At(i)) 661 } 662 } 663 664 func (w *writer) param(param *types2.Var) { 665 w.Sync(pkgbits.SyncParam) 666 w.pos(param) 667 w.localIdent(param) 668 w.typ(param.Type()) 669 } 670 671 // @@@ Objects 672 673 // obj writes a use of the given object into the bitstream. 674 // 675 // If obj is a generic object, then explicits are the explicit type 676 // arguments used to instantiate it (i.e., used to substitute the 677 // object's own declared type parameters). 678 func (w *writer) obj(obj types2.Object, explicits *types2.TypeList) { 679 w.objInfo(w.p.objInstIdx(obj, explicits, w.dict)) 680 } 681 682 // objInfo writes a use of the given encoded object into the 683 // bitstream. 684 func (w *writer) objInfo(info objInfo) { 685 w.Sync(pkgbits.SyncObject) 686 w.Bool(false) // TODO(mdempsky): Remove; was derived func inst. 687 w.Reloc(pkgbits.RelocObj, info.idx) 688 689 w.Len(len(info.explicits)) 690 for _, info := range info.explicits { 691 w.typInfo(info) 692 } 693 } 694 695 // objInstIdx returns the indices for an object and a corresponding 696 // list of type arguments used to instantiate it, adding them to the 697 // export data as needed. 698 func (pw *pkgWriter) objInstIdx(obj types2.Object, explicits *types2.TypeList, dict *writerDict) objInfo { 699 explicitInfos := make([]typeInfo, explicits.Len()) 700 for i := range explicitInfos { 701 explicitInfos[i] = pw.typIdx(explicits.At(i), dict) 702 } 703 return objInfo{idx: pw.objIdx(obj), explicits: explicitInfos} 704 } 705 706 // objIdx returns the index for the given Object, adding it to the 707 // export data as needed. 708 func (pw *pkgWriter) objIdx(obj types2.Object) pkgbits.Index { 709 // TODO(mdempsky): Validate that obj is a global object (or a local 710 // defined type, which we hoist to global scope anyway). 711 712 if idx, ok := pw.objsIdx[obj]; ok { 713 return idx 714 } 715 716 dict := &writerDict{ 717 derivedIdx: make(map[types2.Type]pkgbits.Index), 718 } 719 720 if isDefinedType(obj) && obj.Pkg() == pw.curpkg { 721 decl, ok := pw.typDecls[obj.(*types2.TypeName)] 722 assert(ok) 723 dict.implicits = decl.implicits 724 } 725 726 // We encode objects into 4 elements across different sections, all 727 // sharing the same index: 728 // 729 // - RelocName has just the object's qualified name (i.e., 730 // Object.Pkg and Object.Name) and the CodeObj indicating what 731 // specific type of Object it is (Var, Func, etc). 732 // 733 // - RelocObj has the remaining public details about the object, 734 // relevant to go/types importers. 735 // 736 // - RelocObjExt has additional private details about the object, 737 // which are only relevant to cmd/compile itself. This is 738 // separated from RelocObj so that go/types importers are 739 // unaffected by internal compiler changes. 740 // 741 // - RelocObjDict has public details about the object's type 742 // parameters and derived type's used by the object. This is 743 // separated to facilitate the eventual introduction of 744 // shape-based stenciling. 745 // 746 // TODO(mdempsky): Re-evaluate whether RelocName still makes sense 747 // to keep separate from RelocObj. 748 749 w := pw.newWriter(pkgbits.RelocObj, pkgbits.SyncObject1) 750 wext := pw.newWriter(pkgbits.RelocObjExt, pkgbits.SyncObject1) 751 wname := pw.newWriter(pkgbits.RelocName, pkgbits.SyncObject1) 752 wdict := pw.newWriter(pkgbits.RelocObjDict, pkgbits.SyncObject1) 753 754 pw.objsIdx[obj] = w.Idx // break cycles 755 assert(wext.Idx == w.Idx) 756 assert(wname.Idx == w.Idx) 757 assert(wdict.Idx == w.Idx) 758 759 w.dict = dict 760 wext.dict = dict 761 762 code := w.doObj(wext, obj) 763 w.Flush() 764 wext.Flush() 765 766 wname.qualifiedIdent(obj) 767 wname.Code(code) 768 wname.Flush() 769 770 wdict.objDict(obj, w.dict) 771 wdict.Flush() 772 773 return w.Idx 774 } 775 776 // doObj writes the RelocObj definition for obj to w, and the 777 // RelocObjExt definition to wext. 778 func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj { 779 if obj.Pkg() != w.p.curpkg { 780 return pkgbits.ObjStub 781 } 782 783 switch obj := obj.(type) { 784 default: 785 w.p.unexpected("object", obj) 786 panic("unreachable") 787 788 case *types2.Const: 789 w.pos(obj) 790 w.typ(obj.Type()) 791 w.Value(obj.Val()) 792 return pkgbits.ObjConst 793 794 case *types2.Func: 795 decl, ok := w.p.funDecls[obj] 796 assert(ok) 797 sig := obj.Type().(*types2.Signature) 798 799 w.pos(obj) 800 w.typeParamNames(sig.TypeParams()) 801 w.signature(sig) 802 w.pos(decl) 803 wext.funcExt(obj) 804 return pkgbits.ObjFunc 805 806 case *types2.TypeName: 807 if obj.IsAlias() { 808 w.pos(obj) 809 w.typ(obj.Type()) 810 return pkgbits.ObjAlias 811 } 812 813 named := obj.Type().(*types2.Named) 814 assert(named.TypeArgs() == nil) 815 816 w.pos(obj) 817 w.typeParamNames(named.TypeParams()) 818 wext.typeExt(obj) 819 w.typ(named.Underlying()) 820 821 w.Len(named.NumMethods()) 822 for i := 0; i < named.NumMethods(); i++ { 823 w.method(wext, named.Method(i)) 824 } 825 826 return pkgbits.ObjType 827 828 case *types2.Var: 829 w.pos(obj) 830 w.typ(obj.Type()) 831 wext.varExt(obj) 832 return pkgbits.ObjVar 833 } 834 } 835 836 // objDict writes the dictionary needed for reading the given object. 837 func (w *writer) objDict(obj types2.Object, dict *writerDict) { 838 // TODO(mdempsky): Split objDict into multiple entries? reader.go 839 // doesn't care about the type parameter bounds, and reader2.go 840 // doesn't care about referenced functions. 841 842 w.dict = dict // TODO(mdempsky): This is a bit sketchy. 843 844 w.Len(len(dict.implicits)) 845 846 tparams := objTypeParams(obj) 847 ntparams := tparams.Len() 848 w.Len(ntparams) 849 for i := 0; i < ntparams; i++ { 850 w.typ(tparams.At(i).Constraint()) 851 } 852 853 nderived := len(dict.derived) 854 w.Len(nderived) 855 for _, typ := range dict.derived { 856 w.Reloc(pkgbits.RelocType, typ.idx) 857 w.Bool(typ.needed) 858 } 859 860 // Write runtime dictionary information. 861 // 862 // N.B., the go/types importer reads up to the section, but doesn't 863 // read any further, so it's safe to change. (See TODO above.) 864 865 // For each type parameter, write out whether the constraint is a 866 // basic interface. This is used to determine how aggressively we 867 // can shape corresponding type arguments. 868 // 869 // This is somewhat redundant with writing out the full type 870 // parameter constraints above, but the compiler currently skips 871 // over those. Also, we don't care about the *declared* constraints, 872 // but how the type parameters are actually *used*. E.g., if a type 873 // parameter is constrained to `int | uint` but then never used in 874 // arithmetic/conversions/etc, we could shape those together. 875 for _, implicit := range dict.implicits { 876 tparam := implicit.Type().(*types2.TypeParam) 877 w.Bool(tparam.Underlying().(*types2.Interface).IsMethodSet()) 878 } 879 for i := 0; i < ntparams; i++ { 880 tparam := tparams.At(i) 881 w.Bool(tparam.Underlying().(*types2.Interface).IsMethodSet()) 882 } 883 884 w.Len(len(dict.typeParamMethodExprs)) 885 for _, info := range dict.typeParamMethodExprs { 886 w.Len(info.typeParamIdx) 887 w.selectorInfo(info.methodInfo) 888 } 889 890 w.Len(len(dict.subdicts)) 891 for _, info := range dict.subdicts { 892 w.objInfo(info) 893 } 894 895 w.Len(len(dict.rtypes)) 896 for _, info := range dict.rtypes { 897 w.typInfo(info) 898 } 899 900 w.Len(len(dict.itabs)) 901 for _, info := range dict.itabs { 902 w.typInfo(info.typ) 903 w.typInfo(info.iface) 904 } 905 906 assert(len(dict.derived) == nderived) 907 } 908 909 func (w *writer) typeParamNames(tparams *types2.TypeParamList) { 910 w.Sync(pkgbits.SyncTypeParamNames) 911 912 ntparams := tparams.Len() 913 for i := 0; i < ntparams; i++ { 914 tparam := tparams.At(i).Obj() 915 w.pos(tparam) 916 w.localIdent(tparam) 917 } 918 } 919 920 func (w *writer) method(wext *writer, meth *types2.Func) { 921 decl, ok := w.p.funDecls[meth] 922 assert(ok) 923 sig := meth.Type().(*types2.Signature) 924 925 w.Sync(pkgbits.SyncMethod) 926 w.pos(meth) 927 w.selector(meth) 928 w.typeParamNames(sig.RecvTypeParams()) 929 w.param(sig.Recv()) 930 w.signature(sig) 931 932 w.pos(decl) // XXX: Hack to workaround linker limitations. 933 wext.funcExt(meth) 934 } 935 936 // qualifiedIdent writes out the name of an object declared at package 937 // scope. (For now, it's also used to refer to local defined types.) 938 func (w *writer) qualifiedIdent(obj types2.Object) { 939 w.Sync(pkgbits.SyncSym) 940 941 name := obj.Name() 942 if isDefinedType(obj) && obj.Pkg() == w.p.curpkg { 943 decl, ok := w.p.typDecls[obj.(*types2.TypeName)] 944 assert(ok) 945 if decl.gen != 0 { 946 // For local defined types, we embed a scope-disambiguation 947 // number directly into their name. types.SplitVargenSuffix then 948 // knows to look for this. 949 // 950 // TODO(mdempsky): Find a better solution; this is terrible. 951 name = fmt.Sprintf("%s·%v", name, decl.gen) 952 } 953 } 954 955 w.pkg(obj.Pkg()) 956 w.String(name) 957 } 958 959 // TODO(mdempsky): We should be able to omit pkg from both localIdent 960 // and selector, because they should always be known from context. 961 // However, past frustrations with this optimization in iexport make 962 // me a little nervous to try it again. 963 964 // localIdent writes the name of a locally declared object (i.e., 965 // objects that can only be accessed by non-qualified name, within the 966 // context of a particular function). 967 func (w *writer) localIdent(obj types2.Object) { 968 assert(!isGlobal(obj)) 969 w.Sync(pkgbits.SyncLocalIdent) 970 w.pkg(obj.Pkg()) 971 w.String(obj.Name()) 972 } 973 974 // selector writes the name of a field or method (i.e., objects that 975 // can only be accessed using selector expressions). 976 func (w *writer) selector(obj types2.Object) { 977 w.selectorInfo(w.p.selectorIdx(obj)) 978 } 979 980 func (w *writer) selectorInfo(info selectorInfo) { 981 w.Sync(pkgbits.SyncSelector) 982 w.pkgRef(info.pkgIdx) 983 w.StringRef(info.nameIdx) 984 } 985 986 func (pw *pkgWriter) selectorIdx(obj types2.Object) selectorInfo { 987 pkgIdx := pw.pkgIdx(obj.Pkg()) 988 nameIdx := pw.StringIdx(obj.Name()) 989 return selectorInfo{pkgIdx: pkgIdx, nameIdx: nameIdx} 990 } 991 992 // @@@ Compiler extensions 993 994 func (w *writer) funcExt(obj *types2.Func) { 995 decl, ok := w.p.funDecls[obj] 996 assert(ok) 997 998 // TODO(mdempsky): Extend these pragma validation flags to account 999 // for generics. E.g., linkname probably doesn't make sense at 1000 // least. 1001 1002 pragma := asPragmaFlag(decl.Pragma) 1003 if pragma&ir.Systemstack != 0 && pragma&ir.Nosplit != 0 { 1004 w.p.errorf(decl, "go:nosplit and go:systemstack cannot be combined") 1005 } 1006 1007 if decl.Body != nil { 1008 if pragma&ir.Noescape != 0 { 1009 w.p.errorf(decl, "can only use //go:noescape with external func implementations") 1010 } 1011 if (pragma&ir.UintptrKeepAlive != 0 && pragma&ir.UintptrEscapes == 0) && pragma&ir.Nosplit == 0 { 1012 // Stack growth can't handle uintptr arguments that may 1013 // be pointers (as we don't know which are pointers 1014 // when creating the stack map). Thus uintptrkeepalive 1015 // functions (and all transitive callees) must be 1016 // nosplit. 1017 // 1018 // N.B. uintptrescapes implies uintptrkeepalive but it 1019 // is OK since the arguments must escape to the heap. 1020 // 1021 // TODO(prattmic): Add recursive nosplit check of callees. 1022 // TODO(prattmic): Functions with no body (i.e., 1023 // assembly) must also be nosplit, but we can't check 1024 // that here. 1025 w.p.errorf(decl, "go:uintptrkeepalive requires go:nosplit") 1026 } 1027 } else { 1028 if base.Flag.Complete || decl.Name.Value == "init" { 1029 // Linknamed functions are allowed to have no body. Hopefully 1030 // the linkname target has a body. See issue 23311. 1031 if _, ok := w.p.linknames[obj]; !ok { 1032 w.p.errorf(decl, "missing function body") 1033 } 1034 } 1035 } 1036 1037 sig, block := obj.Type().(*types2.Signature), decl.Body 1038 body, closureVars := w.p.bodyIdx(sig, block, w.dict) 1039 assert(len(closureVars) == 0) 1040 1041 w.Sync(pkgbits.SyncFuncExt) 1042 w.pragmaFlag(pragma) 1043 w.linkname(obj) 1044 w.Bool(false) // stub extension 1045 w.Reloc(pkgbits.RelocBody, body) 1046 w.Sync(pkgbits.SyncEOF) 1047 } 1048 1049 func (w *writer) typeExt(obj *types2.TypeName) { 1050 decl, ok := w.p.typDecls[obj] 1051 assert(ok) 1052 1053 w.Sync(pkgbits.SyncTypeExt) 1054 1055 w.pragmaFlag(asPragmaFlag(decl.Pragma)) 1056 1057 // No LSym.SymIdx info yet. 1058 w.Int64(-1) 1059 w.Int64(-1) 1060 } 1061 1062 func (w *writer) varExt(obj *types2.Var) { 1063 w.Sync(pkgbits.SyncVarExt) 1064 w.linkname(obj) 1065 } 1066 1067 func (w *writer) linkname(obj types2.Object) { 1068 w.Sync(pkgbits.SyncLinkname) 1069 w.Int64(-1) 1070 w.String(w.p.linknames[obj]) 1071 } 1072 1073 func (w *writer) pragmaFlag(p ir.PragmaFlag) { 1074 w.Sync(pkgbits.SyncPragma) 1075 w.Int(int(p)) 1076 } 1077 1078 // @@@ Function bodies 1079 1080 // bodyIdx returns the index for the given function body (specified by 1081 // block), adding it to the export data 1082 func (pw *pkgWriter) bodyIdx(sig *types2.Signature, block *syntax.BlockStmt, dict *writerDict) (idx pkgbits.Index, closureVars []posVar) { 1083 w := pw.newWriter(pkgbits.RelocBody, pkgbits.SyncFuncBody) 1084 w.sig = sig 1085 w.dict = dict 1086 1087 w.funcargs(sig) 1088 if w.Bool(block != nil) { 1089 w.stmts(block.List) 1090 w.pos(block.Rbrace) 1091 } 1092 1093 return w.Flush(), w.closureVars 1094 } 1095 1096 func (w *writer) funcargs(sig *types2.Signature) { 1097 do := func(params *types2.Tuple, result bool) { 1098 for i := 0; i < params.Len(); i++ { 1099 w.funcarg(params.At(i), result) 1100 } 1101 } 1102 1103 if recv := sig.Recv(); recv != nil { 1104 w.funcarg(recv, false) 1105 } 1106 do(sig.Params(), false) 1107 do(sig.Results(), true) 1108 } 1109 1110 func (w *writer) funcarg(param *types2.Var, result bool) { 1111 if param.Name() != "" || result { 1112 w.addLocal(param) 1113 } 1114 } 1115 1116 // addLocal records the declaration of a new local variable. 1117 func (w *writer) addLocal(obj *types2.Var) { 1118 idx := len(w.localsIdx) 1119 1120 w.Sync(pkgbits.SyncAddLocal) 1121 if w.p.SyncMarkers() { 1122 w.Int(idx) 1123 } 1124 w.varDictIndex(obj) 1125 1126 if w.localsIdx == nil { 1127 w.localsIdx = make(map[*types2.Var]int) 1128 } 1129 w.localsIdx[obj] = idx 1130 } 1131 1132 // useLocal writes a reference to the given local or free variable 1133 // into the bitstream. 1134 func (w *writer) useLocal(pos syntax.Pos, obj *types2.Var) { 1135 w.Sync(pkgbits.SyncUseObjLocal) 1136 1137 if idx, ok := w.localsIdx[obj]; w.Bool(ok) { 1138 w.Len(idx) 1139 return 1140 } 1141 1142 idx, ok := w.closureVarsIdx[obj] 1143 if !ok { 1144 if w.closureVarsIdx == nil { 1145 w.closureVarsIdx = make(map[*types2.Var]int) 1146 } 1147 idx = len(w.closureVars) 1148 w.closureVars = append(w.closureVars, posVar{pos, obj}) 1149 w.closureVarsIdx[obj] = idx 1150 } 1151 w.Len(idx) 1152 } 1153 1154 func (w *writer) openScope(pos syntax.Pos) { 1155 w.Sync(pkgbits.SyncOpenScope) 1156 w.pos(pos) 1157 } 1158 1159 func (w *writer) closeScope(pos syntax.Pos) { 1160 w.Sync(pkgbits.SyncCloseScope) 1161 w.pos(pos) 1162 w.closeAnotherScope() 1163 } 1164 1165 func (w *writer) closeAnotherScope() { 1166 w.Sync(pkgbits.SyncCloseAnotherScope) 1167 } 1168 1169 // @@@ Statements 1170 1171 // stmt writes the given statement into the function body bitstream. 1172 func (w *writer) stmt(stmt syntax.Stmt) { 1173 var stmts []syntax.Stmt 1174 if stmt != nil { 1175 stmts = []syntax.Stmt{stmt} 1176 } 1177 w.stmts(stmts) 1178 } 1179 1180 func (w *writer) stmts(stmts []syntax.Stmt) { 1181 w.Sync(pkgbits.SyncStmts) 1182 for _, stmt := range stmts { 1183 w.stmt1(stmt) 1184 } 1185 w.Code(stmtEnd) 1186 w.Sync(pkgbits.SyncStmtsEnd) 1187 } 1188 1189 func (w *writer) stmt1(stmt syntax.Stmt) { 1190 switch stmt := stmt.(type) { 1191 default: 1192 w.p.unexpected("statement", stmt) 1193 1194 case nil, *syntax.EmptyStmt: 1195 return 1196 1197 case *syntax.AssignStmt: 1198 switch { 1199 case stmt.Rhs == nil: 1200 w.Code(stmtIncDec) 1201 w.op(binOps[stmt.Op]) 1202 w.expr(stmt.Lhs) 1203 w.pos(stmt) 1204 1205 case stmt.Op != 0 && stmt.Op != syntax.Def: 1206 w.Code(stmtAssignOp) 1207 w.op(binOps[stmt.Op]) 1208 w.expr(stmt.Lhs) 1209 w.pos(stmt) 1210 1211 var typ types2.Type 1212 if stmt.Op != syntax.Shl && stmt.Op != syntax.Shr { 1213 typ = w.p.typeOf(stmt.Lhs) 1214 } 1215 w.implicitConvExpr(typ, stmt.Rhs) 1216 1217 default: 1218 w.assignStmt(stmt, stmt.Lhs, stmt.Rhs) 1219 } 1220 1221 case *syntax.BlockStmt: 1222 w.Code(stmtBlock) 1223 w.blockStmt(stmt) 1224 1225 case *syntax.BranchStmt: 1226 w.Code(stmtBranch) 1227 w.pos(stmt) 1228 w.op(branchOps[stmt.Tok]) 1229 w.optLabel(stmt.Label) 1230 1231 case *syntax.CallStmt: 1232 w.Code(stmtCall) 1233 w.pos(stmt) 1234 w.op(callOps[stmt.Tok]) 1235 w.expr(stmt.Call) 1236 1237 case *syntax.DeclStmt: 1238 for _, decl := range stmt.DeclList { 1239 w.declStmt(decl) 1240 } 1241 1242 case *syntax.ExprStmt: 1243 w.Code(stmtExpr) 1244 w.expr(stmt.X) 1245 1246 case *syntax.ForStmt: 1247 w.Code(stmtFor) 1248 w.forStmt(stmt) 1249 1250 case *syntax.IfStmt: 1251 w.Code(stmtIf) 1252 w.ifStmt(stmt) 1253 1254 case *syntax.LabeledStmt: 1255 w.Code(stmtLabel) 1256 w.pos(stmt) 1257 w.label(stmt.Label) 1258 w.stmt1(stmt.Stmt) 1259 1260 case *syntax.ReturnStmt: 1261 w.Code(stmtReturn) 1262 w.pos(stmt) 1263 1264 resultTypes := w.sig.Results() 1265 dstType := func(i int) types2.Type { 1266 return resultTypes.At(i).Type() 1267 } 1268 w.multiExpr(stmt, dstType, unpackListExpr(stmt.Results)) 1269 1270 case *syntax.SelectStmt: 1271 w.Code(stmtSelect) 1272 w.selectStmt(stmt) 1273 1274 case *syntax.SendStmt: 1275 chanType := types2.CoreType(w.p.typeOf(stmt.Chan)).(*types2.Chan) 1276 1277 w.Code(stmtSend) 1278 w.pos(stmt) 1279 w.expr(stmt.Chan) 1280 w.implicitConvExpr(chanType.Elem(), stmt.Value) 1281 1282 case *syntax.SwitchStmt: 1283 w.Code(stmtSwitch) 1284 w.switchStmt(stmt) 1285 } 1286 } 1287 1288 func (w *writer) assignList(expr syntax.Expr) { 1289 exprs := unpackListExpr(expr) 1290 w.Len(len(exprs)) 1291 1292 for _, expr := range exprs { 1293 w.assign(expr) 1294 } 1295 } 1296 1297 func (w *writer) assign(expr syntax.Expr) { 1298 expr = unparen(expr) 1299 1300 if name, ok := expr.(*syntax.Name); ok { 1301 if name.Value == "_" { 1302 w.Code(assignBlank) 1303 return 1304 } 1305 1306 if obj, ok := w.p.info.Defs[name]; ok { 1307 obj := obj.(*types2.Var) 1308 1309 w.Code(assignDef) 1310 w.pos(obj) 1311 w.localIdent(obj) 1312 w.typ(obj.Type()) 1313 1314 // TODO(mdempsky): Minimize locals index size by deferring 1315 // this until the variables actually come into scope. 1316 w.addLocal(obj) 1317 return 1318 } 1319 } 1320 1321 w.Code(assignExpr) 1322 w.expr(expr) 1323 } 1324 1325 func (w *writer) declStmt(decl syntax.Decl) { 1326 switch decl := decl.(type) { 1327 default: 1328 w.p.unexpected("declaration", decl) 1329 1330 case *syntax.ConstDecl, *syntax.TypeDecl: 1331 1332 case *syntax.VarDecl: 1333 w.assignStmt(decl, namesAsExpr(decl.NameList), decl.Values) 1334 } 1335 } 1336 1337 // assignStmt writes out an assignment for "lhs = rhs". 1338 func (w *writer) assignStmt(pos poser, lhs0, rhs0 syntax.Expr) { 1339 lhs := unpackListExpr(lhs0) 1340 rhs := unpackListExpr(rhs0) 1341 1342 w.Code(stmtAssign) 1343 w.pos(pos) 1344 1345 // As if w.assignList(lhs0). 1346 w.Len(len(lhs)) 1347 for _, expr := range lhs { 1348 w.assign(expr) 1349 } 1350 1351 dstType := func(i int) types2.Type { 1352 dst := lhs[i] 1353 1354 // Finding dstType is somewhat involved, because for VarDecl 1355 // statements, the Names are only added to the info.{Defs,Uses} 1356 // maps, not to info.Types. 1357 if name, ok := unparen(dst).(*syntax.Name); ok { 1358 if name.Value == "_" { 1359 return nil // ok: no implicit conversion 1360 } else if def, ok := w.p.info.Defs[name].(*types2.Var); ok { 1361 return def.Type() 1362 } else if use, ok := w.p.info.Uses[name].(*types2.Var); ok { 1363 return use.Type() 1364 } else { 1365 w.p.fatalf(dst, "cannot find type of destination object: %v", dst) 1366 } 1367 } 1368 1369 return w.p.typeOf(dst) 1370 } 1371 1372 w.multiExpr(pos, dstType, rhs) 1373 } 1374 1375 func (w *writer) blockStmt(stmt *syntax.BlockStmt) { 1376 w.Sync(pkgbits.SyncBlockStmt) 1377 w.openScope(stmt.Pos()) 1378 w.stmts(stmt.List) 1379 w.closeScope(stmt.Rbrace) 1380 } 1381 1382 func (w *writer) forStmt(stmt *syntax.ForStmt) { 1383 w.Sync(pkgbits.SyncForStmt) 1384 w.openScope(stmt.Pos()) 1385 1386 if rang, ok := stmt.Init.(*syntax.RangeClause); w.Bool(ok) { 1387 w.pos(rang) 1388 w.assignList(rang.Lhs) 1389 w.expr(rang.X) 1390 1391 xtyp := w.p.typeOf(rang.X) 1392 if _, isMap := types2.CoreType(xtyp).(*types2.Map); isMap { 1393 w.rtype(xtyp) 1394 } 1395 { 1396 lhs := unpackListExpr(rang.Lhs) 1397 assign := func(i int, src types2.Type) { 1398 if i >= len(lhs) { 1399 return 1400 } 1401 dst := unparen(lhs[i]) 1402 if name, ok := dst.(*syntax.Name); ok && name.Value == "_" { 1403 return 1404 } 1405 1406 var dstType types2.Type 1407 if rang.Def { 1408 // For `:=` assignments, the LHS names only appear in Defs, 1409 // not Types (as used by typeOf). 1410 dstType = w.p.info.Defs[dst.(*syntax.Name)].(*types2.Var).Type() 1411 } else { 1412 dstType = w.p.typeOf(dst) 1413 } 1414 1415 w.convRTTI(src, dstType) 1416 } 1417 1418 keyType, valueType := w.p.rangeTypes(rang.X) 1419 assign(0, keyType) 1420 assign(1, valueType) 1421 } 1422 1423 } else { 1424 w.pos(stmt) 1425 w.stmt(stmt.Init) 1426 w.optExpr(stmt.Cond) 1427 w.stmt(stmt.Post) 1428 } 1429 1430 w.blockStmt(stmt.Body) 1431 w.closeAnotherScope() 1432 } 1433 1434 // rangeTypes returns the types of values produced by ranging over 1435 // expr. 1436 func (pw *pkgWriter) rangeTypes(expr syntax.Expr) (key, value types2.Type) { 1437 typ := pw.typeOf(expr) 1438 switch typ := types2.CoreType(typ).(type) { 1439 case *types2.Pointer: // must be pointer to array 1440 return types2.Typ[types2.Int], types2.CoreType(typ.Elem()).(*types2.Array).Elem() 1441 case *types2.Array: 1442 return types2.Typ[types2.Int], typ.Elem() 1443 case *types2.Slice: 1444 return types2.Typ[types2.Int], typ.Elem() 1445 case *types2.Basic: 1446 if typ.Info()&types2.IsString != 0 { 1447 return types2.Typ[types2.Int], runeTypeName.Type() 1448 } 1449 case *types2.Map: 1450 return typ.Key(), typ.Elem() 1451 case *types2.Chan: 1452 return typ.Elem(), nil 1453 } 1454 pw.fatalf(expr, "unexpected range type: %v", typ) 1455 panic("unreachable") 1456 } 1457 1458 func (w *writer) ifStmt(stmt *syntax.IfStmt) { 1459 w.Sync(pkgbits.SyncIfStmt) 1460 w.openScope(stmt.Pos()) 1461 w.pos(stmt) 1462 w.stmt(stmt.Init) 1463 w.expr(stmt.Cond) 1464 w.blockStmt(stmt.Then) 1465 w.stmt(stmt.Else) 1466 w.closeAnotherScope() 1467 } 1468 1469 func (w *writer) selectStmt(stmt *syntax.SelectStmt) { 1470 w.Sync(pkgbits.SyncSelectStmt) 1471 1472 w.pos(stmt) 1473 w.Len(len(stmt.Body)) 1474 for i, clause := range stmt.Body { 1475 if i > 0 { 1476 w.closeScope(clause.Pos()) 1477 } 1478 w.openScope(clause.Pos()) 1479 1480 w.pos(clause) 1481 w.stmt(clause.Comm) 1482 w.stmts(clause.Body) 1483 } 1484 if len(stmt.Body) > 0 { 1485 w.closeScope(stmt.Rbrace) 1486 } 1487 } 1488 1489 func (w *writer) switchStmt(stmt *syntax.SwitchStmt) { 1490 w.Sync(pkgbits.SyncSwitchStmt) 1491 1492 w.openScope(stmt.Pos()) 1493 w.pos(stmt) 1494 w.stmt(stmt.Init) 1495 1496 var iface, tagType types2.Type 1497 if guard, ok := stmt.Tag.(*syntax.TypeSwitchGuard); w.Bool(ok) { 1498 iface = w.p.typeOf(guard.X) 1499 1500 w.pos(guard) 1501 if tag := guard.Lhs; w.Bool(tag != nil) { 1502 w.pos(tag) 1503 1504 // Like w.localIdent, but we don't have a types2.Object. 1505 w.Sync(pkgbits.SyncLocalIdent) 1506 w.pkg(w.p.curpkg) 1507 w.String(tag.Value) 1508 } 1509 w.expr(guard.X) 1510 } else { 1511 tag := stmt.Tag 1512 1513 if tag != nil { 1514 tagType = w.p.typeOf(tag) 1515 } else { 1516 tagType = types2.Typ[types2.Bool] 1517 } 1518 1519 // Walk is going to emit comparisons between the tag value and 1520 // each case expression, and we want these comparisons to always 1521 // have the same type. If there are any case values that can't be 1522 // converted to the tag value's type, then convert everything to 1523 // `any` instead. 1524 Outer: 1525 for _, clause := range stmt.Body { 1526 for _, cas := range unpackListExpr(clause.Cases) { 1527 if casType := w.p.typeOf(cas); !types2.AssignableTo(casType, tagType) { 1528 tagType = types2.NewInterfaceType(nil, nil) 1529 break Outer 1530 } 1531 } 1532 } 1533 1534 if w.Bool(tag != nil) { 1535 w.implicitConvExpr(tagType, tag) 1536 } 1537 } 1538 1539 w.Len(len(stmt.Body)) 1540 for i, clause := range stmt.Body { 1541 if i > 0 { 1542 w.closeScope(clause.Pos()) 1543 } 1544 w.openScope(clause.Pos()) 1545 1546 w.pos(clause) 1547 1548 cases := unpackListExpr(clause.Cases) 1549 if iface != nil { 1550 w.Len(len(cases)) 1551 for _, cas := range cases { 1552 if w.Bool(isNil(w.p, cas)) { 1553 continue 1554 } 1555 w.exprType(iface, cas) 1556 } 1557 } else { 1558 // As if w.exprList(clause.Cases), 1559 // but with implicit conversions to tagType. 1560 1561 w.Sync(pkgbits.SyncExprList) 1562 w.Sync(pkgbits.SyncExprs) 1563 w.Len(len(cases)) 1564 for _, cas := range cases { 1565 w.implicitConvExpr(tagType, cas) 1566 } 1567 } 1568 1569 if obj, ok := w.p.info.Implicits[clause]; ok { 1570 // TODO(mdempsky): These pos details are quirkish, but also 1571 // necessary so the variable's position is correct for DWARF 1572 // scope assignment later. It would probably be better for us to 1573 // instead just set the variable's DWARF scoping info earlier so 1574 // we can give it the correct position information. 1575 pos := clause.Pos() 1576 if typs := unpackListExpr(clause.Cases); len(typs) != 0 { 1577 pos = typeExprEndPos(typs[len(typs)-1]) 1578 } 1579 w.pos(pos) 1580 1581 obj := obj.(*types2.Var) 1582 w.typ(obj.Type()) 1583 w.addLocal(obj) 1584 } 1585 1586 w.stmts(clause.Body) 1587 } 1588 if len(stmt.Body) > 0 { 1589 w.closeScope(stmt.Rbrace) 1590 } 1591 1592 w.closeScope(stmt.Rbrace) 1593 } 1594 1595 func (w *writer) label(label *syntax.Name) { 1596 w.Sync(pkgbits.SyncLabel) 1597 1598 // TODO(mdempsky): Replace label strings with dense indices. 1599 w.String(label.Value) 1600 } 1601 1602 func (w *writer) optLabel(label *syntax.Name) { 1603 w.Sync(pkgbits.SyncOptLabel) 1604 if w.Bool(label != nil) { 1605 w.label(label) 1606 } 1607 } 1608 1609 // @@@ Expressions 1610 1611 // expr writes the given expression into the function body bitstream. 1612 func (w *writer) expr(expr syntax.Expr) { 1613 base.Assertf(expr != nil, "missing expression") 1614 1615 expr = unparen(expr) // skip parens; unneeded after typecheck 1616 1617 obj, inst := lookupObj(w.p, expr) 1618 targs := inst.TypeArgs 1619 1620 if tv, ok := w.p.maybeTypeAndValue(expr); ok { 1621 if tv.IsType() { 1622 w.p.fatalf(expr, "unexpected type expression %v", syntax.String(expr)) 1623 } 1624 1625 if tv.Value != nil { 1626 w.Code(exprConst) 1627 w.pos(expr) 1628 typ := idealType(tv) 1629 assert(typ != nil) 1630 w.typ(typ) 1631 w.Value(tv.Value) 1632 1633 // TODO(mdempsky): These details are only important for backend 1634 // diagnostics. Explore writing them out separately. 1635 w.op(constExprOp(expr)) 1636 w.String(syntax.String(expr)) 1637 return 1638 } 1639 1640 if _, isNil := obj.(*types2.Nil); isNil { 1641 w.Code(exprNil) 1642 w.pos(expr) 1643 w.typ(tv.Type) 1644 return 1645 } 1646 1647 // With shape types (and particular pointer shaping), we may have 1648 // an expression of type "go.shape.*uint8", but need to reshape it 1649 // to another shape-identical type to allow use in field 1650 // selection, indexing, etc. 1651 if typ := tv.Type; !tv.IsBuiltin() && !isTuple(typ) && !isUntyped(typ) { 1652 w.Code(exprReshape) 1653 w.typ(typ) 1654 // fallthrough 1655 } 1656 } 1657 1658 if obj != nil { 1659 if targs.Len() != 0 { 1660 obj := obj.(*types2.Func) 1661 1662 w.Code(exprFuncInst) 1663 w.pos(expr) 1664 w.funcInst(obj, targs) 1665 return 1666 } 1667 1668 if isGlobal(obj) { 1669 w.Code(exprGlobal) 1670 w.obj(obj, nil) 1671 return 1672 } 1673 1674 obj := obj.(*types2.Var) 1675 assert(!obj.IsField()) 1676 1677 w.Code(exprLocal) 1678 w.useLocal(expr.Pos(), obj) 1679 return 1680 } 1681 1682 switch expr := expr.(type) { 1683 default: 1684 w.p.unexpected("expression", expr) 1685 1686 case *syntax.CompositeLit: 1687 w.Code(exprCompLit) 1688 w.compLit(expr) 1689 1690 case *syntax.FuncLit: 1691 w.Code(exprFuncLit) 1692 w.funcLit(expr) 1693 1694 case *syntax.SelectorExpr: 1695 sel, ok := w.p.info.Selections[expr] 1696 assert(ok) 1697 1698 switch sel.Kind() { 1699 default: 1700 w.p.fatalf(expr, "unexpected selection kind: %v", sel.Kind()) 1701 1702 case types2.FieldVal: 1703 w.Code(exprFieldVal) 1704 w.expr(expr.X) 1705 w.pos(expr) 1706 w.selector(sel.Obj()) 1707 1708 case types2.MethodVal: 1709 w.Code(exprMethodVal) 1710 typ := w.recvExpr(expr, sel) 1711 w.pos(expr) 1712 w.methodExpr(expr, typ, sel) 1713 1714 case types2.MethodExpr: 1715 w.Code(exprMethodExpr) 1716 1717 tv := w.p.typeAndValue(expr.X) 1718 assert(tv.IsType()) 1719 1720 index := sel.Index() 1721 implicits := index[:len(index)-1] 1722 1723 typ := tv.Type 1724 w.typ(typ) 1725 1726 w.Len(len(implicits)) 1727 for _, ix := range implicits { 1728 w.Len(ix) 1729 typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type() 1730 } 1731 1732 recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type() 1733 if w.Bool(isPtrTo(typ, recv)) { // need deref 1734 typ = recv 1735 } else if w.Bool(isPtrTo(recv, typ)) { // need addr 1736 typ = recv 1737 } 1738 1739 w.pos(expr) 1740 w.methodExpr(expr, typ, sel) 1741 } 1742 1743 case *syntax.IndexExpr: 1744 _ = w.p.typeOf(expr.Index) // ensure this is an index expression, not an instantiation 1745 1746 xtyp := w.p.typeOf(expr.X) 1747 1748 var keyType types2.Type 1749 if mapType, ok := types2.CoreType(xtyp).(*types2.Map); ok { 1750 keyType = mapType.Key() 1751 } 1752 1753 w.Code(exprIndex) 1754 w.expr(expr.X) 1755 w.pos(expr) 1756 w.implicitConvExpr(keyType, expr.Index) 1757 if keyType != nil { 1758 w.rtype(xtyp) 1759 } 1760 1761 case *syntax.SliceExpr: 1762 w.Code(exprSlice) 1763 w.expr(expr.X) 1764 w.pos(expr) 1765 for _, n := range &expr.Index { 1766 w.optExpr(n) 1767 } 1768 1769 case *syntax.AssertExpr: 1770 iface := w.p.typeOf(expr.X) 1771 1772 w.Code(exprAssert) 1773 w.expr(expr.X) 1774 w.pos(expr) 1775 w.exprType(iface, expr.Type) 1776 w.rtype(iface) 1777 1778 case *syntax.Operation: 1779 if expr.Y == nil { 1780 w.Code(exprUnaryOp) 1781 w.op(unOps[expr.Op]) 1782 w.pos(expr) 1783 w.expr(expr.X) 1784 break 1785 } 1786 1787 var commonType types2.Type 1788 switch expr.Op { 1789 case syntax.Shl, syntax.Shr: 1790 // ok: operands are allowed to have different types 1791 default: 1792 xtyp := w.p.typeOf(expr.X) 1793 ytyp := w.p.typeOf(expr.Y) 1794 switch { 1795 case types2.AssignableTo(xtyp, ytyp): 1796 commonType = ytyp 1797 case types2.AssignableTo(ytyp, xtyp): 1798 commonType = xtyp 1799 default: 1800 w.p.fatalf(expr, "failed to find common type between %v and %v", xtyp, ytyp) 1801 } 1802 } 1803 1804 w.Code(exprBinaryOp) 1805 w.op(binOps[expr.Op]) 1806 w.implicitConvExpr(commonType, expr.X) 1807 w.pos(expr) 1808 w.implicitConvExpr(commonType, expr.Y) 1809 1810 case *syntax.CallExpr: 1811 tv := w.p.typeAndValue(expr.Fun) 1812 if tv.IsType() { 1813 assert(len(expr.ArgList) == 1) 1814 assert(!expr.HasDots) 1815 w.convertExpr(tv.Type, expr.ArgList[0], false) 1816 break 1817 } 1818 1819 var rtype types2.Type 1820 if tv.IsBuiltin() { 1821 switch obj, _ := lookupObj(w.p, expr.Fun); obj.Name() { 1822 case "make": 1823 assert(len(expr.ArgList) >= 1) 1824 assert(!expr.HasDots) 1825 1826 w.Code(exprMake) 1827 w.pos(expr) 1828 w.exprType(nil, expr.ArgList[0]) 1829 w.exprs(expr.ArgList[1:]) 1830 1831 typ := w.p.typeOf(expr) 1832 switch coreType := types2.CoreType(typ).(type) { 1833 default: 1834 w.p.fatalf(expr, "unexpected core type: %v", coreType) 1835 case *types2.Chan: 1836 w.rtype(typ) 1837 case *types2.Map: 1838 w.rtype(typ) 1839 case *types2.Slice: 1840 w.rtype(sliceElem(typ)) 1841 } 1842 1843 return 1844 1845 case "new": 1846 assert(len(expr.ArgList) == 1) 1847 assert(!expr.HasDots) 1848 1849 w.Code(exprNew) 1850 w.pos(expr) 1851 w.exprType(nil, expr.ArgList[0]) 1852 return 1853 1854 case "append": 1855 rtype = sliceElem(w.p.typeOf(expr)) 1856 case "copy": 1857 typ := w.p.typeOf(expr.ArgList[0]) 1858 if tuple, ok := typ.(*types2.Tuple); ok { // "copy(g())" 1859 typ = tuple.At(0).Type() 1860 } 1861 rtype = sliceElem(typ) 1862 case "delete": 1863 typ := w.p.typeOf(expr.ArgList[0]) 1864 if tuple, ok := typ.(*types2.Tuple); ok { // "delete(g())" 1865 typ = tuple.At(0).Type() 1866 } 1867 rtype = typ 1868 case "Slice": 1869 rtype = sliceElem(w.p.typeOf(expr)) 1870 } 1871 } 1872 1873 writeFunExpr := func() { 1874 fun := unparen(expr.Fun) 1875 1876 if selector, ok := fun.(*syntax.SelectorExpr); ok { 1877 if sel, ok := w.p.info.Selections[selector]; ok && sel.Kind() == types2.MethodVal { 1878 w.Bool(true) // method call 1879 typ := w.recvExpr(selector, sel) 1880 w.methodExpr(selector, typ, sel) 1881 return 1882 } 1883 } 1884 1885 w.Bool(false) // not a method call (i.e., normal function call) 1886 1887 if obj, inst := lookupObj(w.p, fun); w.Bool(obj != nil && inst.TypeArgs.Len() != 0) { 1888 obj := obj.(*types2.Func) 1889 1890 w.pos(fun) 1891 w.funcInst(obj, inst.TypeArgs) 1892 return 1893 } 1894 1895 w.expr(fun) 1896 } 1897 1898 sigType := types2.CoreType(tv.Type).(*types2.Signature) 1899 paramTypes := sigType.Params() 1900 1901 w.Code(exprCall) 1902 writeFunExpr() 1903 w.pos(expr) 1904 1905 paramType := func(i int) types2.Type { 1906 if sigType.Variadic() && !expr.HasDots && i >= paramTypes.Len()-1 { 1907 return paramTypes.At(paramTypes.Len() - 1).Type().(*types2.Slice).Elem() 1908 } 1909 return paramTypes.At(i).Type() 1910 } 1911 1912 w.multiExpr(expr, paramType, expr.ArgList) 1913 w.Bool(expr.HasDots) 1914 if rtype != nil { 1915 w.rtype(rtype) 1916 } 1917 } 1918 } 1919 1920 func sliceElem(typ types2.Type) types2.Type { 1921 return types2.CoreType(typ).(*types2.Slice).Elem() 1922 } 1923 1924 func (w *writer) optExpr(expr syntax.Expr) { 1925 if w.Bool(expr != nil) { 1926 w.expr(expr) 1927 } 1928 } 1929 1930 // recvExpr writes out expr.X, but handles any implicit addressing, 1931 // dereferencing, and field selections appropriate for the method 1932 // selection. 1933 func (w *writer) recvExpr(expr *syntax.SelectorExpr, sel *types2.Selection) types2.Type { 1934 index := sel.Index() 1935 implicits := index[:len(index)-1] 1936 1937 w.Code(exprRecv) 1938 w.expr(expr.X) 1939 w.pos(expr) 1940 w.Len(len(implicits)) 1941 1942 typ := w.p.typeOf(expr.X) 1943 for _, ix := range implicits { 1944 typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type() 1945 w.Len(ix) 1946 } 1947 1948 recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type() 1949 if w.Bool(isPtrTo(typ, recv)) { // needs deref 1950 typ = recv 1951 } else if w.Bool(isPtrTo(recv, typ)) { // needs addr 1952 typ = recv 1953 } 1954 1955 return typ 1956 } 1957 1958 // funcInst writes a reference to an instantiated function. 1959 func (w *writer) funcInst(obj *types2.Func, targs *types2.TypeList) { 1960 info := w.p.objInstIdx(obj, targs, w.dict) 1961 1962 // Type arguments list contains derived types; we can emit a static 1963 // call to the shaped function, but need to dynamically compute the 1964 // runtime dictionary pointer. 1965 if w.Bool(info.anyDerived()) { 1966 w.Len(w.dict.subdictIdx(info)) 1967 return 1968 } 1969 1970 // Type arguments list is statically known; we can emit a static 1971 // call with a statically reference to the respective runtime 1972 // dictionary. 1973 w.objInfo(info) 1974 } 1975 1976 // methodExpr writes out a reference to the method selected by 1977 // expr. sel should be the corresponding types2.Selection, and recv 1978 // the type produced after any implicit addressing, dereferencing, and 1979 // field selection. (Note: recv might differ from sel.Obj()'s receiver 1980 // parameter in the case of interface types, and is needed for 1981 // handling type parameter methods.) 1982 func (w *writer) methodExpr(expr *syntax.SelectorExpr, recv types2.Type, sel *types2.Selection) { 1983 fun := sel.Obj().(*types2.Func) 1984 sig := fun.Type().(*types2.Signature) 1985 1986 w.typ(recv) 1987 w.typ(sig) 1988 w.pos(expr) 1989 w.selector(fun) 1990 1991 // Method on a type parameter. These require an indirect call 1992 // through the current function's runtime dictionary. 1993 if typeParam, ok := recv.(*types2.TypeParam); w.Bool(ok) { 1994 typeParamIdx := w.dict.typeParamIndex(typeParam) 1995 methodInfo := w.p.selectorIdx(fun) 1996 1997 w.Len(w.dict.typeParamMethodExprIdx(typeParamIdx, methodInfo)) 1998 return 1999 } 2000 2001 if isInterface(recv) != isInterface(sig.Recv().Type()) { 2002 w.p.fatalf(expr, "isInterface inconsistency: %v and %v", recv, sig.Recv().Type()) 2003 } 2004 2005 if !isInterface(recv) { 2006 if named, ok := deref2(recv).(*types2.Named); ok { 2007 obj, targs := splitNamed(named) 2008 info := w.p.objInstIdx(obj, targs, w.dict) 2009 2010 // Method on a derived receiver type. These can be handled by a 2011 // static call to the shaped method, but require dynamically 2012 // looking up the appropriate dictionary argument in the current 2013 // function's runtime dictionary. 2014 if w.p.hasImplicitTypeParams(obj) || info.anyDerived() { 2015 w.Bool(true) // dynamic subdictionary 2016 w.Len(w.dict.subdictIdx(info)) 2017 return 2018 } 2019 2020 // Method on a fully known receiver type. These can be handled 2021 // by a static call to the shaped method, and with a static 2022 // reference to the receiver type's dictionary. 2023 if targs.Len() != 0 { 2024 w.Bool(false) // no dynamic subdictionary 2025 w.Bool(true) // static dictionary 2026 w.objInfo(info) 2027 return 2028 } 2029 } 2030 } 2031 2032 w.Bool(false) // no dynamic subdictionary 2033 w.Bool(false) // no static dictionary 2034 } 2035 2036 // multiExpr writes a sequence of expressions, where the i'th value is 2037 // implicitly converted to dstType(i). It also handles when exprs is a 2038 // single, multi-valued expression (e.g., the multi-valued argument in 2039 // an f(g()) call, or the RHS operand in a comma-ok assignment). 2040 func (w *writer) multiExpr(pos poser, dstType func(int) types2.Type, exprs []syntax.Expr) { 2041 w.Sync(pkgbits.SyncMultiExpr) 2042 2043 if len(exprs) == 1 { 2044 expr := exprs[0] 2045 if tuple, ok := w.p.typeOf(expr).(*types2.Tuple); ok { 2046 assert(tuple.Len() > 1) 2047 w.Bool(true) // N:1 assignment 2048 w.pos(pos) 2049 w.expr(expr) 2050 2051 w.Len(tuple.Len()) 2052 for i := 0; i < tuple.Len(); i++ { 2053 src := tuple.At(i).Type() 2054 // TODO(mdempsky): Investigate not writing src here. I think 2055 // the reader should be able to infer it from expr anyway. 2056 w.typ(src) 2057 if dst := dstType(i); w.Bool(dst != nil && !types2.Identical(src, dst)) { 2058 if src == nil || dst == nil { 2059 w.p.fatalf(pos, "src is %v, dst is %v", src, dst) 2060 } 2061 if !types2.AssignableTo(src, dst) { 2062 w.p.fatalf(pos, "%v is not assignable to %v", src, dst) 2063 } 2064 w.typ(dst) 2065 w.convRTTI(src, dst) 2066 } 2067 } 2068 return 2069 } 2070 } 2071 2072 w.Bool(false) // N:N assignment 2073 w.Len(len(exprs)) 2074 for i, expr := range exprs { 2075 w.implicitConvExpr(dstType(i), expr) 2076 } 2077 } 2078 2079 // implicitConvExpr is like expr, but if dst is non-nil and different 2080 // from expr's type, then an implicit conversion operation is inserted 2081 // at expr's position. 2082 func (w *writer) implicitConvExpr(dst types2.Type, expr syntax.Expr) { 2083 w.convertExpr(dst, expr, true) 2084 } 2085 2086 func (w *writer) convertExpr(dst types2.Type, expr syntax.Expr, implicit bool) { 2087 src := w.p.typeOf(expr) 2088 2089 // Omit implicit no-op conversions. 2090 identical := dst == nil || types2.Identical(src, dst) 2091 if implicit && identical { 2092 w.expr(expr) 2093 return 2094 } 2095 2096 if implicit && !types2.AssignableTo(src, dst) { 2097 w.p.fatalf(expr, "%v is not assignable to %v", src, dst) 2098 } 2099 2100 w.Code(exprConvert) 2101 w.Bool(implicit) 2102 w.typ(dst) 2103 w.pos(expr) 2104 w.convRTTI(src, dst) 2105 w.Bool(isTypeParam(dst)) 2106 w.Bool(identical) 2107 w.expr(expr) 2108 } 2109 2110 func (w *writer) compLit(lit *syntax.CompositeLit) { 2111 typ := w.p.typeOf(lit) 2112 2113 w.Sync(pkgbits.SyncCompLit) 2114 w.pos(lit) 2115 w.typ(typ) 2116 2117 if ptr, ok := types2.CoreType(typ).(*types2.Pointer); ok { 2118 typ = ptr.Elem() 2119 } 2120 var keyType, elemType types2.Type 2121 var structType *types2.Struct 2122 switch typ0 := typ; typ := types2.CoreType(typ).(type) { 2123 default: 2124 w.p.fatalf(lit, "unexpected composite literal type: %v", typ) 2125 case *types2.Array: 2126 elemType = typ.Elem() 2127 case *types2.Map: 2128 w.rtype(typ0) 2129 keyType, elemType = typ.Key(), typ.Elem() 2130 case *types2.Slice: 2131 elemType = typ.Elem() 2132 case *types2.Struct: 2133 structType = typ 2134 } 2135 2136 w.Len(len(lit.ElemList)) 2137 for i, elem := range lit.ElemList { 2138 elemType := elemType 2139 if structType != nil { 2140 if kv, ok := elem.(*syntax.KeyValueExpr); ok { 2141 // use position of expr.Key rather than of elem (which has position of ':') 2142 w.pos(kv.Key) 2143 i = fieldIndex(w.p.info, structType, kv.Key.(*syntax.Name)) 2144 elem = kv.Value 2145 } else { 2146 w.pos(elem) 2147 } 2148 elemType = structType.Field(i).Type() 2149 w.Len(i) 2150 } else { 2151 if kv, ok := elem.(*syntax.KeyValueExpr); w.Bool(ok) { 2152 // use position of expr.Key rather than of elem (which has position of ':') 2153 w.pos(kv.Key) 2154 w.implicitConvExpr(keyType, kv.Key) 2155 elem = kv.Value 2156 } 2157 } 2158 w.pos(elem) 2159 w.implicitConvExpr(elemType, elem) 2160 } 2161 } 2162 2163 func (w *writer) funcLit(expr *syntax.FuncLit) { 2164 sig := w.p.typeOf(expr).(*types2.Signature) 2165 2166 body, closureVars := w.p.bodyIdx(sig, expr.Body, w.dict) 2167 2168 w.Sync(pkgbits.SyncFuncLit) 2169 w.pos(expr) 2170 w.signature(sig) 2171 2172 w.Len(len(closureVars)) 2173 for _, cv := range closureVars { 2174 w.pos(cv.pos) 2175 w.useLocal(cv.pos, cv.var_) 2176 } 2177 2178 w.Reloc(pkgbits.RelocBody, body) 2179 } 2180 2181 type posVar struct { 2182 pos syntax.Pos 2183 var_ *types2.Var 2184 } 2185 2186 func (w *writer) exprList(expr syntax.Expr) { 2187 w.Sync(pkgbits.SyncExprList) 2188 w.exprs(unpackListExpr(expr)) 2189 } 2190 2191 func (w *writer) exprs(exprs []syntax.Expr) { 2192 w.Sync(pkgbits.SyncExprs) 2193 w.Len(len(exprs)) 2194 for _, expr := range exprs { 2195 w.expr(expr) 2196 } 2197 } 2198 2199 // rtype writes information so that the reader can construct an 2200 // expression of type *runtime._type representing typ. 2201 func (w *writer) rtype(typ types2.Type) { 2202 typ = types2.Default(typ) 2203 2204 info := w.p.typIdx(typ, w.dict) 2205 w.rtypeInfo(info) 2206 } 2207 2208 func (w *writer) rtypeInfo(info typeInfo) { 2209 w.Sync(pkgbits.SyncRType) 2210 2211 if w.Bool(info.derived) { 2212 w.Len(w.dict.rtypeIdx(info)) 2213 } else { 2214 w.typInfo(info) 2215 } 2216 } 2217 2218 // varDictIndex writes out information for populating DictIndex for 2219 // the ir.Name that will represent obj. 2220 func (w *writer) varDictIndex(obj *types2.Var) { 2221 info := w.p.typIdx(obj.Type(), w.dict) 2222 if w.Bool(info.derived) { 2223 w.Len(w.dict.rtypeIdx(info)) 2224 } 2225 } 2226 2227 func isUntyped(typ types2.Type) bool { 2228 basic, ok := typ.(*types2.Basic) 2229 return ok && basic.Info()&types2.IsUntyped != 0 2230 } 2231 2232 func isTuple(typ types2.Type) bool { 2233 _, ok := typ.(*types2.Tuple) 2234 return ok 2235 } 2236 2237 func (w *writer) itab(typ, iface types2.Type) { 2238 typ = types2.Default(typ) 2239 iface = types2.Default(iface) 2240 2241 typInfo := w.p.typIdx(typ, w.dict) 2242 ifaceInfo := w.p.typIdx(iface, w.dict) 2243 2244 w.rtypeInfo(typInfo) 2245 w.rtypeInfo(ifaceInfo) 2246 if w.Bool(typInfo.derived || ifaceInfo.derived) { 2247 w.Len(w.dict.itabIdx(typInfo, ifaceInfo)) 2248 } 2249 } 2250 2251 // convRTTI writes information so that the reader can construct 2252 // expressions for converting from src to dst. 2253 func (w *writer) convRTTI(src, dst types2.Type) { 2254 w.Sync(pkgbits.SyncConvRTTI) 2255 w.itab(src, dst) 2256 } 2257 2258 func (w *writer) exprType(iface types2.Type, typ syntax.Expr) { 2259 base.Assertf(iface == nil || isInterface(iface), "%v must be nil or an interface type", iface) 2260 2261 tv := w.p.typeAndValue(typ) 2262 assert(tv.IsType()) 2263 2264 w.Sync(pkgbits.SyncExprType) 2265 w.pos(typ) 2266 2267 if w.Bool(iface != nil && !iface.Underlying().(*types2.Interface).Empty()) { 2268 w.itab(tv.Type, iface) 2269 } else { 2270 w.rtype(tv.Type) 2271 2272 info := w.p.typIdx(tv.Type, w.dict) 2273 w.Bool(info.derived) 2274 } 2275 } 2276 2277 // isInterface reports whether typ is known to be an interface type. 2278 // If typ is a type parameter, then isInterface reports an internal 2279 // compiler error instead. 2280 func isInterface(typ types2.Type) bool { 2281 if _, ok := typ.(*types2.TypeParam); ok { 2282 // typ is a type parameter and may be instantiated as either a 2283 // concrete or interface type, so the writer can't depend on 2284 // knowing this. 2285 base.Fatalf("%v is a type parameter", typ) 2286 } 2287 2288 _, ok := typ.Underlying().(*types2.Interface) 2289 return ok 2290 } 2291 2292 // op writes an Op into the bitstream. 2293 func (w *writer) op(op ir.Op) { 2294 // TODO(mdempsky): Remove in favor of explicit codes? Would make 2295 // export data more stable against internal refactorings, but low 2296 // priority at the moment. 2297 assert(op != 0) 2298 w.Sync(pkgbits.SyncOp) 2299 w.Len(int(op)) 2300 } 2301 2302 // @@@ Package initialization 2303 2304 // Caution: This code is still clumsy, because toolstash -cmp is 2305 // particularly sensitive to it. 2306 2307 type typeDeclGen struct { 2308 *syntax.TypeDecl 2309 gen int 2310 2311 // Implicit type parameters in scope at this type declaration. 2312 implicits []*types2.TypeName 2313 } 2314 2315 type fileImports struct { 2316 importedEmbed, importedUnsafe bool 2317 } 2318 2319 // declCollector is a visitor type that collects compiler-needed 2320 // information about declarations that types2 doesn't track. 2321 // 2322 // Notably, it maps declared types and functions back to their 2323 // declaration statement, keeps track of implicit type parameters, and 2324 // assigns unique type "generation" numbers to local defined types. 2325 type declCollector struct { 2326 pw *pkgWriter 2327 typegen *int 2328 file *fileImports 2329 withinFunc bool 2330 implicits []*types2.TypeName 2331 } 2332 2333 func (c *declCollector) withTParams(obj types2.Object) *declCollector { 2334 tparams := objTypeParams(obj) 2335 n := tparams.Len() 2336 if n == 0 { 2337 return c 2338 } 2339 2340 copy := *c 2341 copy.implicits = copy.implicits[:len(copy.implicits):len(copy.implicits)] 2342 for i := 0; i < n; i++ { 2343 copy.implicits = append(copy.implicits, tparams.At(i).Obj()) 2344 } 2345 return © 2346 } 2347 2348 func (c *declCollector) Visit(n syntax.Node) syntax.Visitor { 2349 pw := c.pw 2350 2351 switch n := n.(type) { 2352 case *syntax.File: 2353 pw.checkPragmas(n.Pragma, ir.GoBuildPragma, false) 2354 2355 case *syntax.ImportDecl: 2356 pw.checkPragmas(n.Pragma, 0, false) 2357 2358 switch pkgNameOf(pw.info, n).Imported().Path() { 2359 case "embed": 2360 c.file.importedEmbed = true 2361 case "unsafe": 2362 c.file.importedUnsafe = true 2363 } 2364 2365 case *syntax.ConstDecl: 2366 pw.checkPragmas(n.Pragma, 0, false) 2367 2368 case *syntax.FuncDecl: 2369 pw.checkPragmas(n.Pragma, funcPragmas, false) 2370 2371 obj := pw.info.Defs[n.Name].(*types2.Func) 2372 pw.funDecls[obj] = n 2373 2374 return c.withTParams(obj) 2375 2376 case *syntax.TypeDecl: 2377 obj := pw.info.Defs[n.Name].(*types2.TypeName) 2378 d := typeDeclGen{TypeDecl: n, implicits: c.implicits} 2379 2380 if n.Alias { 2381 pw.checkPragmas(n.Pragma, 0, false) 2382 } else { 2383 pw.checkPragmas(n.Pragma, 0, false) 2384 2385 // Assign a unique ID to function-scoped defined types. 2386 if c.withinFunc { 2387 *c.typegen++ 2388 d.gen = *c.typegen 2389 } 2390 } 2391 2392 pw.typDecls[obj] = d 2393 2394 // TODO(mdempsky): Omit? Not strictly necessary; only matters for 2395 // type declarations within function literals within parameterized 2396 // type declarations, but types2 the function literals will be 2397 // constant folded away. 2398 return c.withTParams(obj) 2399 2400 case *syntax.VarDecl: 2401 pw.checkPragmas(n.Pragma, 0, true) 2402 2403 if p, ok := n.Pragma.(*pragmas); ok && len(p.Embeds) > 0 { 2404 if err := checkEmbed(n, c.file.importedEmbed, c.withinFunc); err != nil { 2405 pw.errorf(p.Embeds[0].Pos, "%s", err) 2406 } 2407 } 2408 2409 case *syntax.BlockStmt: 2410 if !c.withinFunc { 2411 copy := *c 2412 copy.withinFunc = true 2413 return © 2414 } 2415 } 2416 2417 return c 2418 } 2419 2420 func (pw *pkgWriter) collectDecls(noders []*noder) { 2421 var typegen int 2422 for _, p := range noders { 2423 var file fileImports 2424 2425 syntax.Walk(p.file, &declCollector{ 2426 pw: pw, 2427 typegen: &typegen, 2428 file: &file, 2429 }) 2430 2431 pw.cgoPragmas = append(pw.cgoPragmas, p.pragcgobuf...) 2432 2433 for _, l := range p.linknames { 2434 if !file.importedUnsafe { 2435 pw.errorf(l.pos, "//go:linkname only allowed in Go files that import \"unsafe\"") 2436 continue 2437 } 2438 2439 switch obj := pw.curpkg.Scope().Lookup(l.local).(type) { 2440 case *types2.Func, *types2.Var: 2441 if _, ok := pw.linknames[obj]; !ok { 2442 pw.linknames[obj] = l.remote 2443 } else { 2444 pw.errorf(l.pos, "duplicate //go:linkname for %s", l.local) 2445 } 2446 2447 default: 2448 if types.AllowsGoVersion(1, 18) { 2449 pw.errorf(l.pos, "//go:linkname must refer to declared function or variable") 2450 } 2451 } 2452 } 2453 } 2454 } 2455 2456 func (pw *pkgWriter) checkPragmas(p syntax.Pragma, allowed ir.PragmaFlag, embedOK bool) { 2457 if p == nil { 2458 return 2459 } 2460 pragma := p.(*pragmas) 2461 2462 for _, pos := range pragma.Pos { 2463 if pos.Flag&^allowed != 0 { 2464 pw.errorf(pos.Pos, "misplaced compiler directive") 2465 } 2466 } 2467 2468 if !embedOK { 2469 for _, e := range pragma.Embeds { 2470 pw.errorf(e.Pos, "misplaced go:embed directive") 2471 } 2472 } 2473 } 2474 2475 func (w *writer) pkgInit(noders []*noder) { 2476 w.Len(len(w.p.cgoPragmas)) 2477 for _, cgoPragma := range w.p.cgoPragmas { 2478 w.Strings(cgoPragma) 2479 } 2480 2481 w.Sync(pkgbits.SyncDecls) 2482 for _, p := range noders { 2483 for _, decl := range p.file.DeclList { 2484 w.pkgDecl(decl) 2485 } 2486 } 2487 w.Code(declEnd) 2488 2489 w.Sync(pkgbits.SyncEOF) 2490 } 2491 2492 func (w *writer) pkgDecl(decl syntax.Decl) { 2493 switch decl := decl.(type) { 2494 default: 2495 w.p.unexpected("declaration", decl) 2496 2497 case *syntax.ImportDecl: 2498 2499 case *syntax.ConstDecl: 2500 w.Code(declOther) 2501 w.pkgObjs(decl.NameList...) 2502 2503 case *syntax.FuncDecl: 2504 if decl.Name.Value == "_" { 2505 break // skip blank functions 2506 } 2507 2508 obj := w.p.info.Defs[decl.Name].(*types2.Func) 2509 sig := obj.Type().(*types2.Signature) 2510 2511 if sig.RecvTypeParams() != nil || sig.TypeParams() != nil { 2512 break // skip generic functions 2513 } 2514 2515 if recv := sig.Recv(); recv != nil { 2516 w.Code(declMethod) 2517 w.typ(recvBase(recv)) 2518 w.selector(obj) 2519 break 2520 } 2521 2522 w.Code(declFunc) 2523 w.pkgObjs(decl.Name) 2524 2525 case *syntax.TypeDecl: 2526 if len(decl.TParamList) != 0 { 2527 break // skip generic type decls 2528 } 2529 2530 if decl.Name.Value == "_" { 2531 break // skip blank type decls 2532 } 2533 2534 name := w.p.info.Defs[decl.Name].(*types2.TypeName) 2535 // Skip type declarations for interfaces that are only usable as 2536 // type parameter bounds. 2537 if iface, ok := name.Type().Underlying().(*types2.Interface); ok && !iface.IsMethodSet() { 2538 break 2539 } 2540 2541 w.Code(declOther) 2542 w.pkgObjs(decl.Name) 2543 2544 case *syntax.VarDecl: 2545 w.Code(declVar) 2546 w.pos(decl) 2547 w.pkgObjs(decl.NameList...) 2548 2549 // TODO(mdempsky): It would make sense to use multiExpr here, but 2550 // that results in IR that confuses pkginit/initorder.go. So we 2551 // continue using exprList, and let typecheck handle inserting any 2552 // implicit conversions. That's okay though, because package-scope 2553 // assignments never require dictionaries. 2554 w.exprList(decl.Values) 2555 2556 var embeds []pragmaEmbed 2557 if p, ok := decl.Pragma.(*pragmas); ok { 2558 embeds = p.Embeds 2559 } 2560 w.Len(len(embeds)) 2561 for _, embed := range embeds { 2562 w.pos(embed.Pos) 2563 w.Strings(embed.Patterns) 2564 } 2565 } 2566 } 2567 2568 func (w *writer) pkgObjs(names ...*syntax.Name) { 2569 w.Sync(pkgbits.SyncDeclNames) 2570 w.Len(len(names)) 2571 2572 for _, name := range names { 2573 obj, ok := w.p.info.Defs[name] 2574 assert(ok) 2575 2576 w.Sync(pkgbits.SyncDeclName) 2577 w.obj(obj, nil) 2578 } 2579 } 2580 2581 // @@@ Helpers 2582 2583 // hasImplicitTypeParams reports whether obj is a defined type with 2584 // implicit type parameters (e.g., declared within a generic function 2585 // or method). 2586 func (p *pkgWriter) hasImplicitTypeParams(obj *types2.TypeName) bool { 2587 if obj.Pkg() == p.curpkg { 2588 decl, ok := p.typDecls[obj] 2589 assert(ok) 2590 if len(decl.implicits) != 0 { 2591 return true 2592 } 2593 } 2594 return false 2595 } 2596 2597 // isDefinedType reports whether obj is a defined type. 2598 func isDefinedType(obj types2.Object) bool { 2599 if obj, ok := obj.(*types2.TypeName); ok { 2600 return !obj.IsAlias() 2601 } 2602 return false 2603 } 2604 2605 // isGlobal reports whether obj was declared at package scope. 2606 // 2607 // Caveat: blank objects are not declared. 2608 func isGlobal(obj types2.Object) bool { 2609 return obj.Parent() == obj.Pkg().Scope() 2610 } 2611 2612 // lookupObj returns the object that expr refers to, if any. If expr 2613 // is an explicit instantiation of a generic object, then the instance 2614 // object is returned as well. 2615 func lookupObj(p *pkgWriter, expr syntax.Expr) (obj types2.Object, inst types2.Instance) { 2616 if index, ok := expr.(*syntax.IndexExpr); ok { 2617 args := unpackListExpr(index.Index) 2618 if len(args) == 1 { 2619 tv := p.typeAndValue(args[0]) 2620 if tv.IsValue() { 2621 return // normal index expression 2622 } 2623 } 2624 2625 expr = index.X 2626 } 2627 2628 // Strip package qualifier, if present. 2629 if sel, ok := expr.(*syntax.SelectorExpr); ok { 2630 if !isPkgQual(p.info, sel) { 2631 return // normal selector expression 2632 } 2633 expr = sel.Sel 2634 } 2635 2636 if name, ok := expr.(*syntax.Name); ok { 2637 obj = p.info.Uses[name] 2638 inst = p.info.Instances[name] 2639 } 2640 return 2641 } 2642 2643 // isPkgQual reports whether the given selector expression is a 2644 // package-qualified identifier. 2645 func isPkgQual(info *types2.Info, sel *syntax.SelectorExpr) bool { 2646 if name, ok := sel.X.(*syntax.Name); ok { 2647 _, isPkgName := info.Uses[name].(*types2.PkgName) 2648 return isPkgName 2649 } 2650 return false 2651 } 2652 2653 // isNil reports whether expr is a (possibly parenthesized) reference 2654 // to the predeclared nil value. 2655 func isNil(p *pkgWriter, expr syntax.Expr) bool { 2656 tv := p.typeAndValue(expr) 2657 return tv.IsNil() 2658 } 2659 2660 // recvBase returns the base type for the given receiver parameter. 2661 func recvBase(recv *types2.Var) *types2.Named { 2662 typ := recv.Type() 2663 if ptr, ok := typ.(*types2.Pointer); ok { 2664 typ = ptr.Elem() 2665 } 2666 return typ.(*types2.Named) 2667 } 2668 2669 // namesAsExpr returns a list of names as a syntax.Expr. 2670 func namesAsExpr(names []*syntax.Name) syntax.Expr { 2671 if len(names) == 1 { 2672 return names[0] 2673 } 2674 2675 exprs := make([]syntax.Expr, len(names)) 2676 for i, name := range names { 2677 exprs[i] = name 2678 } 2679 return &syntax.ListExpr{ElemList: exprs} 2680 } 2681 2682 // fieldIndex returns the index of the struct field named by key. 2683 func fieldIndex(info *types2.Info, str *types2.Struct, key *syntax.Name) int { 2684 field := info.Uses[key].(*types2.Var) 2685 2686 for i := 0; i < str.NumFields(); i++ { 2687 if str.Field(i) == field { 2688 return i 2689 } 2690 } 2691 2692 panic(fmt.Sprintf("%s: %v is not a field of %v", key.Pos(), field, str)) 2693 } 2694 2695 // objTypeParams returns the type parameters on the given object. 2696 func objTypeParams(obj types2.Object) *types2.TypeParamList { 2697 switch obj := obj.(type) { 2698 case *types2.Func: 2699 sig := obj.Type().(*types2.Signature) 2700 if sig.Recv() != nil { 2701 return sig.RecvTypeParams() 2702 } 2703 return sig.TypeParams() 2704 case *types2.TypeName: 2705 if !obj.IsAlias() { 2706 return obj.Type().(*types2.Named).TypeParams() 2707 } 2708 } 2709 return nil 2710 } 2711 2712 // splitNamed decomposes a use of a defined type into its original 2713 // type definition and the type arguments used to instantiate it. 2714 func splitNamed(typ *types2.Named) (*types2.TypeName, *types2.TypeList) { 2715 base.Assertf(typ.TypeParams().Len() == typ.TypeArgs().Len(), "use of uninstantiated type: %v", typ) 2716 2717 orig := typ.Origin() 2718 base.Assertf(orig.TypeArgs() == nil, "origin %v of %v has type arguments", orig, typ) 2719 base.Assertf(typ.Obj() == orig.Obj(), "%v has object %v, but %v has object %v", typ, typ.Obj(), orig, orig.Obj()) 2720 2721 return typ.Obj(), typ.TypeArgs() 2722 } 2723 2724 func asPragmaFlag(p syntax.Pragma) ir.PragmaFlag { 2725 if p == nil { 2726 return 0 2727 } 2728 return p.(*pragmas).Flag 2729 } 2730 2731 // isPtrTo reports whether from is the type *to. 2732 func isPtrTo(from, to types2.Type) bool { 2733 ptr, ok := from.(*types2.Pointer) 2734 return ok && types2.Identical(ptr.Elem(), to) 2735 }