1// UNREVIEWED 2 3// Copyright 2021 The Go Authors. All rights reserved. 4// Use of this source code is governed by a BSD-style 5// license that can be found in the LICENSE file. 6 7package noder 8 9import ( 10 "fmt" 11 "go/constant" 12 13 "cmd/compile/internal/base" 14 "cmd/compile/internal/ir" 15 "cmd/compile/internal/syntax" 16 "cmd/compile/internal/types2" 17) 18 19type pkgWriter struct { 20 pkgEncoder 21 22 m posMap 23 curpkg *types2.Package 24 info *types2.Info 25 26 posBasesIdx map[*syntax.PosBase]int 27 pkgsIdx map[*types2.Package]int 28 typsIdx map[types2.Type]int 29 globalsIdx map[types2.Object]int 30 31 funDecls map[*types2.Func]*syntax.FuncDecl 32 typDecls map[*types2.TypeName]typeDeclGen 33 34 linknames map[types2.Object]string 35 cgoPragmas [][]string 36 37 dups dupTypes 38} 39 40func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info) *pkgWriter { 41 return &pkgWriter{ 42 pkgEncoder: newPkgEncoder(), 43 44 m: m, 45 curpkg: pkg, 46 info: info, 47 48 pkgsIdx: make(map[*types2.Package]int), 49 globalsIdx: make(map[types2.Object]int), 50 typsIdx: make(map[types2.Type]int), 51 52 posBasesIdx: make(map[*syntax.PosBase]int), 53 54 funDecls: make(map[*types2.Func]*syntax.FuncDecl), 55 typDecls: make(map[*types2.TypeName]typeDeclGen), 56 57 linknames: make(map[types2.Object]string), 58 } 59} 60 61func (pw *pkgWriter) errorf(p poser, msg string, args ...interface{}) { 62 base.ErrorfAt(pw.m.pos(p), msg, args...) 63} 64 65func (pw *pkgWriter) fatalf(p poser, msg string, args ...interface{}) { 66 base.FatalfAt(pw.m.pos(p), msg, args...) 67} 68 69func (pw *pkgWriter) unexpected(what string, p poser) { 70 pw.fatalf(p, "unexpected %s: %v (%T)", what, p, p) 71} 72 73type writer struct { 74 p *pkgWriter 75 76 encoder 77 78 // TODO(mdempsky): We should be able to prune localsIdx whenever a 79 // scope closes, and then maybe we can just use the same map for 80 // storing the TypeParams too (as their TypeName instead). 81 82 // variables declared within this function 83 localsIdx map[*types2.Var]int 84 85 closureVars []posObj 86 closureVarsIdx map[*types2.Var]int 87 88 dict *writerDict 89 derived bool 90} 91 92// A writerDict tracks types and objects that are used by a declaration. 93type writerDict struct { 94 implicits []*types2.TypeName 95 96 // derived is a slice of type indices for computing derived types 97 // (i.e., types that depend on the declaration's type parameters). 98 derived []derivedInfo 99 100 // derivedIdx maps a Type to its corresponding index within the 101 // derived slice, if present. 102 derivedIdx map[types2.Type]int 103 104 // funcs lists references to generic functions that were 105 // instantiated with derived types (i.e., that require 106 // sub-dictionaries when called at run time). 107 funcs []objInfo 108} 109 110type derivedInfo struct { 111 idx int 112 needed bool 113} 114 115type typeInfo struct { 116 idx int 117 derived bool 118} 119 120type objInfo struct { 121 idx int // index for the generic function declaration 122 explicits []typeInfo // info for the type arguments 123} 124 125func (info objInfo) anyDerived() bool { 126 for _, explicit := range info.explicits { 127 if explicit.derived { 128 return true 129 } 130 } 131 return false 132} 133 134func (info objInfo) equals(other objInfo) bool { 135 if info.idx != other.idx { 136 return false 137 } 138 assert(len(info.explicits) == len(other.explicits)) 139 for i, targ := range info.explicits { 140 if targ != other.explicits[i] { 141 return false 142 } 143 } 144 return true 145} 146 147func (pw *pkgWriter) newWriter(k reloc, marker syncMarker) *writer { 148 return &writer{ 149 encoder: pw.newEncoder(k, marker), 150 p: pw, 151 } 152} 153 154// @@@ Positions 155 156func (w *writer) pos(p poser) { 157 w.sync(syncPos) 158 pos := p.Pos() 159 160 // TODO(mdempsky): Track down the remaining cases here and fix them. 161 if !w.bool(pos.IsKnown()) { 162 return 163 } 164 165 // TODO(mdempsky): Delta encoding. Also, if there's a b-side, update 166 // its position base too (but not vice versa!). 167 w.posBase(pos.Base()) 168 w.uint(pos.Line()) 169 w.uint(pos.Col()) 170} 171 172func (w *writer) posBase(b *syntax.PosBase) { 173 w.reloc(relocPosBase, w.p.posBaseIdx(b)) 174} 175 176func (pw *pkgWriter) posBaseIdx(b *syntax.PosBase) int { 177 if idx, ok := pw.posBasesIdx[b]; ok { 178 return idx 179 } 180 181 w := pw.newWriter(relocPosBase, syncPosBase) 182 w.p.posBasesIdx[b] = w.idx 183 184 w.string(trimFilename(b)) 185 186 if !w.bool(b.IsFileBase()) { 187 w.pos(b) 188 w.uint(b.Line()) 189 w.uint(b.Col()) 190 } 191 192 return w.flush() 193} 194 195// @@@ Packages 196 197func (w *writer) pkg(pkg *types2.Package) { 198 w.sync(syncPkg) 199 w.reloc(relocPkg, w.p.pkgIdx(pkg)) 200} 201 202func (pw *pkgWriter) pkgIdx(pkg *types2.Package) int { 203 if idx, ok := pw.pkgsIdx[pkg]; ok { 204 return idx 205 } 206 207 w := pw.newWriter(relocPkg, syncPkgDef) 208 pw.pkgsIdx[pkg] = w.idx 209 210 if pkg == nil { 211 w.string("builtin") 212 } else { 213 var path string 214 if pkg != w.p.curpkg { 215 path = pkg.Path() 216 } 217 w.string(path) 218 w.string(pkg.Name()) 219 w.len(pkg.Height()) 220 221 w.len(len(pkg.Imports())) 222 for _, imp := range pkg.Imports() { 223 w.pkg(imp) 224 } 225 } 226 227 return w.flush() 228} 229 230// @@@ Types 231 232var anyTypeName = types2.Universe.Lookup("any").(*types2.TypeName) 233 234func (w *writer) typ(typ types2.Type) { 235 w.typInfo(w.p.typIdx(typ, w.dict)) 236} 237 238func (w *writer) typInfo(info typeInfo) { 239 w.sync(syncType) 240 if w.bool(info.derived) { 241 w.len(info.idx) 242 w.derived = true 243 } else { 244 w.reloc(relocType, info.idx) 245 } 246} 247 248// typIdx returns the index where the export data description of type 249// can be read back in. If no such index exists yet, it's created. 250// 251// typIdx also reports whether typ is a derived type; that is, whether 252// its identity depends on type parameters. 253func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo { 254 if quirksMode() { 255 typ = pw.dups.orig(typ) 256 } 257 258 if idx, ok := pw.typsIdx[typ]; ok { 259 return typeInfo{idx: idx, derived: false} 260 } 261 if dict != nil { 262 if idx, ok := dict.derivedIdx[typ]; ok { 263 return typeInfo{idx: idx, derived: true} 264 } 265 } 266 267 w := pw.newWriter(relocType, syncTypeIdx) 268 w.dict = dict 269 270 switch typ := typ.(type) { 271 default: 272 base.Fatalf("unexpected type: %v (%T)", typ, typ) 273 274 case *types2.Basic: 275 switch kind := typ.Kind(); { 276 case kind == types2.Invalid: 277 base.Fatalf("unexpected types2.Invalid") 278 279 case types2.Typ[kind] == typ: 280 w.code(typeBasic) 281 w.len(int(kind)) 282 283 default: 284 // Handle "byte" and "rune" as references to their TypeName. 285 obj := types2.Universe.Lookup(typ.Name()) 286 assert(obj.Type() == typ) 287 288 w.code(typeNamed) 289 w.obj(obj, nil) 290 } 291 292 case *types2.Named: 293 // Type aliases can refer to uninstantiated generic types, so we 294 // might see len(TParams) != 0 && len(TArgs) == 0 here. 295 // TODO(mdempsky): Revisit after #46477 is resolved. 296 assert(typ.TypeParams().Len() == typ.TypeArgs().Len() || typ.TypeArgs().Len() == 0) 297 298 // TODO(mdempsky): Why do we need to loop here? 299 orig := typ 300 for orig.TypeArgs() != nil { 301 orig = orig.Origin() 302 } 303 304 w.code(typeNamed) 305 w.obj(orig.Obj(), typ.TypeArgs()) 306 307 case *types2.TypeParam: 308 index := func() int { 309 for idx, name := range w.dict.implicits { 310 if name.Type().(*types2.TypeParam) == typ { 311 return idx 312 } 313 } 314 315 return len(w.dict.implicits) + typ.Index() 316 }() 317 318 w.derived = true 319 w.code(typeTypeParam) 320 w.len(index) 321 322 case *types2.Array: 323 w.code(typeArray) 324 w.uint64(uint64(typ.Len())) 325 w.typ(typ.Elem()) 326 327 case *types2.Chan: 328 w.code(typeChan) 329 w.len(int(typ.Dir())) 330 w.typ(typ.Elem()) 331 332 case *types2.Map: 333 w.code(typeMap) 334 w.typ(typ.Key()) 335 w.typ(typ.Elem()) 336 337 case *types2.Pointer: 338 w.code(typePointer) 339 w.typ(typ.Elem()) 340 341 case *types2.Signature: 342 base.Assertf(typ.TypeParams() == nil, "unexpected type params: %v", typ) 343 w.code(typeSignature) 344 w.signature(typ) 345 346 case *types2.Slice: 347 w.code(typeSlice) 348 w.typ(typ.Elem()) 349 350 case *types2.Struct: 351 w.code(typeStruct) 352 w.structType(typ) 353 354 case *types2.Interface: 355 if typ == anyTypeName.Type() { 356 w.code(typeNamed) 357 w.obj(anyTypeName, nil) 358 break 359 } 360 361 w.code(typeInterface) 362 w.interfaceType(typ) 363 364 case *types2.Union: 365 w.code(typeUnion) 366 w.unionType(typ) 367 } 368 369 if w.derived { 370 idx := len(dict.derived) 371 dict.derived = append(dict.derived, derivedInfo{idx: w.flush()}) 372 dict.derivedIdx[typ] = idx 373 return typeInfo{idx: idx, derived: true} 374 } 375 376 pw.typsIdx[typ] = w.idx 377 return typeInfo{idx: w.flush(), derived: false} 378} 379 380func (w *writer) structType(typ *types2.Struct) { 381 w.len(typ.NumFields()) 382 for i := 0; i < typ.NumFields(); i++ { 383 f := typ.Field(i) 384 w.pos(f) 385 w.selector(f) 386 w.typ(f.Type()) 387 w.string(typ.Tag(i)) 388 w.bool(f.Embedded()) 389 } 390} 391 392func (w *writer) unionType(typ *types2.Union) { 393 w.len(typ.Len()) 394 for i := 0; i < typ.Len(); i++ { 395 t := typ.Term(i) 396 w.bool(t.Tilde()) 397 w.typ(t.Type()) 398 } 399} 400 401func (w *writer) interfaceType(typ *types2.Interface) { 402 w.len(typ.NumExplicitMethods()) 403 w.len(typ.NumEmbeddeds()) 404 405 for i := 0; i < typ.NumExplicitMethods(); i++ { 406 m := typ.ExplicitMethod(i) 407 sig := m.Type().(*types2.Signature) 408 assert(sig.TypeParams() == nil) 409 410 w.pos(m) 411 w.selector(m) 412 w.signature(sig) 413 } 414 415 for i := 0; i < typ.NumEmbeddeds(); i++ { 416 w.typ(typ.EmbeddedType(i)) 417 } 418} 419 420func (w *writer) signature(sig *types2.Signature) { 421 w.sync(syncSignature) 422 w.params(sig.Params()) 423 w.params(sig.Results()) 424 w.bool(sig.Variadic()) 425} 426 427func (w *writer) params(typ *types2.Tuple) { 428 w.sync(syncParams) 429 w.len(typ.Len()) 430 for i := 0; i < typ.Len(); i++ { 431 w.param(typ.At(i)) 432 } 433} 434 435func (w *writer) param(param *types2.Var) { 436 w.sync(syncParam) 437 w.pos(param) 438 w.localIdent(param) 439 w.typ(param.Type()) 440} 441 442// @@@ Objects 443 444func (w *writer) obj(obj types2.Object, explicits *types2.TypeList) { 445 explicitInfos := make([]typeInfo, explicits.Len()) 446 for i := range explicitInfos { 447 explicitInfos[i] = w.p.typIdx(explicits.At(i), w.dict) 448 } 449 info := objInfo{idx: w.p.objIdx(obj), explicits: explicitInfos} 450 451 if _, ok := obj.(*types2.Func); ok && info.anyDerived() { 452 idx := -1 453 for i, prev := range w.dict.funcs { 454 if prev.equals(info) { 455 idx = i 456 } 457 } 458 if idx < 0 { 459 idx = len(w.dict.funcs) 460 w.dict.funcs = append(w.dict.funcs, info) 461 } 462 463 // TODO(mdempsky): Push up into expr; this shouldn't appear 464 // outside of expression context. 465 w.sync(syncObject) 466 w.bool(true) 467 w.len(idx) 468 return 469 } 470 471 // TODO(mdempsky): Push up into typIdx; this shouldn't be needed 472 // except while writing out types. 473 if isDefinedType(obj) && obj.Pkg() == w.p.curpkg { 474 decl, ok := w.p.typDecls[obj.(*types2.TypeName)] 475 assert(ok) 476 if len(decl.implicits) != 0 { 477 w.derived = true 478 } 479 } 480 481 w.sync(syncObject) 482 w.bool(false) 483 w.reloc(relocObj, info.idx) 484 485 w.len(len(info.explicits)) 486 for _, info := range info.explicits { 487 w.typInfo(info) 488 } 489} 490 491func (pw *pkgWriter) objIdx(obj types2.Object) int { 492 if idx, ok := pw.globalsIdx[obj]; ok { 493 return idx 494 } 495 496 dict := &writerDict{ 497 derivedIdx: make(map[types2.Type]int), 498 } 499 500 if isDefinedType(obj) && obj.Pkg() == pw.curpkg { 501 decl, ok := pw.typDecls[obj.(*types2.TypeName)] 502 assert(ok) 503 dict.implicits = decl.implicits 504 } 505 506 w := pw.newWriter(relocObj, syncObject1) 507 wext := pw.newWriter(relocObjExt, syncObject1) 508 wname := pw.newWriter(relocName, syncObject1) 509 wdict := pw.newWriter(relocObjDict, syncObject1) 510 511 pw.globalsIdx[obj] = w.idx // break cycles 512 assert(wext.idx == w.idx) 513 assert(wname.idx == w.idx) 514 assert(wdict.idx == w.idx) 515 516 w.dict = dict 517 wext.dict = dict 518 519 code := w.doObj(wext, obj) 520 w.flush() 521 wext.flush() 522 523 wname.qualifiedIdent(obj) 524 wname.code(code) 525 wname.flush() 526 527 wdict.objDict(obj, w.dict) 528 wdict.flush() 529 530 return w.idx 531} 532 533func (w *writer) doObj(wext *writer, obj types2.Object) codeObj { 534 if obj.Pkg() != w.p.curpkg { 535 return objStub 536 } 537 538 switch obj := obj.(type) { 539 default: 540 w.p.unexpected("object", obj) 541 panic("unreachable") 542 543 case *types2.Const: 544 w.pos(obj) 545 w.typ(obj.Type()) 546 w.value(obj.Val()) 547 return objConst 548 549 case *types2.Func: 550 decl, ok := w.p.funDecls[obj] 551 assert(ok) 552 sig := obj.Type().(*types2.Signature) 553 554 w.pos(obj) 555 w.typeParamNames(sig.TypeParams()) 556 w.signature(sig) 557 w.pos(decl) 558 wext.funcExt(obj) 559 return objFunc 560 561 case *types2.TypeName: 562 decl, ok := w.p.typDecls[obj] 563 assert(ok) 564 565 if obj.IsAlias() { 566 w.pos(obj) 567 w.typ(obj.Type()) 568 return objAlias 569 } 570 571 named := obj.Type().(*types2.Named) 572 assert(named.TypeArgs() == nil) 573 574 w.pos(obj) 575 w.typeParamNames(named.TypeParams()) 576 wext.typeExt(obj) 577 w.typExpr(decl.Type) 578 579 w.len(named.NumMethods()) 580 for i := 0; i < named.NumMethods(); i++ { 581 w.method(wext, named.Method(i)) 582 } 583 584 return objType 585 586 case *types2.Var: 587 w.pos(obj) 588 w.typ(obj.Type()) 589 wext.varExt(obj) 590 return objVar 591 } 592} 593 594// typExpr writes the type represented by the given expression. 595func (w *writer) typExpr(expr syntax.Expr) { 596 tv, ok := w.p.info.Types[expr] 597 assert(ok) 598 assert(tv.IsType()) 599 w.typ(tv.Type) 600} 601 602// objDict writes the dictionary needed for reading the given object. 603func (w *writer) objDict(obj types2.Object, dict *writerDict) { 604 // TODO(mdempsky): Split objDict into multiple entries? reader.go 605 // doesn't care about the type parameter bounds, and reader2.go 606 // doesn't care about referenced functions. 607 608 w.dict = dict // TODO(mdempsky): This is a bit sketchy. 609 610 w.len(len(dict.implicits)) 611 612 tparams := objTypeParams(obj) 613 ntparams := tparams.Len() 614 w.len(ntparams) 615 for i := 0; i < ntparams; i++ { 616 w.typ(tparams.At(i).Constraint()) 617 } 618 619 nderived := len(dict.derived) 620 w.len(nderived) 621 for _, typ := range dict.derived { 622 w.reloc(relocType, typ.idx) 623 w.bool(typ.needed) 624 } 625 626 nfuncs := len(dict.funcs) 627 w.len(nfuncs) 628 for _, fn := range dict.funcs { 629 w.reloc(relocObj, fn.idx) 630 w.len(len(fn.explicits)) 631 for _, targ := range fn.explicits { 632 w.typInfo(targ) 633 } 634 } 635 636 assert(len(dict.derived) == nderived) 637 assert(len(dict.funcs) == nfuncs) 638} 639 640func (w *writer) typeParamNames(tparams *types2.TypeParamList) { 641 w.sync(syncTypeParamNames) 642 643 ntparams := tparams.Len() 644 for i := 0; i < ntparams; i++ { 645 tparam := tparams.At(i).Obj() 646 w.pos(tparam) 647 w.localIdent(tparam) 648 } 649} 650 651func (w *writer) method(wext *writer, meth *types2.Func) { 652 decl, ok := w.p.funDecls[meth] 653 assert(ok) 654 sig := meth.Type().(*types2.Signature) 655 656 w.sync(syncMethod) 657 w.pos(meth) 658 w.selector(meth) 659 w.typeParamNames(sig.RecvTypeParams()) 660 w.param(sig.Recv()) 661 w.signature(sig) 662 663 w.pos(decl) // XXX: Hack to workaround linker limitations. 664 wext.funcExt(meth) 665} 666 667// qualifiedIdent writes out the name of an object declared at package 668// scope. (For now, it's also used to refer to local defined types.) 669func (w *writer) qualifiedIdent(obj types2.Object) { 670 w.sync(syncSym) 671 672 name := obj.Name() 673 if isDefinedType(obj) && obj.Pkg() == w.p.curpkg { 674 decl, ok := w.p.typDecls[obj.(*types2.TypeName)] 675 assert(ok) 676 if decl.gen != 0 { 677 // TODO(mdempsky): Find a better solution than embedding middle 678 // dot in the symbol name; this is terrible. 679 name = fmt.Sprintf("%s·%v", name, decl.gen) 680 } 681 } 682 683 w.pkg(obj.Pkg()) 684 w.string(name) 685} 686 687// TODO(mdempsky): We should be able to omit pkg from both localIdent 688// and selector, because they should always be known from context. 689// However, past frustrations with this optimization in iexport make 690// me a little nervous to try it again. 691 692// localIdent writes the name of a locally declared object (i.e., 693// objects that can only be accessed by name, within the context of a 694// particular function). 695func (w *writer) localIdent(obj types2.Object) { 696 assert(!isGlobal(obj)) 697 w.sync(syncLocalIdent) 698 w.pkg(obj.Pkg()) 699 w.string(obj.Name()) 700} 701 702// selector writes the name of a field or method (i.e., objects that 703// can only be accessed using selector expressions). 704func (w *writer) selector(obj types2.Object) { 705 w.sync(syncSelector) 706 w.pkg(obj.Pkg()) 707 w.string(obj.Name()) 708} 709 710// @@@ Compiler extensions 711 712func (w *writer) funcExt(obj *types2.Func) { 713 decl, ok := w.p.funDecls[obj] 714 assert(ok) 715 716 // TODO(mdempsky): Extend these pragma validation flags to account 717 // for generics. E.g., linkname probably doesn't make sense at 718 // least. 719 720 pragma := asPragmaFlag(decl.Pragma) 721 if pragma&ir.Systemstack != 0 && pragma&ir.Nosplit != 0 { 722 w.p.errorf(decl, "go:nosplit and go:systemstack cannot be combined") 723 } 724 725 if decl.Body != nil { 726 if pragma&ir.Noescape != 0 { 727 w.p.errorf(decl, "can only use //go:noescape with external func implementations") 728 } 729 } else { 730 if base.Flag.Complete || decl.Name.Value == "init" { 731 // Linknamed functions are allowed to have no body. Hopefully 732 // the linkname target has a body. See issue 23311. 733 if _, ok := w.p.linknames[obj]; !ok { 734 w.p.errorf(decl, "missing function body") 735 } 736 } 737 } 738 739 sig, block := obj.Type().(*types2.Signature), decl.Body 740 body, closureVars := w.p.bodyIdx(w.p.curpkg, sig, block, w.dict) 741 assert(len(closureVars) == 0) 742 743 w.sync(syncFuncExt) 744 w.pragmaFlag(pragma) 745 w.linkname(obj) 746 w.bool(false) // stub extension 747 w.reloc(relocBody, body) 748 w.sync(syncEOF) 749} 750 751func (w *writer) typeExt(obj *types2.TypeName) { 752 decl, ok := w.p.typDecls[obj] 753 assert(ok) 754 755 w.sync(syncTypeExt) 756 757 w.pragmaFlag(asPragmaFlag(decl.Pragma)) 758 759 // No LSym.SymIdx info yet. 760 w.int64(-1) 761 w.int64(-1) 762} 763 764func (w *writer) varExt(obj *types2.Var) { 765 w.sync(syncVarExt) 766 w.linkname(obj) 767} 768 769func (w *writer) linkname(obj types2.Object) { 770 w.sync(syncLinkname) 771 w.int64(-1) 772 w.string(w.p.linknames[obj]) 773} 774 775func (w *writer) pragmaFlag(p ir.PragmaFlag) { 776 w.sync(syncPragma) 777 w.int(int(p)) 778} 779 780// @@@ Function bodies 781 782func (pw *pkgWriter) bodyIdx(pkg *types2.Package, sig *types2.Signature, block *syntax.BlockStmt, dict *writerDict) (idx int, closureVars []posObj) { 783 w := pw.newWriter(relocBody, syncFuncBody) 784 w.dict = dict 785 786 w.funcargs(sig) 787 if w.bool(block != nil) { 788 w.stmts(block.List) 789 w.pos(block.Rbrace) 790 } 791 792 return w.flush(), w.closureVars 793} 794 795func (w *writer) funcargs(sig *types2.Signature) { 796 do := func(params *types2.Tuple, result bool) { 797 for i := 0; i < params.Len(); i++ { 798 w.funcarg(params.At(i), result) 799 } 800 } 801 802 if recv := sig.Recv(); recv != nil { 803 w.funcarg(recv, false) 804 } 805 do(sig.Params(), false) 806 do(sig.Results(), true) 807} 808 809func (w *writer) funcarg(param *types2.Var, result bool) { 810 if param.Name() != "" || result { 811 w.addLocal(param) 812 } 813} 814 815func (w *writer) addLocal(obj *types2.Var) { 816 w.sync(syncAddLocal) 817 idx := len(w.localsIdx) 818 if enableSync { 819 w.int(idx) 820 } 821 if w.localsIdx == nil { 822 w.localsIdx = make(map[*types2.Var]int) 823 } 824 w.localsIdx[obj] = idx 825} 826 827func (w *writer) useLocal(pos syntax.Pos, obj *types2.Var) { 828 w.sync(syncUseObjLocal) 829 830 if idx, ok := w.localsIdx[obj]; w.bool(ok) { 831 w.len(idx) 832 return 833 } 834 835 idx, ok := w.closureVarsIdx[obj] 836 if !ok { 837 if w.closureVarsIdx == nil { 838 w.closureVarsIdx = make(map[*types2.Var]int) 839 } 840 idx = len(w.closureVars) 841 w.closureVars = append(w.closureVars, posObj{pos, obj}) 842 w.closureVarsIdx[obj] = idx 843 } 844 w.len(idx) 845} 846 847func (w *writer) openScope(pos syntax.Pos) { 848 w.sync(syncOpenScope) 849 w.pos(pos) 850} 851 852func (w *writer) closeScope(pos syntax.Pos) { 853 w.sync(syncCloseScope) 854 w.pos(pos) 855 w.closeAnotherScope() 856} 857 858func (w *writer) closeAnotherScope() { 859 w.sync(syncCloseAnotherScope) 860} 861 862// @@@ Statements 863 864func (w *writer) stmt(stmt syntax.Stmt) { 865 var stmts []syntax.Stmt 866 if stmt != nil { 867 stmts = []syntax.Stmt{stmt} 868 } 869 w.stmts(stmts) 870} 871 872func (w *writer) stmts(stmts []syntax.Stmt) { 873 w.sync(syncStmts) 874 for _, stmt := range stmts { 875 w.stmt1(stmt) 876 } 877 w.code(stmtEnd) 878 w.sync(syncStmtsEnd) 879} 880 881func (w *writer) stmt1(stmt syntax.Stmt) { 882 switch stmt := stmt.(type) { 883 default: 884 w.p.unexpected("statement", stmt) 885 886 case nil, *syntax.EmptyStmt: 887 return 888 889 case *syntax.AssignStmt: 890 switch { 891 case stmt.Rhs == nil: 892 w.code(stmtIncDec) 893 w.op(binOps[stmt.Op]) 894 w.expr(stmt.Lhs) 895 w.pos(stmt) 896 897 case stmt.Op != 0 && stmt.Op != syntax.Def: 898 w.code(stmtAssignOp) 899 w.op(binOps[stmt.Op]) 900 w.expr(stmt.Lhs) 901 w.pos(stmt) 902 w.expr(stmt.Rhs) 903 904 default: 905 w.code(stmtAssign) 906 w.pos(stmt) 907 w.exprList(stmt.Rhs) 908 w.assignList(stmt.Lhs) 909 } 910 911 case *syntax.BlockStmt: 912 w.code(stmtBlock) 913 w.blockStmt(stmt) 914 915 case *syntax.BranchStmt: 916 w.code(stmtBranch) 917 w.pos(stmt) 918 w.op(branchOps[stmt.Tok]) 919 w.optLabel(stmt.Label) 920 921 case *syntax.CallStmt: 922 w.code(stmtCall) 923 w.pos(stmt) 924 w.op(callOps[stmt.Tok]) 925 w.expr(stmt.Call) 926 927 case *syntax.DeclStmt: 928 for _, decl := range stmt.DeclList { 929 w.declStmt(decl) 930 } 931 932 case *syntax.ExprStmt: 933 w.code(stmtExpr) 934 w.expr(stmt.X) 935 936 case *syntax.ForStmt: 937 w.code(stmtFor) 938 w.forStmt(stmt) 939 940 case *syntax.IfStmt: 941 w.code(stmtIf) 942 w.ifStmt(stmt) 943 944 case *syntax.LabeledStmt: 945 w.code(stmtLabel) 946 w.pos(stmt) 947 w.label(stmt.Label) 948 w.stmt1(stmt.Stmt) 949 950 case *syntax.ReturnStmt: 951 w.code(stmtReturn) 952 w.pos(stmt) 953 w.exprList(stmt.Results) 954 955 case *syntax.SelectStmt: 956 w.code(stmtSelect) 957 w.selectStmt(stmt) 958 959 case *syntax.SendStmt: 960 w.code(stmtSend) 961 w.pos(stmt) 962 w.expr(stmt.Chan) 963 w.expr(stmt.Value) 964 965 case *syntax.SwitchStmt: 966 w.code(stmtSwitch) 967 w.switchStmt(stmt) 968 } 969} 970 971func (w *writer) assignList(expr syntax.Expr) { 972 exprs := unpackListExpr(expr) 973 w.len(len(exprs)) 974 975 for _, expr := range exprs { 976 if name, ok := expr.(*syntax.Name); ok && name.Value != "_" { 977 if obj, ok := w.p.info.Defs[name]; ok { 978 obj := obj.(*types2.Var) 979 980 w.bool(true) 981 w.pos(obj) 982 w.localIdent(obj) 983 w.typ(obj.Type()) 984 985 // TODO(mdempsky): Minimize locals index size by deferring 986 // this until the variables actually come into scope. 987 w.addLocal(obj) 988 continue 989 } 990 } 991 992 w.bool(false) 993 w.expr(expr) 994 } 995} 996 997func (w *writer) declStmt(decl syntax.Decl) { 998 switch decl := decl.(type) { 999 default: 1000 w.p.unexpected("declaration", decl) 1001 1002 case *syntax.ConstDecl: 1003 1004 case *syntax.TypeDecl: 1005 // Quirk: The legacy inliner doesn't support inlining functions 1006 // with type declarations. Unified IR doesn't have any need to 1007 // write out type declarations explicitly (they're always looked 1008 // up via global index tables instead), so we just write out a 1009 // marker so the reader knows to synthesize a fake declaration to 1010 // prevent inlining. 1011 if quirksMode() { 1012 w.code(stmtTypeDeclHack) 1013 } 1014 1015 case *syntax.VarDecl: 1016 values := unpackListExpr(decl.Values) 1017 1018 // Quirk: When N variables are declared with N initialization 1019 // values, we need to decompose that into N interleaved 1020 // declarations+initializations, because it leads to different 1021 // (albeit semantically equivalent) code generation. 1022 if quirksMode() && len(decl.NameList) == len(values) { 1023 for i, name := range decl.NameList { 1024 w.code(stmtAssign) 1025 w.pos(decl) 1026 w.exprList(values[i]) 1027 w.assignList(name) 1028 } 1029 break 1030 } 1031 1032 w.code(stmtAssign) 1033 w.pos(decl) 1034 w.exprList(decl.Values) 1035 w.assignList(namesAsExpr(decl.NameList)) 1036 } 1037} 1038 1039func (w *writer) blockStmt(stmt *syntax.BlockStmt) { 1040 w.sync(syncBlockStmt) 1041 w.openScope(stmt.Pos()) 1042 w.stmts(stmt.List) 1043 w.closeScope(stmt.Rbrace) 1044} 1045 1046func (w *writer) forStmt(stmt *syntax.ForStmt) { 1047 w.sync(syncForStmt) 1048 w.openScope(stmt.Pos()) 1049 1050 if rang, ok := stmt.Init.(*syntax.RangeClause); w.bool(ok) { 1051 w.pos(rang) 1052 w.expr(rang.X) 1053 w.assignList(rang.Lhs) 1054 } else { 1055 w.pos(stmt) 1056 w.stmt(stmt.Init) 1057 w.expr(stmt.Cond) 1058 w.stmt(stmt.Post) 1059 } 1060 1061 w.blockStmt(stmt.Body) 1062 w.closeAnotherScope() 1063} 1064 1065func (w *writer) ifStmt(stmt *syntax.IfStmt) { 1066 w.sync(syncIfStmt) 1067 w.openScope(stmt.Pos()) 1068 w.pos(stmt) 1069 w.stmt(stmt.Init) 1070 w.expr(stmt.Cond) 1071 w.blockStmt(stmt.Then) 1072 w.stmt(stmt.Else) 1073 w.closeAnotherScope() 1074} 1075 1076func (w *writer) selectStmt(stmt *syntax.SelectStmt) { 1077 w.sync(syncSelectStmt) 1078 1079 w.pos(stmt) 1080 w.len(len(stmt.Body)) 1081 for i, clause := range stmt.Body { 1082 if i > 0 { 1083 w.closeScope(clause.Pos()) 1084 } 1085 w.openScope(clause.Pos()) 1086 1087 w.pos(clause) 1088 w.stmt(clause.Comm) 1089 w.stmts(clause.Body) 1090 } 1091 if len(stmt.Body) > 0 { 1092 w.closeScope(stmt.Rbrace) 1093 } 1094} 1095 1096func (w *writer) switchStmt(stmt *syntax.SwitchStmt) { 1097 w.sync(syncSwitchStmt) 1098 1099 w.openScope(stmt.Pos()) 1100 w.pos(stmt) 1101 w.stmt(stmt.Init) 1102 1103 if guard, ok := stmt.Tag.(*syntax.TypeSwitchGuard); w.bool(ok) { 1104 w.pos(guard) 1105 if tag := guard.Lhs; w.bool(tag != nil) { 1106 w.pos(tag) 1107 w.string(tag.Value) 1108 } 1109 w.expr(guard.X) 1110 } else { 1111 w.expr(stmt.Tag) 1112 } 1113 1114 w.len(len(stmt.Body)) 1115 for i, clause := range stmt.Body { 1116 if i > 0 { 1117 w.closeScope(clause.Pos()) 1118 } 1119 w.openScope(clause.Pos()) 1120 1121 w.pos(clause) 1122 w.exprList(clause.Cases) 1123 1124 if obj, ok := w.p.info.Implicits[clause]; ok { 1125 // TODO(mdempsky): These pos details are quirkish, but also 1126 // necessary so the variable's position is correct for DWARF 1127 // scope assignment later. It would probably be better for us to 1128 // instead just set the variable's DWARF scoping info earlier so 1129 // we can give it the correct position information. 1130 pos := clause.Pos() 1131 if typs := unpackListExpr(clause.Cases); len(typs) != 0 { 1132 pos = typeExprEndPos(typs[len(typs)-1]) 1133 } 1134 w.pos(pos) 1135 1136 obj := obj.(*types2.Var) 1137 w.typ(obj.Type()) 1138 w.addLocal(obj) 1139 } 1140 1141 w.stmts(clause.Body) 1142 } 1143 if len(stmt.Body) > 0 { 1144 w.closeScope(stmt.Rbrace) 1145 } 1146 1147 w.closeScope(stmt.Rbrace) 1148} 1149 1150func (w *writer) label(label *syntax.Name) { 1151 w.sync(syncLabel) 1152 1153 // TODO(mdempsky): Replace label strings with dense indices. 1154 w.string(label.Value) 1155} 1156 1157func (w *writer) optLabel(label *syntax.Name) { 1158 w.sync(syncOptLabel) 1159 if w.bool(label != nil) { 1160 w.label(label) 1161 } 1162} 1163 1164// @@@ Expressions 1165 1166func (w *writer) expr(expr syntax.Expr) { 1167 expr = unparen(expr) // skip parens; unneeded after typecheck 1168 1169 obj, inst := lookupObj(w.p.info, expr) 1170 targs := inst.TypeArgs 1171 1172 if tv, ok := w.p.info.Types[expr]; ok { 1173 // TODO(mdempsky): Be more judicious about which types are marked as "needed". 1174 if inst.Type != nil { 1175 w.needType(inst.Type) 1176 } else { 1177 w.needType(tv.Type) 1178 } 1179 1180 if tv.IsType() { 1181 w.code(exprType) 1182 w.typ(tv.Type) 1183 return 1184 } 1185 1186 if tv.Value != nil { 1187 pos := expr.Pos() 1188 if quirksMode() { 1189 if obj != nil { 1190 // Quirk: IR (and thus iexport) doesn't track position 1191 // information for uses of declared objects. 1192 pos = syntax.Pos{} 1193 } else if tv.Value.Kind() == constant.String { 1194 // Quirk: noder.sum picks a particular position for certain 1195 // string concatenations. 1196 pos = sumPos(expr) 1197 } 1198 } 1199 1200 w.code(exprConst) 1201 w.pos(pos) 1202 w.typ(tv.Type) 1203 w.value(tv.Value) 1204 1205 // TODO(mdempsky): These details are only important for backend 1206 // diagnostics. Explore writing them out separately. 1207 w.op(constExprOp(expr)) 1208 w.string(syntax.String(expr)) 1209 return 1210 } 1211 } 1212 1213 if obj != nil { 1214 if isGlobal(obj) { 1215 w.code(exprName) 1216 w.obj(obj, targs) 1217 return 1218 } 1219 1220 obj := obj.(*types2.Var) 1221 assert(targs.Len() == 0) 1222 1223 w.code(exprLocal) 1224 w.useLocal(expr.Pos(), obj) 1225 return 1226 } 1227 1228 switch expr := expr.(type) { 1229 default: 1230 w.p.unexpected("expression", expr) 1231 1232 case nil: // absent slice index, for condition, or switch tag 1233 w.code(exprNone) 1234 1235 case *syntax.Name: 1236 assert(expr.Value == "_") 1237 w.code(exprBlank) 1238 1239 case *syntax.CompositeLit: 1240 w.code(exprCompLit) 1241 w.compLit(expr) 1242 1243 case *syntax.FuncLit: 1244 w.code(exprFuncLit) 1245 w.funcLit(expr) 1246 1247 case *syntax.SelectorExpr: 1248 sel, ok := w.p.info.Selections[expr] 1249 assert(ok) 1250 1251 w.code(exprSelector) 1252 w.expr(expr.X) 1253 w.pos(expr) 1254 w.selector(sel.Obj()) 1255 1256 case *syntax.IndexExpr: 1257 tv, ok := w.p.info.Types[expr.Index] 1258 assert(ok && tv.IsValue()) 1259 1260 w.code(exprIndex) 1261 w.expr(expr.X) 1262 w.pos(expr) 1263 w.expr(expr.Index) 1264 1265 case *syntax.SliceExpr: 1266 w.code(exprSlice) 1267 w.expr(expr.X) 1268 w.pos(expr) 1269 for _, n := range &expr.Index { 1270 w.expr(n) 1271 } 1272 1273 case *syntax.AssertExpr: 1274 w.code(exprAssert) 1275 w.expr(expr.X) 1276 w.pos(expr) 1277 w.expr(expr.Type) 1278 1279 case *syntax.Operation: 1280 if expr.Y == nil { 1281 w.code(exprUnaryOp) 1282 w.op(unOps[expr.Op]) 1283 w.pos(expr) 1284 w.expr(expr.X) 1285 break 1286 } 1287 1288 w.code(exprBinaryOp) 1289 w.op(binOps[expr.Op]) 1290 w.expr(expr.X) 1291 w.pos(expr) 1292 w.expr(expr.Y) 1293 1294 case *syntax.CallExpr: 1295 tv, ok := w.p.info.Types[expr.Fun] 1296 assert(ok) 1297 if tv.IsType() { 1298 assert(len(expr.ArgList) == 1) 1299 assert(!expr.HasDots) 1300 1301 w.code(exprConvert) 1302 w.typ(tv.Type) 1303 w.pos(expr) 1304 w.expr(expr.ArgList[0]) 1305 break 1306 } 1307 1308 writeFunExpr := func() { 1309 if selector, ok := unparen(expr.Fun).(*syntax.SelectorExpr); ok { 1310 if sel, ok := w.p.info.Selections[selector]; ok && sel.Kind() == types2.MethodVal { 1311 w.expr(selector.X) 1312 w.bool(true) // method call 1313 w.pos(selector) 1314 w.selector(sel.Obj()) 1315 return 1316 } 1317 } 1318 1319 w.expr(expr.Fun) 1320 w.bool(false) // not a method call (i.e., normal function call) 1321 } 1322 1323 w.code(exprCall) 1324 writeFunExpr() 1325 w.pos(expr) 1326 w.exprs(expr.ArgList) 1327 w.bool(expr.HasDots) 1328 } 1329} 1330 1331func (w *writer) compLit(lit *syntax.CompositeLit) { 1332 tv, ok := w.p.info.Types[lit] 1333 assert(ok) 1334 1335 w.sync(syncCompLit) 1336 w.pos(lit) 1337 w.typ(tv.Type) 1338 1339 typ := tv.Type 1340 if ptr, ok := typ.Underlying().(*types2.Pointer); ok { 1341 typ = ptr.Elem() 1342 } 1343 str, isStruct := typ.Underlying().(*types2.Struct) 1344 1345 w.len(len(lit.ElemList)) 1346 for i, elem := range lit.ElemList { 1347 if isStruct { 1348 if kv, ok := elem.(*syntax.KeyValueExpr); ok { 1349 // use position of expr.Key rather than of elem (which has position of ':') 1350 w.pos(kv.Key) 1351 w.len(fieldIndex(w.p.info, str, kv.Key.(*syntax.Name))) 1352 elem = kv.Value 1353 } else { 1354 w.pos(elem) 1355 w.len(i) 1356 } 1357 } else { 1358 if kv, ok := elem.(*syntax.KeyValueExpr); w.bool(ok) { 1359 // use position of expr.Key rather than of elem (which has position of ':') 1360 w.pos(kv.Key) 1361 w.expr(kv.Key) 1362 elem = kv.Value 1363 } 1364 } 1365 w.pos(elem) 1366 w.expr(elem) 1367 } 1368} 1369 1370func (w *writer) funcLit(expr *syntax.FuncLit) { 1371 tv, ok := w.p.info.Types[expr] 1372 assert(ok) 1373 sig := tv.Type.(*types2.Signature) 1374 1375 body, closureVars := w.p.bodyIdx(w.p.curpkg, sig, expr.Body, w.dict) 1376 1377 w.sync(syncFuncLit) 1378 w.pos(expr) 1379 w.pos(expr.Type) // for QuirksMode 1380 w.signature(sig) 1381 1382 w.len(len(closureVars)) 1383 for _, cv := range closureVars { 1384 w.pos(cv.pos) 1385 if quirksMode() { 1386 cv.pos = expr.Body.Rbrace 1387 } 1388 w.useLocal(cv.pos, cv.obj) 1389 } 1390 1391 w.reloc(relocBody, body) 1392} 1393 1394type posObj struct { 1395 pos syntax.Pos 1396 obj *types2.Var 1397} 1398 1399func (w *writer) exprList(expr syntax.Expr) { 1400 w.sync(syncExprList) 1401 w.exprs(unpackListExpr(expr)) 1402} 1403 1404func (w *writer) exprs(exprs []syntax.Expr) { 1405 if len(exprs) == 0 { 1406 assert(exprs == nil) 1407 } 1408 1409 w.sync(syncExprs) 1410 w.len(len(exprs)) 1411 for _, expr := range exprs { 1412 w.expr(expr) 1413 } 1414} 1415 1416func (w *writer) op(op ir.Op) { 1417 // TODO(mdempsky): Remove in favor of explicit codes? Would make 1418 // export data more stable against internal refactorings, but low 1419 // priority at the moment. 1420 assert(op != 0) 1421 w.sync(syncOp) 1422 w.len(int(op)) 1423} 1424 1425func (w *writer) needType(typ types2.Type) { 1426 // Decompose tuple into component element types. 1427 if typ, ok := typ.(*types2.Tuple); ok { 1428 for i := 0; i < typ.Len(); i++ { 1429 w.needType(typ.At(i).Type()) 1430 } 1431 return 1432 } 1433 1434 if info := w.p.typIdx(typ, w.dict); info.derived { 1435 w.dict.derived[info.idx].needed = true 1436 } 1437} 1438 1439// @@@ Package initialization 1440 1441// Caution: This code is still clumsy, because toolstash -cmp is 1442// particularly sensitive to it. 1443 1444type typeDeclGen struct { 1445 *syntax.TypeDecl 1446 gen int 1447 1448 // Implicit type parameters in scope at this type declaration. 1449 implicits []*types2.TypeName 1450} 1451 1452type fileImports struct { 1453 importedEmbed, importedUnsafe bool 1454} 1455 1456type declCollector struct { 1457 pw *pkgWriter 1458 typegen *int 1459 file *fileImports 1460 withinFunc bool 1461 implicits []*types2.TypeName 1462} 1463 1464func (c *declCollector) withTParams(obj types2.Object) *declCollector { 1465 tparams := objTypeParams(obj) 1466 n := tparams.Len() 1467 if n == 0 { 1468 return c 1469 } 1470 1471 copy := *c 1472 copy.implicits = copy.implicits[:len(copy.implicits):len(copy.implicits)] 1473 for i := 0; i < n; i++ { 1474 copy.implicits = append(copy.implicits, tparams.At(i).Obj()) 1475 } 1476 return © 1477} 1478 1479func (c *declCollector) Visit(n syntax.Node) syntax.Visitor { 1480 pw := c.pw 1481 1482 switch n := n.(type) { 1483 case *syntax.File: 1484 pw.checkPragmas(n.Pragma, ir.GoBuildPragma, false) 1485 1486 case *syntax.ImportDecl: 1487 pw.checkPragmas(n.Pragma, 0, false) 1488 1489 switch pkgNameOf(pw.info, n).Imported().Path() { 1490 case "embed": 1491 c.file.importedEmbed = true 1492 case "unsafe": 1493 c.file.importedUnsafe = true 1494 } 1495 1496 case *syntax.ConstDecl: 1497 pw.checkPragmas(n.Pragma, 0, false) 1498 1499 case *syntax.FuncDecl: 1500 pw.checkPragmas(n.Pragma, funcPragmas, false) 1501 1502 obj := pw.info.Defs[n.Name].(*types2.Func) 1503 pw.funDecls[obj] = n 1504 1505 return c.withTParams(obj) 1506 1507 case *syntax.TypeDecl: 1508 obj := pw.info.Defs[n.Name].(*types2.TypeName) 1509 d := typeDeclGen{TypeDecl: n, implicits: c.implicits} 1510 1511 if n.Alias { 1512 pw.checkPragmas(n.Pragma, 0, false) 1513 } else { 1514 pw.checkPragmas(n.Pragma, typePragmas, false) 1515 1516 // Assign a unique ID to function-scoped defined types. 1517 if c.withinFunc { 1518 *c.typegen++ 1519 d.gen = *c.typegen 1520 } 1521 } 1522 1523 pw.typDecls[obj] = d 1524 1525 // TODO(mdempsky): Omit? Not strictly necessary; only matters for 1526 // type declarations within function literals within parameterized 1527 // type declarations, but types2 the function literals will be 1528 // constant folded away. 1529 return c.withTParams(obj) 1530 1531 case *syntax.VarDecl: 1532 pw.checkPragmas(n.Pragma, 0, true) 1533 1534 if p, ok := n.Pragma.(*pragmas); ok && len(p.Embeds) > 0 { 1535 if err := checkEmbed(n, c.file.importedEmbed, c.withinFunc); err != nil { 1536 pw.errorf(p.Embeds[0].Pos, "%s", err) 1537 } 1538 } 1539 1540 // Workaround for #46208. For variable declarations that 1541 // declare multiple variables and have an explicit type 1542 // expression, the type expression is evaluated multiple 1543 // times. This affects toolstash -cmp, because iexport is 1544 // sensitive to *types.Type pointer identity. 1545 if quirksMode() && n.Type != nil { 1546 tv, ok := pw.info.Types[n.Type] 1547 assert(ok) 1548 assert(tv.IsType()) 1549 for _, name := range n.NameList { 1550 obj := pw.info.Defs[name].(*types2.Var) 1551 pw.dups.add(obj.Type(), tv.Type) 1552 } 1553 } 1554 1555 case *syntax.BlockStmt: 1556 if !c.withinFunc { 1557 copy := *c 1558 copy.withinFunc = true 1559 return © 1560 } 1561 } 1562 1563 return c 1564} 1565 1566func (pw *pkgWriter) collectDecls(noders []*noder) { 1567 var typegen int 1568 for _, p := range noders { 1569 var file fileImports 1570 1571 syntax.Walk(p.file, &declCollector{ 1572 pw: pw, 1573 typegen: &typegen, 1574 file: &file, 1575 }) 1576 1577 pw.cgoPragmas = append(pw.cgoPragmas, p.pragcgobuf...) 1578 1579 for _, l := range p.linknames { 1580 if !file.importedUnsafe { 1581 pw.errorf(l.pos, "//go:linkname only allowed in Go files that import \"unsafe\"") 1582 continue 1583 } 1584 1585 switch obj := pw.curpkg.Scope().Lookup(l.local).(type) { 1586 case *types2.Func, *types2.Var: 1587 if _, ok := pw.linknames[obj]; !ok { 1588 pw.linknames[obj] = l.remote 1589 } else { 1590 pw.errorf(l.pos, "duplicate //go:linkname for %s", l.local) 1591 } 1592 1593 default: 1594 // TODO(mdempsky): Enable after #42938 is fixed. 1595 if false { 1596 pw.errorf(l.pos, "//go:linkname must refer to declared function or variable") 1597 } 1598 } 1599 } 1600 } 1601} 1602 1603func (pw *pkgWriter) checkPragmas(p syntax.Pragma, allowed ir.PragmaFlag, embedOK bool) { 1604 if p == nil { 1605 return 1606 } 1607 pragma := p.(*pragmas) 1608 1609 for _, pos := range pragma.Pos { 1610 if pos.Flag&^allowed != 0 { 1611 pw.errorf(pos.Pos, "misplaced compiler directive") 1612 } 1613 } 1614 1615 if !embedOK { 1616 for _, e := range pragma.Embeds { 1617 pw.errorf(e.Pos, "misplaced go:embed directive") 1618 } 1619 } 1620} 1621 1622func (w *writer) pkgInit(noders []*noder) { 1623 if quirksMode() { 1624 posBases := posBasesOf(noders) 1625 w.len(len(posBases)) 1626 for _, posBase := range posBases { 1627 w.posBase(posBase) 1628 } 1629 1630 objs := importedObjsOf(w.p.curpkg, w.p.info, noders) 1631 w.len(len(objs)) 1632 for _, obj := range objs { 1633 w.qualifiedIdent(obj) 1634 } 1635 } 1636 1637 w.len(len(w.p.cgoPragmas)) 1638 for _, cgoPragma := range w.p.cgoPragmas { 1639 w.strings(cgoPragma) 1640 } 1641 1642 w.sync(syncDecls) 1643 for _, p := range noders { 1644 for _, decl := range p.file.DeclList { 1645 w.pkgDecl(decl) 1646 } 1647 } 1648 w.code(declEnd) 1649 1650 w.sync(syncEOF) 1651} 1652 1653func (w *writer) pkgDecl(decl syntax.Decl) { 1654 switch decl := decl.(type) { 1655 default: 1656 w.p.unexpected("declaration", decl) 1657 1658 case *syntax.ImportDecl: 1659 1660 case *syntax.ConstDecl: 1661 w.code(declOther) 1662 w.pkgObjs(decl.NameList...) 1663 1664 case *syntax.FuncDecl: 1665 if decl.Name.Value == "_" { 1666 break // skip blank functions 1667 } 1668 1669 obj := w.p.info.Defs[decl.Name].(*types2.Func) 1670 sig := obj.Type().(*types2.Signature) 1671 1672 if sig.RecvTypeParams() != nil || sig.TypeParams() != nil { 1673 break // skip generic functions 1674 } 1675 1676 if recv := sig.Recv(); recv != nil { 1677 w.code(declMethod) 1678 w.typ(recvBase(recv)) 1679 w.selector(obj) 1680 break 1681 } 1682 1683 w.code(declFunc) 1684 w.pkgObjs(decl.Name) 1685 1686 case *syntax.TypeDecl: 1687 if len(decl.TParamList) != 0 { 1688 break // skip generic type decls 1689 } 1690 1691 if decl.Name.Value == "_" { 1692 break // skip blank type decls 1693 } 1694 1695 name := w.p.info.Defs[decl.Name].(*types2.TypeName) 1696 // Skip type declarations for interfaces that are only usable as 1697 // type parameter bounds. 1698 if iface, ok := name.Type().Underlying().(*types2.Interface); ok && !iface.IsMethodSet() { 1699 break 1700 } 1701 1702 // Skip aliases to uninstantiated generic types. 1703 // TODO(mdempsky): Revisit after #46477 is resolved. 1704 if name.IsAlias() { 1705 named, ok := name.Type().(*types2.Named) 1706 if ok && named.TypeParams().Len() != 0 && named.TypeArgs().Len() == 0 { 1707 break 1708 } 1709 } 1710 1711 w.code(declOther) 1712 w.pkgObjs(decl.Name) 1713 1714 case *syntax.VarDecl: 1715 w.code(declVar) 1716 w.pos(decl) 1717 w.pkgObjs(decl.NameList...) 1718 w.exprList(decl.Values) 1719 1720 var embeds []pragmaEmbed 1721 if p, ok := decl.Pragma.(*pragmas); ok { 1722 embeds = p.Embeds 1723 } 1724 w.len(len(embeds)) 1725 for _, embed := range embeds { 1726 w.pos(embed.Pos) 1727 w.strings(embed.Patterns) 1728 } 1729 } 1730} 1731 1732func (w *writer) pkgObjs(names ...*syntax.Name) { 1733 w.sync(syncDeclNames) 1734 w.len(len(names)) 1735 1736 for _, name := range names { 1737 obj, ok := w.p.info.Defs[name] 1738 assert(ok) 1739 1740 w.sync(syncDeclName) 1741 w.obj(obj, nil) 1742 } 1743} 1744 1745// @@@ Helpers 1746 1747// isDefinedType reports whether obj is a defined type. 1748func isDefinedType(obj types2.Object) bool { 1749 if obj, ok := obj.(*types2.TypeName); ok { 1750 return !obj.IsAlias() 1751 } 1752 return false 1753} 1754 1755// isGlobal reports whether obj was declared at package scope. 1756// 1757// Caveat: blank objects are not declared. 1758func isGlobal(obj types2.Object) bool { 1759 return obj.Parent() == obj.Pkg().Scope() 1760} 1761 1762// lookupObj returns the object that expr refers to, if any. If expr 1763// is an explicit instantiation of a generic object, then the instance 1764// object is returned as well. 1765func lookupObj(info *types2.Info, expr syntax.Expr) (obj types2.Object, inst types2.Instance) { 1766 if index, ok := expr.(*syntax.IndexExpr); ok { 1767 args := unpackListExpr(index.Index) 1768 if len(args) == 1 { 1769 tv, ok := info.Types[args[0]] 1770 assert(ok) 1771 if tv.IsValue() { 1772 return // normal index expression 1773 } 1774 } 1775 1776 expr = index.X 1777 } 1778 1779 // Strip package qualifier, if present. 1780 if sel, ok := expr.(*syntax.SelectorExpr); ok { 1781 if !isPkgQual(info, sel) { 1782 return // normal selector expression 1783 } 1784 expr = sel.Sel 1785 } 1786 1787 if name, ok := expr.(*syntax.Name); ok { 1788 obj = info.Uses[name] 1789 inst = info.Instances[name] 1790 } 1791 return 1792} 1793 1794// isPkgQual reports whether the given selector expression is a 1795// package-qualified identifier. 1796func isPkgQual(info *types2.Info, sel *syntax.SelectorExpr) bool { 1797 if name, ok := sel.X.(*syntax.Name); ok { 1798 _, isPkgName := info.Uses[name].(*types2.PkgName) 1799 return isPkgName 1800 } 1801 return false 1802} 1803 1804// recvBase returns the base type for the given receiver parameter. 1805func recvBase(recv *types2.Var) *types2.Named { 1806 typ := recv.Type() 1807 if ptr, ok := typ.(*types2.Pointer); ok { 1808 typ = ptr.Elem() 1809 } 1810 return typ.(*types2.Named) 1811} 1812 1813// namesAsExpr returns a list of names as a syntax.Expr. 1814func namesAsExpr(names []*syntax.Name) syntax.Expr { 1815 if len(names) == 1 { 1816 return names[0] 1817 } 1818 1819 exprs := make([]syntax.Expr, len(names)) 1820 for i, name := range names { 1821 exprs[i] = name 1822 } 1823 return &syntax.ListExpr{ElemList: exprs} 1824} 1825 1826// fieldIndex returns the index of the struct field named by key. 1827func fieldIndex(info *types2.Info, str *types2.Struct, key *syntax.Name) int { 1828 field := info.Uses[key].(*types2.Var) 1829 1830 for i := 0; i < str.NumFields(); i++ { 1831 if str.Field(i) == field { 1832 return i 1833 } 1834 } 1835 1836 panic(fmt.Sprintf("%s: %v is not a field of %v", key.Pos(), field, str)) 1837} 1838 1839// objTypeParams returns the type parameters on the given object. 1840func objTypeParams(obj types2.Object) *types2.TypeParamList { 1841 switch obj := obj.(type) { 1842 case *types2.Func: 1843 sig := obj.Type().(*types2.Signature) 1844 if sig.Recv() != nil { 1845 return sig.RecvTypeParams() 1846 } 1847 return sig.TypeParams() 1848 case *types2.TypeName: 1849 if !obj.IsAlias() { 1850 return obj.Type().(*types2.Named).TypeParams() 1851 } 1852 } 1853 return nil 1854} 1855 1856func asPragmaFlag(p syntax.Pragma) ir.PragmaFlag { 1857 if p == nil { 1858 return 0 1859 } 1860 return p.(*pragmas).Flag 1861} 1862