1
2
3
4
5
6
7 package noder
8
9 import (
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
19 type 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
40 func 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
61 func (pw *pkgWriter) errorf(p poser, msg string, args ...interface{}) {
62 base.ErrorfAt(pw.m.pos(p), msg, args...)
63 }
64
65 func (pw *pkgWriter) fatalf(p poser, msg string, args ...interface{}) {
66 base.FatalfAt(pw.m.pos(p), msg, args...)
67 }
68
69 func (pw *pkgWriter) unexpected(what string, p poser) {
70 pw.fatalf(p, "unexpected %s: %v (%T)", what, p, p)
71 }
72
73 type writer struct {
74 p *pkgWriter
75
76 encoder
77
78
79
80
81
82
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
93 type writerDict struct {
94 implicits []*types2.TypeName
95
96
97
98 derived []derivedInfo
99
100
101
102 derivedIdx map[types2.Type]int
103
104
105
106
107 funcs []objInfo
108 }
109
110 type derivedInfo struct {
111 idx int
112 needed bool
113 }
114
115 type typeInfo struct {
116 idx int
117 derived bool
118 }
119
120 type objInfo struct {
121 idx int
122 explicits []typeInfo
123 }
124
125 func (info objInfo) anyDerived() bool {
126 for _, explicit := range info.explicits {
127 if explicit.derived {
128 return true
129 }
130 }
131 return false
132 }
133
134 func (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
147 func (pw *pkgWriter) newWriter(k reloc, marker syncMarker) *writer {
148 return &writer{
149 encoder: pw.newEncoder(k, marker),
150 p: pw,
151 }
152 }
153
154
155
156 func (w *writer) pos(p poser) {
157 w.sync(syncPos)
158 pos := p.Pos()
159
160
161 if !w.bool(pos.IsKnown()) {
162 return
163 }
164
165
166
167 w.posBase(pos.Base())
168 w.uint(pos.Line())
169 w.uint(pos.Col())
170 }
171
172 func (w *writer) posBase(b *syntax.PosBase) {
173 w.reloc(relocPosBase, w.p.posBaseIdx(b))
174 }
175
176 func (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
196
197 func (w *writer) pkg(pkg *types2.Package) {
198 w.sync(syncPkg)
199 w.reloc(relocPkg, w.p.pkgIdx(pkg))
200 }
201
202 func (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
231
232 var anyTypeName = types2.Universe.Lookup("any").(*types2.TypeName)
233
234 func (w *writer) typ(typ types2.Type) {
235 w.typInfo(w.p.typIdx(typ, w.dict))
236 }
237
238 func (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
249
250
251
252
253 func (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
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
294
295
296 assert(typ.TypeParams().Len() == typ.TypeArgs().Len() || typ.TypeArgs().Len() == 0)
297
298
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
380 func (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
392 func (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
401 func (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
420 func (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
427 func (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
435 func (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
443
444 func (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
464
465 w.sync(syncObject)
466 w.bool(true)
467 w.len(idx)
468 return
469 }
470
471
472
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
491 func (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
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
533 func (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
595 func (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
603 func (w *writer) objDict(obj types2.Object, dict *writerDict) {
604
605
606
607
608 w.dict = dict
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
640 func (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
651 func (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)
664 wext.funcExt(meth)
665 }
666
667
668
669 func (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
678
679 name = fmt.Sprintf("%s·%v", name, decl.gen)
680 }
681 }
682
683 w.pkg(obj.Pkg())
684 w.string(name)
685 }
686
687
688
689
690
691
692
693
694
695 func (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
703
704 func (w *writer) selector(obj types2.Object) {
705 w.sync(syncSelector)
706 w.pkg(obj.Pkg())
707 w.string(obj.Name())
708 }
709
710
711
712 func (w *writer) funcExt(obj *types2.Func) {
713 decl, ok := w.p.funDecls[obj]
714 assert(ok)
715
716
717
718
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
732
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)
747 w.reloc(relocBody, body)
748 w.sync(syncEOF)
749 }
750
751 func (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
760 w.int64(-1)
761 w.int64(-1)
762 }
763
764 func (w *writer) varExt(obj *types2.Var) {
765 w.sync(syncVarExt)
766 w.linkname(obj)
767 }
768
769 func (w *writer) linkname(obj types2.Object) {
770 w.sync(syncLinkname)
771 w.int64(-1)
772 w.string(w.p.linknames[obj])
773 }
774
775 func (w *writer) pragmaFlag(p ir.PragmaFlag) {
776 w.sync(syncPragma)
777 w.int(int(p))
778 }
779
780
781
782 func (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
795 func (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
809 func (w *writer) funcarg(param *types2.Var, result bool) {
810 if param.Name() != "" || result {
811 w.addLocal(param)
812 }
813 }
814
815 func (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
827 func (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
847 func (w *writer) openScope(pos syntax.Pos) {
848 w.sync(syncOpenScope)
849 w.pos(pos)
850 }
851
852 func (w *writer) closeScope(pos syntax.Pos) {
853 w.sync(syncCloseScope)
854 w.pos(pos)
855 w.closeAnotherScope()
856 }
857
858 func (w *writer) closeAnotherScope() {
859 w.sync(syncCloseAnotherScope)
860 }
861
862
863
864 func (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
872 func (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
881 func (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
971 func (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
986
987 w.addLocal(obj)
988 continue
989 }
990 }
991
992 w.bool(false)
993 w.expr(expr)
994 }
995 }
996
997 func (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
1006
1007
1008
1009
1010
1011 if quirksMode() {
1012 w.code(stmtTypeDeclHack)
1013 }
1014
1015 case *syntax.VarDecl:
1016 values := unpackListExpr(decl.Values)
1017
1018
1019
1020
1021
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
1039 func (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
1046 func (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
1065 func (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
1076 func (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
1096 func (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
1126
1127
1128
1129
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
1150 func (w *writer) label(label *syntax.Name) {
1151 w.sync(syncLabel)
1152
1153
1154 w.string(label.Value)
1155 }
1156
1157 func (w *writer) optLabel(label *syntax.Name) {
1158 w.sync(syncOptLabel)
1159 if w.bool(label != nil) {
1160 w.label(label)
1161 }
1162 }
1163
1164
1165
1166 func (w *writer) expr(expr syntax.Expr) {
1167 expr = unparen(expr)
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
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
1191
1192 pos = syntax.Pos{}
1193 } else if tv.Value.Kind() == constant.String {
1194
1195
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
1206
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(!obj.IsField())
1222 assert(targs.Len() == 0)
1223
1224 w.code(exprLocal)
1225 w.useLocal(expr.Pos(), obj)
1226 return
1227 }
1228
1229 switch expr := expr.(type) {
1230 default:
1231 w.p.unexpected("expression", expr)
1232
1233 case nil:
1234 w.code(exprNone)
1235
1236 case *syntax.Name:
1237 assert(expr.Value == "_")
1238 w.code(exprBlank)
1239
1240 case *syntax.CompositeLit:
1241 w.code(exprCompLit)
1242 w.compLit(expr)
1243
1244 case *syntax.FuncLit:
1245 w.code(exprFuncLit)
1246 w.funcLit(expr)
1247
1248 case *syntax.SelectorExpr:
1249 sel, ok := w.p.info.Selections[expr]
1250 assert(ok)
1251
1252 w.code(exprSelector)
1253 w.expr(expr.X)
1254 w.pos(expr)
1255 w.selector(sel.Obj())
1256
1257 case *syntax.IndexExpr:
1258 tv, ok := w.p.info.Types[expr.Index]
1259 assert(ok && tv.IsValue())
1260
1261 w.code(exprIndex)
1262 w.expr(expr.X)
1263 w.pos(expr)
1264 w.expr(expr.Index)
1265
1266 case *syntax.SliceExpr:
1267 w.code(exprSlice)
1268 w.expr(expr.X)
1269 w.pos(expr)
1270 for _, n := range &expr.Index {
1271 w.expr(n)
1272 }
1273
1274 case *syntax.AssertExpr:
1275 w.code(exprAssert)
1276 w.expr(expr.X)
1277 w.pos(expr)
1278 w.expr(expr.Type)
1279
1280 case *syntax.Operation:
1281 if expr.Y == nil {
1282 w.code(exprUnaryOp)
1283 w.op(unOps[expr.Op])
1284 w.pos(expr)
1285 w.expr(expr.X)
1286 break
1287 }
1288
1289 w.code(exprBinaryOp)
1290 w.op(binOps[expr.Op])
1291 w.expr(expr.X)
1292 w.pos(expr)
1293 w.expr(expr.Y)
1294
1295 case *syntax.CallExpr:
1296 tv, ok := w.p.info.Types[expr.Fun]
1297 assert(ok)
1298 if tv.IsType() {
1299 assert(len(expr.ArgList) == 1)
1300 assert(!expr.HasDots)
1301
1302 w.code(exprConvert)
1303 w.typ(tv.Type)
1304 w.pos(expr)
1305 w.expr(expr.ArgList[0])
1306 break
1307 }
1308
1309 writeFunExpr := func() {
1310 if selector, ok := unparen(expr.Fun).(*syntax.SelectorExpr); ok {
1311 if sel, ok := w.p.info.Selections[selector]; ok && sel.Kind() == types2.MethodVal {
1312 w.expr(selector.X)
1313 w.bool(true)
1314 w.pos(selector)
1315 w.selector(sel.Obj())
1316 return
1317 }
1318 }
1319
1320 w.expr(expr.Fun)
1321 w.bool(false)
1322 }
1323
1324 w.code(exprCall)
1325 writeFunExpr()
1326 w.pos(expr)
1327 w.exprs(expr.ArgList)
1328 w.bool(expr.HasDots)
1329 }
1330 }
1331
1332 func (w *writer) compLit(lit *syntax.CompositeLit) {
1333 tv, ok := w.p.info.Types[lit]
1334 assert(ok)
1335
1336 w.sync(syncCompLit)
1337 w.pos(lit)
1338 w.typ(tv.Type)
1339
1340 typ := tv.Type
1341 if ptr, ok := types2.CoreType(typ).(*types2.Pointer); ok {
1342 typ = ptr.Elem()
1343 }
1344 str, isStruct := types2.CoreType(typ).(*types2.Struct)
1345
1346 w.len(len(lit.ElemList))
1347 for i, elem := range lit.ElemList {
1348 if isStruct {
1349 if kv, ok := elem.(*syntax.KeyValueExpr); ok {
1350
1351 w.pos(kv.Key)
1352 w.len(fieldIndex(w.p.info, str, kv.Key.(*syntax.Name)))
1353 elem = kv.Value
1354 } else {
1355 w.pos(elem)
1356 w.len(i)
1357 }
1358 } else {
1359 if kv, ok := elem.(*syntax.KeyValueExpr); w.bool(ok) {
1360
1361 w.pos(kv.Key)
1362 w.expr(kv.Key)
1363 elem = kv.Value
1364 }
1365 }
1366 w.pos(elem)
1367 w.expr(elem)
1368 }
1369 }
1370
1371 func (w *writer) funcLit(expr *syntax.FuncLit) {
1372 tv, ok := w.p.info.Types[expr]
1373 assert(ok)
1374 sig := tv.Type.(*types2.Signature)
1375
1376 body, closureVars := w.p.bodyIdx(w.p.curpkg, sig, expr.Body, w.dict)
1377
1378 w.sync(syncFuncLit)
1379 w.pos(expr)
1380 w.pos(expr.Type)
1381 w.signature(sig)
1382
1383 w.len(len(closureVars))
1384 for _, cv := range closureVars {
1385 w.pos(cv.pos)
1386 if quirksMode() {
1387 cv.pos = expr.Body.Rbrace
1388 }
1389 w.useLocal(cv.pos, cv.obj)
1390 }
1391
1392 w.reloc(relocBody, body)
1393 }
1394
1395 type posObj struct {
1396 pos syntax.Pos
1397 obj *types2.Var
1398 }
1399
1400 func (w *writer) exprList(expr syntax.Expr) {
1401 w.sync(syncExprList)
1402 w.exprs(unpackListExpr(expr))
1403 }
1404
1405 func (w *writer) exprs(exprs []syntax.Expr) {
1406 if len(exprs) == 0 {
1407 assert(exprs == nil)
1408 }
1409
1410 w.sync(syncExprs)
1411 w.len(len(exprs))
1412 for _, expr := range exprs {
1413 w.expr(expr)
1414 }
1415 }
1416
1417 func (w *writer) op(op ir.Op) {
1418
1419
1420
1421 assert(op != 0)
1422 w.sync(syncOp)
1423 w.len(int(op))
1424 }
1425
1426 func (w *writer) needType(typ types2.Type) {
1427
1428 if typ, ok := typ.(*types2.Tuple); ok {
1429 for i := 0; i < typ.Len(); i++ {
1430 w.needType(typ.At(i).Type())
1431 }
1432 return
1433 }
1434
1435 if info := w.p.typIdx(typ, w.dict); info.derived {
1436 w.dict.derived[info.idx].needed = true
1437 }
1438 }
1439
1440
1441
1442
1443
1444
1445 type typeDeclGen struct {
1446 *syntax.TypeDecl
1447 gen int
1448
1449
1450 implicits []*types2.TypeName
1451 }
1452
1453 type fileImports struct {
1454 importedEmbed, importedUnsafe bool
1455 }
1456
1457 type declCollector struct {
1458 pw *pkgWriter
1459 typegen *int
1460 file *fileImports
1461 withinFunc bool
1462 implicits []*types2.TypeName
1463 }
1464
1465 func (c *declCollector) withTParams(obj types2.Object) *declCollector {
1466 tparams := objTypeParams(obj)
1467 n := tparams.Len()
1468 if n == 0 {
1469 return c
1470 }
1471
1472 copy := *c
1473 copy.implicits = copy.implicits[:len(copy.implicits):len(copy.implicits)]
1474 for i := 0; i < n; i++ {
1475 copy.implicits = append(copy.implicits, tparams.At(i).Obj())
1476 }
1477 return ©
1478 }
1479
1480 func (c *declCollector) Visit(n syntax.Node) syntax.Visitor {
1481 pw := c.pw
1482
1483 switch n := n.(type) {
1484 case *syntax.File:
1485 pw.checkPragmas(n.Pragma, ir.GoBuildPragma, false)
1486
1487 case *syntax.ImportDecl:
1488 pw.checkPragmas(n.Pragma, 0, false)
1489
1490 switch pkgNameOf(pw.info, n).Imported().Path() {
1491 case "embed":
1492 c.file.importedEmbed = true
1493 case "unsafe":
1494 c.file.importedUnsafe = true
1495 }
1496
1497 case *syntax.ConstDecl:
1498 pw.checkPragmas(n.Pragma, 0, false)
1499
1500 case *syntax.FuncDecl:
1501 pw.checkPragmas(n.Pragma, funcPragmas, false)
1502
1503 obj := pw.info.Defs[n.Name].(*types2.Func)
1504 pw.funDecls[obj] = n
1505
1506 return c.withTParams(obj)
1507
1508 case *syntax.TypeDecl:
1509 obj := pw.info.Defs[n.Name].(*types2.TypeName)
1510 d := typeDeclGen{TypeDecl: n, implicits: c.implicits}
1511
1512 if n.Alias {
1513 pw.checkPragmas(n.Pragma, 0, false)
1514 } else {
1515 pw.checkPragmas(n.Pragma, typePragmas, false)
1516
1517
1518 if c.withinFunc {
1519 *c.typegen++
1520 d.gen = *c.typegen
1521 }
1522 }
1523
1524 pw.typDecls[obj] = d
1525
1526
1527
1528
1529
1530 return c.withTParams(obj)
1531
1532 case *syntax.VarDecl:
1533 pw.checkPragmas(n.Pragma, 0, true)
1534
1535 if p, ok := n.Pragma.(*pragmas); ok && len(p.Embeds) > 0 {
1536 if err := checkEmbed(n, c.file.importedEmbed, c.withinFunc); err != nil {
1537 pw.errorf(p.Embeds[0].Pos, "%s", err)
1538 }
1539 }
1540
1541
1542
1543
1544
1545
1546 if quirksMode() && n.Type != nil {
1547 tv, ok := pw.info.Types[n.Type]
1548 assert(ok)
1549 assert(tv.IsType())
1550 for _, name := range n.NameList {
1551 obj := pw.info.Defs[name].(*types2.Var)
1552 pw.dups.add(obj.Type(), tv.Type)
1553 }
1554 }
1555
1556 case *syntax.BlockStmt:
1557 if !c.withinFunc {
1558 copy := *c
1559 copy.withinFunc = true
1560 return ©
1561 }
1562 }
1563
1564 return c
1565 }
1566
1567 func (pw *pkgWriter) collectDecls(noders []*noder) {
1568 var typegen int
1569 for _, p := range noders {
1570 var file fileImports
1571
1572 syntax.Walk(p.file, &declCollector{
1573 pw: pw,
1574 typegen: &typegen,
1575 file: &file,
1576 })
1577
1578 pw.cgoPragmas = append(pw.cgoPragmas, p.pragcgobuf...)
1579
1580 for _, l := range p.linknames {
1581 if !file.importedUnsafe {
1582 pw.errorf(l.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")
1583 continue
1584 }
1585
1586 switch obj := pw.curpkg.Scope().Lookup(l.local).(type) {
1587 case *types2.Func, *types2.Var:
1588 if _, ok := pw.linknames[obj]; !ok {
1589 pw.linknames[obj] = l.remote
1590 } else {
1591 pw.errorf(l.pos, "duplicate //go:linkname for %s", l.local)
1592 }
1593
1594 default:
1595
1596 if false {
1597 pw.errorf(l.pos, "//go:linkname must refer to declared function or variable")
1598 }
1599 }
1600 }
1601 }
1602 }
1603
1604 func (pw *pkgWriter) checkPragmas(p syntax.Pragma, allowed ir.PragmaFlag, embedOK bool) {
1605 if p == nil {
1606 return
1607 }
1608 pragma := p.(*pragmas)
1609
1610 for _, pos := range pragma.Pos {
1611 if pos.Flag&^allowed != 0 {
1612 pw.errorf(pos.Pos, "misplaced compiler directive")
1613 }
1614 }
1615
1616 if !embedOK {
1617 for _, e := range pragma.Embeds {
1618 pw.errorf(e.Pos, "misplaced go:embed directive")
1619 }
1620 }
1621 }
1622
1623 func (w *writer) pkgInit(noders []*noder) {
1624 if quirksMode() {
1625 posBases := posBasesOf(noders)
1626 w.len(len(posBases))
1627 for _, posBase := range posBases {
1628 w.posBase(posBase)
1629 }
1630
1631 objs := importedObjsOf(w.p.curpkg, w.p.info, noders)
1632 w.len(len(objs))
1633 for _, obj := range objs {
1634 w.qualifiedIdent(obj)
1635 }
1636 }
1637
1638 w.len(len(w.p.cgoPragmas))
1639 for _, cgoPragma := range w.p.cgoPragmas {
1640 w.strings(cgoPragma)
1641 }
1642
1643 w.sync(syncDecls)
1644 for _, p := range noders {
1645 for _, decl := range p.file.DeclList {
1646 w.pkgDecl(decl)
1647 }
1648 }
1649 w.code(declEnd)
1650
1651 w.sync(syncEOF)
1652 }
1653
1654 func (w *writer) pkgDecl(decl syntax.Decl) {
1655 switch decl := decl.(type) {
1656 default:
1657 w.p.unexpected("declaration", decl)
1658
1659 case *syntax.ImportDecl:
1660
1661 case *syntax.ConstDecl:
1662 w.code(declOther)
1663 w.pkgObjs(decl.NameList...)
1664
1665 case *syntax.FuncDecl:
1666 if decl.Name.Value == "_" {
1667 break
1668 }
1669
1670 obj := w.p.info.Defs[decl.Name].(*types2.Func)
1671 sig := obj.Type().(*types2.Signature)
1672
1673 if sig.RecvTypeParams() != nil || sig.TypeParams() != nil {
1674 break
1675 }
1676
1677 if recv := sig.Recv(); recv != nil {
1678 w.code(declMethod)
1679 w.typ(recvBase(recv))
1680 w.selector(obj)
1681 break
1682 }
1683
1684 w.code(declFunc)
1685 w.pkgObjs(decl.Name)
1686
1687 case *syntax.TypeDecl:
1688 if len(decl.TParamList) != 0 {
1689 break
1690 }
1691
1692 if decl.Name.Value == "_" {
1693 break
1694 }
1695
1696 name := w.p.info.Defs[decl.Name].(*types2.TypeName)
1697
1698
1699 if iface, ok := name.Type().Underlying().(*types2.Interface); ok && !iface.IsMethodSet() {
1700 break
1701 }
1702
1703
1704
1705 if name.IsAlias() {
1706 named, ok := name.Type().(*types2.Named)
1707 if ok && named.TypeParams().Len() != 0 && named.TypeArgs().Len() == 0 {
1708 break
1709 }
1710 }
1711
1712 w.code(declOther)
1713 w.pkgObjs(decl.Name)
1714
1715 case *syntax.VarDecl:
1716 w.code(declVar)
1717 w.pos(decl)
1718 w.pkgObjs(decl.NameList...)
1719 w.exprList(decl.Values)
1720
1721 var embeds []pragmaEmbed
1722 if p, ok := decl.Pragma.(*pragmas); ok {
1723 embeds = p.Embeds
1724 }
1725 w.len(len(embeds))
1726 for _, embed := range embeds {
1727 w.pos(embed.Pos)
1728 w.strings(embed.Patterns)
1729 }
1730 }
1731 }
1732
1733 func (w *writer) pkgObjs(names ...*syntax.Name) {
1734 w.sync(syncDeclNames)
1735 w.len(len(names))
1736
1737 for _, name := range names {
1738 obj, ok := w.p.info.Defs[name]
1739 assert(ok)
1740
1741 w.sync(syncDeclName)
1742 w.obj(obj, nil)
1743 }
1744 }
1745
1746
1747
1748
1749 func isDefinedType(obj types2.Object) bool {
1750 if obj, ok := obj.(*types2.TypeName); ok {
1751 return !obj.IsAlias()
1752 }
1753 return false
1754 }
1755
1756
1757
1758
1759 func isGlobal(obj types2.Object) bool {
1760 return obj.Parent() == obj.Pkg().Scope()
1761 }
1762
1763
1764
1765
1766 func lookupObj(info *types2.Info, expr syntax.Expr) (obj types2.Object, inst types2.Instance) {
1767 if index, ok := expr.(*syntax.IndexExpr); ok {
1768 args := unpackListExpr(index.Index)
1769 if len(args) == 1 {
1770 tv, ok := info.Types[args[0]]
1771 assert(ok)
1772 if tv.IsValue() {
1773 return
1774 }
1775 }
1776
1777 expr = index.X
1778 }
1779
1780
1781 if sel, ok := expr.(*syntax.SelectorExpr); ok {
1782 if !isPkgQual(info, sel) {
1783 return
1784 }
1785 expr = sel.Sel
1786 }
1787
1788 if name, ok := expr.(*syntax.Name); ok {
1789 obj = info.Uses[name]
1790 inst = info.Instances[name]
1791 }
1792 return
1793 }
1794
1795
1796
1797 func isPkgQual(info *types2.Info, sel *syntax.SelectorExpr) bool {
1798 if name, ok := sel.X.(*syntax.Name); ok {
1799 _, isPkgName := info.Uses[name].(*types2.PkgName)
1800 return isPkgName
1801 }
1802 return false
1803 }
1804
1805
1806 func recvBase(recv *types2.Var) *types2.Named {
1807 typ := recv.Type()
1808 if ptr, ok := typ.(*types2.Pointer); ok {
1809 typ = ptr.Elem()
1810 }
1811 return typ.(*types2.Named)
1812 }
1813
1814
1815 func namesAsExpr(names []*syntax.Name) syntax.Expr {
1816 if len(names) == 1 {
1817 return names[0]
1818 }
1819
1820 exprs := make([]syntax.Expr, len(names))
1821 for i, name := range names {
1822 exprs[i] = name
1823 }
1824 return &syntax.ListExpr{ElemList: exprs}
1825 }
1826
1827
1828 func fieldIndex(info *types2.Info, str *types2.Struct, key *syntax.Name) int {
1829 field := info.Uses[key].(*types2.Var)
1830
1831 for i := 0; i < str.NumFields(); i++ {
1832 if str.Field(i) == field {
1833 return i
1834 }
1835 }
1836
1837 panic(fmt.Sprintf("%s: %v is not a field of %v", key.Pos(), field, str))
1838 }
1839
1840
1841 func objTypeParams(obj types2.Object) *types2.TypeParamList {
1842 switch obj := obj.(type) {
1843 case *types2.Func:
1844 sig := obj.Type().(*types2.Signature)
1845 if sig.Recv() != nil {
1846 return sig.RecvTypeParams()
1847 }
1848 return sig.TypeParams()
1849 case *types2.TypeName:
1850 if !obj.IsAlias() {
1851 return obj.Type().(*types2.Named).TypeParams()
1852 }
1853 }
1854 return nil
1855 }
1856
1857 func asPragmaFlag(p syntax.Pragma) ir.PragmaFlag {
1858 if p == nil {
1859 return 0
1860 }
1861 return p.(*pragmas).Flag
1862 }
1863
View as plain text