1
2
3
4
5
6
7 package noder
8
9 import (
10 "bytes"
11 "fmt"
12 "go/constant"
13 "internal/buildcfg"
14 "strings"
15
16 "cmd/compile/internal/base"
17 "cmd/compile/internal/deadcode"
18 "cmd/compile/internal/dwarfgen"
19 "cmd/compile/internal/inline"
20 "cmd/compile/internal/ir"
21 "cmd/compile/internal/reflectdata"
22 "cmd/compile/internal/typecheck"
23 "cmd/compile/internal/types"
24 "cmd/internal/obj"
25 "cmd/internal/src"
26 )
27
28
29
30
31
32
33
34 type pkgReader struct {
35 pkgDecoder
36
37 posBases []*src.PosBase
38 pkgs []*types.Pkg
39 typs []*types.Type
40
41
42
43 newindex []int
44 }
45
46 func newPkgReader(pr pkgDecoder) *pkgReader {
47 return &pkgReader{
48 pkgDecoder: pr,
49
50 posBases: make([]*src.PosBase, pr.numElems(relocPosBase)),
51 pkgs: make([]*types.Pkg, pr.numElems(relocPkg)),
52 typs: make([]*types.Type, pr.numElems(relocType)),
53
54 newindex: make([]int, pr.totalElems()),
55 }
56 }
57
58 type pkgReaderIndex struct {
59 pr *pkgReader
60 idx int
61 dict *readerDict
62 }
63
64 func (pri pkgReaderIndex) asReader(k reloc, marker syncMarker) *reader {
65 r := pri.pr.newReader(k, pri.idx, marker)
66 r.dict = pri.dict
67 return r
68 }
69
70 func (pr *pkgReader) newReader(k reloc, idx int, marker syncMarker) *reader {
71 return &reader{
72 decoder: pr.newDecoder(k, idx, marker),
73 p: pr,
74 }
75 }
76
77 type reader struct {
78 decoder
79
80 p *pkgReader
81
82 dict *readerDict
83
84
85
86
87
88
89 curfn *ir.Func
90 locals []*ir.Name
91 closureVars []*ir.Name
92
93 funarghack bool
94
95
96
97 scopeVars []int
98 marker dwarfgen.ScopeMarker
99 lastCloseScopePos src.XPos
100
101
102
103
104
105 inlCaller *ir.Func
106 inlCall *ir.CallExpr
107 inlFunc *ir.Func
108 inlTreeIndex int
109 inlPosBases map[*src.PosBase]*src.PosBase
110
111 delayResults bool
112
113
114 retlabel *types.Sym
115
116 inlvars, retvars ir.Nodes
117 }
118
119 type readerDict struct {
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138 targs []*types.Type
139
140
141
142 implicits int
143
144 derived []derivedInfo
145 derivedTypes []*types.Type
146
147 funcs []objInfo
148 funcsObj []ir.Node
149 }
150
151 func setType(n ir.Node, typ *types.Type) {
152 n.SetType(typ)
153 n.SetTypecheck(1)
154
155 if name, ok := n.(*ir.Name); ok {
156 name.SetWalkdef(1)
157 name.Ntype = ir.TypeNode(name.Type())
158 }
159 }
160
161 func setValue(name *ir.Name, val constant.Value) {
162 name.SetVal(val)
163 name.Defn = nil
164 }
165
166
167
168 func (r *reader) pos() src.XPos {
169 return base.Ctxt.PosTable.XPos(r.pos0())
170 }
171
172 func (r *reader) pos0() src.Pos {
173 r.sync(syncPos)
174 if !r.bool() {
175 return src.NoPos
176 }
177
178 posBase := r.posBase()
179 line := r.uint()
180 col := r.uint()
181 return src.MakePos(posBase, line, col)
182 }
183
184 func (r *reader) posBase() *src.PosBase {
185 return r.inlPosBase(r.p.posBaseIdx(r.reloc(relocPosBase)))
186 }
187
188 func (pr *pkgReader) posBaseIdx(idx int) *src.PosBase {
189 if b := pr.posBases[idx]; b != nil {
190 return b
191 }
192
193 r := pr.newReader(relocPosBase, idx, syncPosBase)
194 var b *src.PosBase
195
196 absFilename := r.string()
197 filename := absFilename
198
199
200
201
202
203
204
205
206
207
208
209
210 const dollarGOROOT = "$GOROOT"
211 if strings.HasPrefix(filename, dollarGOROOT) {
212 filename = buildcfg.GOROOT + filename[len(dollarGOROOT):]
213 }
214
215 if r.bool() {
216 b = src.NewFileBase(filename, absFilename)
217 } else {
218 pos := r.pos0()
219 line := r.uint()
220 col := r.uint()
221 b = src.NewLinePragmaBase(pos, filename, absFilename, line, col)
222 }
223
224 pr.posBases[idx] = b
225 return b
226 }
227
228 func (r *reader) inlPosBase(oldBase *src.PosBase) *src.PosBase {
229 if r.inlCall == nil {
230 return oldBase
231 }
232
233 if newBase, ok := r.inlPosBases[oldBase]; ok {
234 return newBase
235 }
236
237 newBase := src.NewInliningBase(oldBase, r.inlTreeIndex)
238 r.inlPosBases[oldBase] = newBase
239 return newBase
240 }
241
242 func (r *reader) updatePos(xpos src.XPos) src.XPos {
243 pos := base.Ctxt.PosTable.Pos(xpos)
244 pos.SetBase(r.inlPosBase(pos.Base()))
245 return base.Ctxt.PosTable.XPos(pos)
246 }
247
248 func (r *reader) origPos(xpos src.XPos) src.XPos {
249 if r.inlCall == nil {
250 return xpos
251 }
252
253 pos := base.Ctxt.PosTable.Pos(xpos)
254 for old, new := range r.inlPosBases {
255 if pos.Base() == new {
256 pos.SetBase(old)
257 return base.Ctxt.PosTable.XPos(pos)
258 }
259 }
260
261 base.FatalfAt(xpos, "pos base missing from inlPosBases")
262 panic("unreachable")
263 }
264
265
266
267 func (r *reader) pkg() *types.Pkg {
268 r.sync(syncPkg)
269 return r.p.pkgIdx(r.reloc(relocPkg))
270 }
271
272 func (pr *pkgReader) pkgIdx(idx int) *types.Pkg {
273 if pkg := pr.pkgs[idx]; pkg != nil {
274 return pkg
275 }
276
277 pkg := pr.newReader(relocPkg, idx, syncPkgDef).doPkg()
278 pr.pkgs[idx] = pkg
279 return pkg
280 }
281
282 func (r *reader) doPkg() *types.Pkg {
283 path := r.string()
284 if path == "builtin" {
285 return types.BuiltinPkg
286 }
287 if path == "" {
288 path = r.p.pkgPath
289 }
290
291 name := r.string()
292 height := r.len()
293
294 pkg := types.NewPkg(path, "")
295
296 if pkg.Name == "" {
297 pkg.Name = name
298 } else {
299 assert(pkg.Name == name)
300 }
301
302 if pkg.Height == 0 {
303 pkg.Height = height
304 } else {
305 assert(pkg.Height == height)
306 }
307
308 return pkg
309 }
310
311
312
313 func (r *reader) typ() *types.Type {
314 return r.typWrapped(true)
315 }
316
317
318
319 func (r *reader) typWrapped(wrapped bool) *types.Type {
320 return r.p.typIdx(r.typInfo(), r.dict, wrapped)
321 }
322
323 func (r *reader) typInfo() typeInfo {
324 r.sync(syncType)
325 if r.bool() {
326 return typeInfo{idx: r.len(), derived: true}
327 }
328 return typeInfo{idx: r.reloc(relocType), derived: false}
329 }
330
331 func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict, wrapped bool) *types.Type {
332 idx := info.idx
333 var where **types.Type
334 if info.derived {
335 where = &dict.derivedTypes[idx]
336 idx = dict.derived[idx].idx
337 } else {
338 where = &pr.typs[idx]
339 }
340
341 if typ := *where; typ != nil {
342 return typ
343 }
344
345 r := pr.newReader(relocType, idx, syncTypeIdx)
346 r.dict = dict
347
348 typ := r.doTyp()
349 assert(typ != nil)
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391 if prev := *where; prev != nil {
392 return prev
393 }
394
395 if wrapped {
396
397
398 *where = typ
399
400 r.needWrapper(typ)
401 }
402
403 if !typ.IsUntyped() {
404 types.CheckSize(typ)
405 }
406
407 return typ
408 }
409
410 func (r *reader) doTyp() *types.Type {
411 switch tag := codeType(r.code(syncType)); tag {
412 default:
413 panic(fmt.Sprintf("unexpected type: %v", tag))
414
415 case typeBasic:
416 return *basics[r.len()]
417
418 case typeNamed:
419 obj := r.obj()
420 assert(obj.Op() == ir.OTYPE)
421 return obj.Type()
422
423 case typeTypeParam:
424 return r.dict.targs[r.len()]
425
426 case typeArray:
427 len := int64(r.uint64())
428 return types.NewArray(r.typ(), len)
429 case typeChan:
430 dir := dirs[r.len()]
431 return types.NewChan(r.typ(), dir)
432 case typeMap:
433 return types.NewMap(r.typ(), r.typ())
434 case typePointer:
435 return types.NewPtr(r.typ())
436 case typeSignature:
437 return r.signature(types.LocalPkg, nil)
438 case typeSlice:
439 return types.NewSlice(r.typ())
440 case typeStruct:
441 return r.structType()
442 case typeInterface:
443 return r.interfaceType()
444 }
445 }
446
447 func (r *reader) interfaceType() *types.Type {
448 tpkg := types.LocalPkg
449
450 nmethods, nembeddeds := r.len(), r.len()
451
452 fields := make([]*types.Field, nmethods+nembeddeds)
453 methods, embeddeds := fields[:nmethods], fields[nmethods:]
454
455 for i := range methods {
456 pos := r.pos()
457 pkg, sym := r.selector()
458 tpkg = pkg
459 mtyp := r.signature(pkg, types.FakeRecv())
460 methods[i] = types.NewField(pos, sym, mtyp)
461 }
462 for i := range embeddeds {
463 embeddeds[i] = types.NewField(src.NoXPos, nil, r.typ())
464 }
465
466 if len(fields) == 0 {
467 return types.Types[types.TINTER]
468 }
469 return types.NewInterface(tpkg, fields, false)
470 }
471
472 func (r *reader) structType() *types.Type {
473 tpkg := types.LocalPkg
474 fields := make([]*types.Field, r.len())
475 for i := range fields {
476 pos := r.pos()
477 pkg, sym := r.selector()
478 tpkg = pkg
479 ftyp := r.typ()
480 tag := r.string()
481 embedded := r.bool()
482
483 f := types.NewField(pos, sym, ftyp)
484 f.Note = tag
485 if embedded {
486 f.Embedded = 1
487 }
488 fields[i] = f
489 }
490 return types.NewStruct(tpkg, fields)
491 }
492
493 func (r *reader) signature(tpkg *types.Pkg, recv *types.Field) *types.Type {
494 r.sync(syncSignature)
495
496 params := r.params(&tpkg)
497 results := r.params(&tpkg)
498 if r.bool() {
499 params[len(params)-1].SetIsDDD(true)
500 }
501
502 return types.NewSignature(tpkg, recv, nil, params, results)
503 }
504
505 func (r *reader) params(tpkg **types.Pkg) []*types.Field {
506 r.sync(syncParams)
507 fields := make([]*types.Field, r.len())
508 for i := range fields {
509 *tpkg, fields[i] = r.param()
510 }
511 return fields
512 }
513
514 func (r *reader) param() (*types.Pkg, *types.Field) {
515 r.sync(syncParam)
516
517 pos := r.pos()
518 pkg, sym := r.localIdent()
519 typ := r.typ()
520
521 return pkg, types.NewField(pos, sym, typ)
522 }
523
524
525
526 var objReader = map[*types.Sym]pkgReaderIndex{}
527
528 func (r *reader) obj() ir.Node {
529 r.sync(syncObject)
530
531 if r.bool() {
532 idx := r.len()
533 obj := r.dict.funcsObj[idx]
534 if obj == nil {
535 fn := r.dict.funcs[idx]
536 targs := make([]*types.Type, len(fn.explicits))
537 for i, targ := range fn.explicits {
538 targs[i] = r.p.typIdx(targ, r.dict, true)
539 }
540
541 obj = r.p.objIdx(fn.idx, nil, targs)
542 assert(r.dict.funcsObj[idx] == nil)
543 r.dict.funcsObj[idx] = obj
544 }
545 return obj
546 }
547
548 idx := r.reloc(relocObj)
549
550 explicits := make([]*types.Type, r.len())
551 for i := range explicits {
552 explicits[i] = r.typ()
553 }
554
555 var implicits []*types.Type
556 if r.dict != nil {
557 implicits = r.dict.targs
558 }
559
560 return r.p.objIdx(idx, implicits, explicits)
561 }
562
563 func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node {
564 rname := pr.newReader(relocName, idx, syncObject1)
565 _, sym := rname.qualifiedIdent()
566 tag := codeObj(rname.code(syncCodeObj))
567
568 if tag == objStub {
569 assert(!sym.IsBlank())
570 switch sym.Pkg {
571 case types.BuiltinPkg, types.UnsafePkg:
572 return sym.Def.(ir.Node)
573 }
574 if pri, ok := objReader[sym]; ok {
575 return pri.pr.objIdx(pri.idx, nil, explicits)
576 }
577 if haveLegacyImports {
578 assert(len(explicits) == 0)
579 return typecheck.Resolve(ir.NewIdent(src.NoXPos, sym))
580 }
581 base.Fatalf("unresolved stub: %v", sym)
582 }
583
584 dict := pr.objDictIdx(sym, idx, implicits, explicits)
585
586 r := pr.newReader(relocObj, idx, syncObject1)
587 rext := pr.newReader(relocObjExt, idx, syncObject1)
588
589 r.dict = dict
590 rext.dict = dict
591
592 sym = r.mangle(sym)
593 if !sym.IsBlank() && sym.Def != nil {
594 return sym.Def.(*ir.Name)
595 }
596
597 do := func(op ir.Op, hasTParams bool) *ir.Name {
598 pos := r.pos()
599 if hasTParams {
600 r.typeParamNames()
601 }
602
603 name := ir.NewDeclNameAt(pos, op, sym)
604 name.Class = ir.PEXTERN
605 if !sym.IsBlank() {
606 if sym.Def != nil {
607 base.FatalfAt(name.Pos(), "already have a definition for %v", name)
608 }
609 assert(sym.Def == nil)
610 sym.Def = name
611 }
612 return name
613 }
614
615 switch tag {
616 default:
617 panic("unexpected object")
618
619 case objAlias:
620 name := do(ir.OTYPE, false)
621 setType(name, r.typ())
622 name.SetAlias(true)
623 return name
624
625 case objConst:
626 name := do(ir.OLITERAL, false)
627 typ := r.typ()
628 val := FixValue(typ, r.value())
629 setType(name, typ)
630 setValue(name, val)
631 return name
632
633 case objFunc:
634 if sym.Name == "init" {
635 sym = renameinit()
636 }
637 name := do(ir.ONAME, true)
638 setType(name, r.signature(sym.Pkg, nil))
639
640 name.Func = ir.NewFunc(r.pos())
641 name.Func.Nname = name
642
643 rext.funcExt(name)
644 return name
645
646 case objType:
647 name := do(ir.OTYPE, true)
648 typ := types.NewNamed(name)
649 setType(name, typ)
650
651
652 rext.typeExt(name)
653
654
655
656 types.DeferCheckSize()
657 typ.SetUnderlying(r.typWrapped(false))
658 types.ResumeCheckSize()
659
660 methods := make([]*types.Field, r.len())
661 for i := range methods {
662 methods[i] = r.method(rext)
663 }
664 if len(methods) != 0 {
665 typ.Methods().Set(methods)
666 }
667
668 r.needWrapper(typ)
669
670 return name
671
672 case objVar:
673 name := do(ir.ONAME, false)
674 setType(name, r.typ())
675 rext.varExt(name)
676 return name
677 }
678 }
679
680 func (r *reader) mangle(sym *types.Sym) *types.Sym {
681 if !r.hasTypeParams() {
682 return sym
683 }
684
685 var buf bytes.Buffer
686 buf.WriteString(sym.Name)
687 buf.WriteByte('[')
688 for i, targ := range r.dict.targs {
689 if i > 0 {
690 if i == r.dict.implicits {
691 buf.WriteByte(';')
692 } else {
693 buf.WriteByte(',')
694 }
695 }
696 buf.WriteString(targ.LinkString())
697 }
698 buf.WriteByte(']')
699 return sym.Pkg.Lookup(buf.String())
700 }
701
702 func (pr *pkgReader) objDictIdx(sym *types.Sym, idx int, implicits, explicits []*types.Type) *readerDict {
703 r := pr.newReader(relocObjDict, idx, syncObject1)
704
705 var dict readerDict
706
707 nimplicits := r.len()
708 nexplicits := r.len()
709
710 if nimplicits > len(implicits) || nexplicits != len(explicits) {
711 base.Fatalf("%v has %v+%v params, but instantiated with %v+%v args", sym, nimplicits, nexplicits, len(implicits), len(explicits))
712 }
713
714 dict.targs = append(implicits[:nimplicits:nimplicits], explicits...)
715 dict.implicits = nimplicits
716
717
718 for range dict.targs[dict.implicits:] {
719
720 r.sync(syncType)
721 if r.bool() {
722 r.len()
723 } else {
724 r.reloc(relocType)
725 }
726 }
727
728 dict.derived = make([]derivedInfo, r.len())
729 dict.derivedTypes = make([]*types.Type, len(dict.derived))
730 for i := range dict.derived {
731 dict.derived[i] = derivedInfo{r.reloc(relocType), r.bool()}
732 }
733
734 dict.funcs = make([]objInfo, r.len())
735 dict.funcsObj = make([]ir.Node, len(dict.funcs))
736 for i := range dict.funcs {
737 objIdx := r.reloc(relocObj)
738 targs := make([]typeInfo, r.len())
739 for j := range targs {
740 targs[j] = r.typInfo()
741 }
742 dict.funcs[i] = objInfo{idx: objIdx, explicits: targs}
743 }
744
745 return &dict
746 }
747
748 func (r *reader) typeParamNames() {
749 r.sync(syncTypeParamNames)
750
751 for range r.dict.targs[r.dict.implicits:] {
752 r.pos()
753 r.localIdent()
754 }
755 }
756
757 func (r *reader) method(rext *reader) *types.Field {
758 r.sync(syncMethod)
759 pos := r.pos()
760 pkg, sym := r.selector()
761 r.typeParamNames()
762 _, recv := r.param()
763 typ := r.signature(pkg, recv)
764
765 fnsym := sym
766 fnsym = ir.MethodSym(recv.Type, fnsym)
767 name := ir.NewNameAt(pos, fnsym)
768 setType(name, typ)
769
770 name.Func = ir.NewFunc(r.pos())
771 name.Func.Nname = name
772
773 rext.funcExt(name)
774
775 meth := types.NewField(name.Func.Pos(), sym, typ)
776 meth.Nname = name
777 meth.SetNointerface(name.Func.Pragma&ir.Nointerface != 0)
778
779 return meth
780 }
781
782 func (r *reader) qualifiedIdent() (pkg *types.Pkg, sym *types.Sym) {
783 r.sync(syncSym)
784 pkg = r.pkg()
785 if name := r.string(); name != "" {
786 sym = pkg.Lookup(name)
787 }
788 return
789 }
790
791 func (r *reader) localIdent() (pkg *types.Pkg, sym *types.Sym) {
792 r.sync(syncLocalIdent)
793 pkg = r.pkg()
794 if name := r.string(); name != "" {
795 sym = pkg.Lookup(name)
796 }
797 return
798 }
799
800 func (r *reader) selector() (origPkg *types.Pkg, sym *types.Sym) {
801 r.sync(syncSelector)
802 origPkg = r.pkg()
803 name := r.string()
804 pkg := origPkg
805 if types.IsExported(name) {
806 pkg = types.LocalPkg
807 }
808 sym = pkg.Lookup(name)
809 return
810 }
811
812 func (r *reader) hasTypeParams() bool {
813 return r.dict.hasTypeParams()
814 }
815
816 func (dict *readerDict) hasTypeParams() bool {
817 return dict != nil && len(dict.targs) != 0
818 }
819
820
821
822 func (r *reader) funcExt(name *ir.Name) {
823 r.sync(syncFuncExt)
824
825 name.Class = 0
826 ir.MarkFunc(name)
827
828 fn := name.Func
829
830
831 if !fn.Pos().IsKnown() {
832 fn.SetPos(name.Pos())
833 }
834
835
836
837
838
839
840
841
842 if name.Sym().Pkg == types.LocalPkg || r.hasTypeParams() {
843 name.Defn = fn
844 }
845
846 fn.Pragma = r.pragmaFlag()
847 r.linkname(name)
848
849 typecheck.Func(fn)
850
851 if r.bool() {
852 fn.ABI = obj.ABI(r.uint64())
853
854
855 for _, fs := range &types.RecvsParams {
856 for _, f := range fs(name.Type()).FieldSlice() {
857 f.Note = r.string()
858 }
859 }
860
861 if r.bool() {
862 fn.Inl = &ir.Inline{
863 Cost: int32(r.len()),
864 CanDelayResults: r.bool(),
865 }
866 r.addBody(name.Func)
867 }
868 } else {
869 r.addBody(name.Func)
870 }
871 r.sync(syncEOF)
872 }
873
874 func (r *reader) typeExt(name *ir.Name) {
875 r.sync(syncTypeExt)
876
877 typ := name.Type()
878
879 if r.hasTypeParams() {
880
881
882
883
884 var targs []*types.Type
885 targs = append(targs, r.dict.targs...)
886 typ.SetRParams(targs)
887 }
888
889 name.SetPragma(r.pragmaFlag())
890 if name.Pragma()&ir.NotInHeap != 0 {
891 typ.SetNotInHeap(true)
892 }
893
894 typecheck.SetBaseTypeIndex(typ, r.int64(), r.int64())
895 }
896
897 func (r *reader) varExt(name *ir.Name) {
898 r.sync(syncVarExt)
899 r.linkname(name)
900 }
901
902 func (r *reader) linkname(name *ir.Name) {
903 assert(name.Op() == ir.ONAME)
904 r.sync(syncLinkname)
905
906 if idx := r.int64(); idx >= 0 {
907 lsym := name.Linksym()
908 lsym.SymIdx = int32(idx)
909 lsym.Set(obj.AttrIndexed, true)
910 } else {
911 name.Sym().Linkname = r.string()
912 }
913 }
914
915 func (r *reader) pragmaFlag() ir.PragmaFlag {
916 r.sync(syncPragma)
917 return ir.PragmaFlag(r.int())
918 }
919
920
921
922
923
924 var bodyReader = map[*ir.Func]pkgReaderIndex{}
925
926
927
928 var todoBodies []*ir.Func
929
930
931
932
933 var todoBodiesDone = false
934
935 func (r *reader) addBody(fn *ir.Func) {
936 pri := pkgReaderIndex{r.p, r.reloc(relocBody), r.dict}
937 bodyReader[fn] = pri
938
939 if fn.Nname.Defn == nil {
940
941
942 return
943 }
944
945 if r.curfn == nil && !todoBodiesDone {
946 todoBodies = append(todoBodies, fn)
947 return
948 }
949
950 pri.funcBody(fn)
951 }
952
953 func (pri pkgReaderIndex) funcBody(fn *ir.Func) {
954 r := pri.asReader(relocBody, syncFuncBody)
955 r.funcBody(fn)
956 }
957
958 func (r *reader) funcBody(fn *ir.Func) {
959 r.curfn = fn
960 r.closureVars = fn.ClosureVars
961
962 ir.WithFunc(fn, func() {
963 r.funcargs(fn)
964
965 if !r.bool() {
966 return
967 }
968
969 body := r.stmts()
970 if body == nil {
971 pos := src.NoXPos
972 if quirksMode() {
973 pos = funcParamsEndPos(fn)
974 }
975 body = []ir.Node{typecheck.Stmt(ir.NewBlockStmt(pos, nil))}
976 }
977 fn.Body = body
978 fn.Endlineno = r.pos()
979 })
980
981 r.marker.WriteTo(fn)
982 }
983
984 func (r *reader) funcargs(fn *ir.Func) {
985 sig := fn.Nname.Type()
986
987 if recv := sig.Recv(); recv != nil {
988 r.funcarg(recv, recv.Sym, ir.PPARAM)
989 }
990 for _, param := range sig.Params().FieldSlice() {
991 r.funcarg(param, param.Sym, ir.PPARAM)
992 }
993
994 for i, param := range sig.Results().FieldSlice() {
995 sym := types.OrigSym(param.Sym)
996
997 if sym == nil || sym.IsBlank() {
998 prefix := "~r"
999 if r.inlCall != nil {
1000 prefix = "~R"
1001 } else if sym != nil {
1002 prefix = "~b"
1003 }
1004 sym = typecheck.LookupNum(prefix, i)
1005 }
1006
1007 r.funcarg(param, sym, ir.PPARAMOUT)
1008 }
1009 }
1010
1011 func (r *reader) funcarg(param *types.Field, sym *types.Sym, ctxt ir.Class) {
1012 if sym == nil {
1013 assert(ctxt == ir.PPARAM)
1014 if r.inlCall != nil {
1015 r.inlvars.Append(ir.BlankNode)
1016 }
1017 return
1018 }
1019
1020 name := ir.NewNameAt(r.updatePos(param.Pos), sym)
1021 setType(name, param.Type)
1022 r.addLocal(name, ctxt)
1023
1024 if r.inlCall == nil {
1025 if !r.funarghack {
1026 param.Sym = sym
1027 param.Nname = name
1028 }
1029 } else {
1030 if ctxt == ir.PPARAMOUT {
1031 r.retvars.Append(name)
1032 } else {
1033 r.inlvars.Append(name)
1034 }
1035 }
1036 }
1037
1038 func (r *reader) addLocal(name *ir.Name, ctxt ir.Class) {
1039 assert(ctxt == ir.PAUTO || ctxt == ir.PPARAM || ctxt == ir.PPARAMOUT)
1040
1041 r.sync(syncAddLocal)
1042 if enableSync {
1043 want := r.int()
1044 if have := len(r.locals); have != want {
1045 base.FatalfAt(name.Pos(), "locals table has desynced")
1046 }
1047 }
1048
1049 name.SetUsed(true)
1050 r.locals = append(r.locals, name)
1051
1052
1053 if ir.IsBlank(name) {
1054 return
1055 }
1056
1057 if r.inlCall != nil {
1058 if ctxt == ir.PAUTO {
1059 name.SetInlLocal(true)
1060 } else {
1061 name.SetInlFormal(true)
1062 ctxt = ir.PAUTO
1063 }
1064
1065
1066 if strings.HasPrefix(name.Sym().Name, "~") || base.Flag.GenDwarfInl == 0 {
1067 name.SetPos(r.inlCall.Pos())
1068 name.SetInlFormal(false)
1069 name.SetInlLocal(false)
1070 }
1071 }
1072
1073 name.Class = ctxt
1074 name.Curfn = r.curfn
1075
1076 r.curfn.Dcl = append(r.curfn.Dcl, name)
1077
1078 if ctxt == ir.PAUTO {
1079 name.SetFrameOffset(0)
1080 }
1081 }
1082
1083 func (r *reader) useLocal() *ir.Name {
1084 r.sync(syncUseObjLocal)
1085 if r.bool() {
1086 return r.locals[r.len()]
1087 }
1088 return r.closureVars[r.len()]
1089 }
1090
1091 func (r *reader) openScope() {
1092 r.sync(syncOpenScope)
1093 pos := r.pos()
1094
1095 if base.Flag.Dwarf {
1096 r.scopeVars = append(r.scopeVars, len(r.curfn.Dcl))
1097 r.marker.Push(pos)
1098 }
1099 }
1100
1101 func (r *reader) closeScope() {
1102 r.sync(syncCloseScope)
1103 r.lastCloseScopePos = r.pos()
1104
1105 r.closeAnotherScope()
1106 }
1107
1108
1109
1110
1111
1112 func (r *reader) closeAnotherScope() {
1113 r.sync(syncCloseAnotherScope)
1114
1115 if base.Flag.Dwarf {
1116 scopeVars := r.scopeVars[len(r.scopeVars)-1]
1117 r.scopeVars = r.scopeVars[:len(r.scopeVars)-1]
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146 retract := true
1147 for _, n := range r.curfn.Dcl[scopeVars:] {
1148 if !n.AutoTemp() {
1149 retract = false
1150 break
1151 }
1152 }
1153
1154 if retract {
1155
1156 r.marker.Unpush()
1157 } else {
1158 r.marker.Pop(r.lastCloseScopePos)
1159 }
1160 }
1161 }
1162
1163
1164
1165 func (r *reader) stmt() ir.Node {
1166 switch stmts := r.stmts(); len(stmts) {
1167 case 0:
1168 return nil
1169 case 1:
1170 return stmts[0]
1171 default:
1172 return ir.NewBlockStmt(stmts[0].Pos(), stmts)
1173 }
1174 }
1175
1176 func (r *reader) stmts() []ir.Node {
1177 assert(ir.CurFunc == r.curfn)
1178 var res ir.Nodes
1179
1180 r.sync(syncStmts)
1181 for {
1182 tag := codeStmt(r.code(syncStmt1))
1183 if tag == stmtEnd {
1184 r.sync(syncStmtsEnd)
1185 return res
1186 }
1187
1188 if n := r.stmt1(tag, &res); n != nil {
1189 res.Append(typecheck.Stmt(n))
1190 }
1191 }
1192 }
1193
1194 func (r *reader) stmt1(tag codeStmt, out *ir.Nodes) ir.Node {
1195 var label *types.Sym
1196 if n := len(*out); n > 0 {
1197 if ls, ok := (*out)[n-1].(*ir.LabelStmt); ok {
1198 label = ls.Label
1199 }
1200 }
1201
1202 switch tag {
1203 default:
1204 panic("unexpected statement")
1205
1206 case stmtAssign:
1207 pos := r.pos()
1208
1209
1210
1211 rhs := r.exprList()
1212 names, lhs := r.assignList()
1213
1214 if len(rhs) == 0 {
1215 for _, name := range names {
1216 as := ir.NewAssignStmt(pos, name, nil)
1217 as.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, name))
1218 out.Append(typecheck.Stmt(as))
1219 }
1220 return nil
1221 }
1222
1223 if len(lhs) == 1 && len(rhs) == 1 {
1224 n := ir.NewAssignStmt(pos, lhs[0], rhs[0])
1225 n.Def = r.initDefn(n, names)
1226 return n
1227 }
1228
1229 n := ir.NewAssignListStmt(pos, ir.OAS2, lhs, rhs)
1230 n.Def = r.initDefn(n, names)
1231 return n
1232
1233 case stmtAssignOp:
1234 op := r.op()
1235 lhs := r.expr()
1236 pos := r.pos()
1237 rhs := r.expr()
1238 return ir.NewAssignOpStmt(pos, op, lhs, rhs)
1239
1240 case stmtIncDec:
1241 op := r.op()
1242 lhs := r.expr()
1243 pos := r.pos()
1244 n := ir.NewAssignOpStmt(pos, op, lhs, ir.NewBasicLit(pos, one))
1245 n.IncDec = true
1246 return n
1247
1248 case stmtBlock:
1249 out.Append(r.blockStmt()...)
1250 return nil
1251
1252 case stmtBranch:
1253 pos := r.pos()
1254 op := r.op()
1255 sym := r.optLabel()
1256 return ir.NewBranchStmt(pos, op, sym)
1257
1258 case stmtCall:
1259 pos := r.pos()
1260 op := r.op()
1261 call := r.expr()
1262 return ir.NewGoDeferStmt(pos, op, call)
1263
1264 case stmtExpr:
1265 return r.expr()
1266
1267 case stmtFor:
1268 return r.forStmt(label)
1269
1270 case stmtIf:
1271 return r.ifStmt()
1272
1273 case stmtLabel:
1274 pos := r.pos()
1275 sym := r.label()
1276 return ir.NewLabelStmt(pos, sym)
1277
1278 case stmtReturn:
1279 pos := r.pos()
1280 results := r.exprList()
1281 return ir.NewReturnStmt(pos, results)
1282
1283 case stmtSelect:
1284 return r.selectStmt(label)
1285
1286 case stmtSend:
1287 pos := r.pos()
1288 ch := r.expr()
1289 value := r.expr()
1290 return ir.NewSendStmt(pos, ch, value)
1291
1292 case stmtSwitch:
1293 return r.switchStmt(label)
1294
1295 case stmtTypeDeclHack:
1296
1297 assert(quirksMode())
1298
1299 name := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, ir.BlankNode.Sym())
1300 name.SetAlias(true)
1301 setType(name, types.Types[types.TINT])
1302
1303 n := ir.NewDecl(src.NoXPos, ir.ODCLTYPE, name)
1304 n.SetTypecheck(1)
1305 return n
1306 }
1307 }
1308
1309 func (r *reader) assignList() ([]*ir.Name, []ir.Node) {
1310 lhs := make([]ir.Node, r.len())
1311 var names []*ir.Name
1312
1313 for i := range lhs {
1314 if r.bool() {
1315 pos := r.pos()
1316 _, sym := r.localIdent()
1317 typ := r.typ()
1318
1319 name := ir.NewNameAt(pos, sym)
1320 lhs[i] = name
1321 names = append(names, name)
1322 setType(name, typ)
1323 r.addLocal(name, ir.PAUTO)
1324 continue
1325 }
1326
1327 lhs[i] = r.expr()
1328 }
1329
1330 return names, lhs
1331 }
1332
1333 func (r *reader) blockStmt() []ir.Node {
1334 r.sync(syncBlockStmt)
1335 r.openScope()
1336 stmts := r.stmts()
1337 r.closeScope()
1338 return stmts
1339 }
1340
1341 func (r *reader) forStmt(label *types.Sym) ir.Node {
1342 r.sync(syncForStmt)
1343
1344 r.openScope()
1345
1346 if r.bool() {
1347 pos := r.pos()
1348
1349
1350
1351 x := r.expr()
1352 names, lhs := r.assignList()
1353
1354 body := r.blockStmt()
1355 r.closeAnotherScope()
1356
1357 rang := ir.NewRangeStmt(pos, nil, nil, x, body)
1358 if len(lhs) >= 1 {
1359 rang.Key = lhs[0]
1360 if len(lhs) >= 2 {
1361 rang.Value = lhs[1]
1362 }
1363 }
1364 rang.Def = r.initDefn(rang, names)
1365 rang.Label = label
1366 return rang
1367 }
1368
1369 pos := r.pos()
1370 init := r.stmt()
1371 cond := r.expr()
1372 post := r.stmt()
1373 body := r.blockStmt()
1374 r.closeAnotherScope()
1375
1376 stmt := ir.NewForStmt(pos, init, cond, post, body)
1377 stmt.Label = label
1378 return stmt
1379 }
1380
1381 func (r *reader) ifStmt() ir.Node {
1382 r.sync(syncIfStmt)
1383 r.openScope()
1384 pos := r.pos()
1385 init := r.stmts()
1386 cond := r.expr()
1387 then := r.blockStmt()
1388 els := r.stmts()
1389 n := ir.NewIfStmt(pos, cond, then, els)
1390 n.SetInit(init)
1391 r.closeAnotherScope()
1392 return n
1393 }
1394
1395 func (r *reader) selectStmt(label *types.Sym) ir.Node {
1396 r.sync(syncSelectStmt)
1397
1398 pos := r.pos()
1399 clauses := make([]*ir.CommClause, r.len())
1400 for i := range clauses {
1401 if i > 0 {
1402 r.closeScope()
1403 }
1404 r.openScope()
1405
1406 pos := r.pos()
1407 comm := r.stmt()
1408 body := r.stmts()
1409
1410 clauses[i] = ir.NewCommStmt(pos, comm, body)
1411 }
1412 if len(clauses) > 0 {
1413 r.closeScope()
1414 }
1415 n := ir.NewSelectStmt(pos, clauses)
1416 n.Label = label
1417 return n
1418 }
1419
1420 func (r *reader) switchStmt(label *types.Sym) ir.Node {
1421 r.sync(syncSwitchStmt)
1422
1423 r.openScope()
1424 pos := r.pos()
1425 init := r.stmt()
1426
1427 var tag ir.Node
1428 if r.bool() {
1429 pos := r.pos()
1430 var ident *ir.Ident
1431 if r.bool() {
1432 pos := r.pos()
1433 sym := typecheck.Lookup(r.string())
1434 ident = ir.NewIdent(pos, sym)
1435 }
1436 x := r.expr()
1437 tag = ir.NewTypeSwitchGuard(pos, ident, x)
1438 } else {
1439 tag = r.expr()
1440 }
1441
1442 tswitch, ok := tag.(*ir.TypeSwitchGuard)
1443 if ok && tswitch.Tag == nil {
1444 tswitch = nil
1445 }
1446
1447 clauses := make([]*ir.CaseClause, r.len())
1448 for i := range clauses {
1449 if i > 0 {
1450 r.closeScope()
1451 }
1452 r.openScope()
1453
1454 pos := r.pos()
1455 cases := r.exprList()
1456
1457 clause := ir.NewCaseStmt(pos, cases, nil)
1458 if tswitch != nil {
1459 pos := r.pos()
1460 typ := r.typ()
1461
1462 name := ir.NewNameAt(pos, tswitch.Tag.Sym())
1463 setType(name, typ)
1464 r.addLocal(name, ir.PAUTO)
1465 clause.Var = name
1466 name.Defn = tswitch
1467 }
1468
1469 clause.Body = r.stmts()
1470 clauses[i] = clause
1471 }
1472 if len(clauses) > 0 {
1473 r.closeScope()
1474 }
1475 r.closeScope()
1476
1477 n := ir.NewSwitchStmt(pos, tag, clauses)
1478 n.Label = label
1479 if init != nil {
1480 n.SetInit([]ir.Node{init})
1481 }
1482 return n
1483 }
1484
1485 func (r *reader) label() *types.Sym {
1486 r.sync(syncLabel)
1487 name := r.string()
1488 if r.inlCall != nil {
1489 name = fmt.Sprintf("~%s·%d", name, inlgen)
1490 }
1491 return typecheck.Lookup(name)
1492 }
1493
1494 func (r *reader) optLabel() *types.Sym {
1495 r.sync(syncOptLabel)
1496 if r.bool() {
1497 return r.label()
1498 }
1499 return nil
1500 }
1501
1502
1503
1504
1505 func (r *reader) initDefn(defn ir.InitNode, names []*ir.Name) bool {
1506 if len(names) == 0 {
1507 return false
1508 }
1509
1510 init := make([]ir.Node, len(names))
1511 for i, name := range names {
1512 name.Defn = defn
1513 init[i] = ir.NewDecl(name.Pos(), ir.ODCL, name)
1514 }
1515 defn.SetInit(init)
1516 return true
1517 }
1518
1519
1520
1521
1522 func (r *reader) expr() (res ir.Node) {
1523 defer func() {
1524 if res != nil && res.Typecheck() == 0 {
1525 base.FatalfAt(res.Pos(), "%v missed typecheck", res)
1526 }
1527 }()
1528
1529 switch tag := codeExpr(r.code(syncExpr)); tag {
1530 default:
1531 panic("unhandled expression")
1532
1533 case exprNone:
1534 return nil
1535
1536 case exprBlank:
1537
1538
1539 return typecheck.AssignExpr(ir.BlankNode)
1540
1541 case exprLocal:
1542 return typecheck.Expr(r.useLocal())
1543
1544 case exprName:
1545
1546
1547 return typecheck.Callee(r.obj())
1548
1549 case exprType:
1550
1551 n := ir.TypeNode(r.typ())
1552 n.SetTypecheck(1)
1553 return n
1554
1555 case exprConst:
1556 pos := r.pos()
1557 typ := r.typ()
1558 val := FixValue(typ, r.value())
1559 op := r.op()
1560 orig := r.string()
1561 return typecheck.Expr(OrigConst(pos, typ, val, op, orig))
1562
1563 case exprCompLit:
1564 return r.compLit()
1565
1566 case exprFuncLit:
1567 return r.funcLit()
1568
1569 case exprSelector:
1570 x := r.expr()
1571 pos := r.pos()
1572 _, sym := r.selector()
1573 n := typecheck.Expr(ir.NewSelectorExpr(pos, ir.OXDOT, x, sym)).(*ir.SelectorExpr)
1574 if n.Op() == ir.OMETHVALUE {
1575 wrapper := methodValueWrapper{
1576 rcvr: n.X.Type(),
1577 method: n.Selection,
1578 }
1579 if r.importedDef() {
1580 haveMethodValueWrappers = append(haveMethodValueWrappers, wrapper)
1581 } else {
1582 needMethodValueWrappers = append(needMethodValueWrappers, wrapper)
1583 }
1584 }
1585 return n
1586
1587 case exprIndex:
1588 x := r.expr()
1589 pos := r.pos()
1590 index := r.expr()
1591 return typecheck.Expr(ir.NewIndexExpr(pos, x, index))
1592
1593 case exprSlice:
1594 x := r.expr()
1595 pos := r.pos()
1596 var index [3]ir.Node
1597 for i := range index {
1598 index[i] = r.expr()
1599 }
1600 op := ir.OSLICE
1601 if index[2] != nil {
1602 op = ir.OSLICE3
1603 }
1604 return typecheck.Expr(ir.NewSliceExpr(pos, op, x, index[0], index[1], index[2]))
1605
1606 case exprAssert:
1607 x := r.expr()
1608 pos := r.pos()
1609 typ := r.expr().(ir.Ntype)
1610 return typecheck.Expr(ir.NewTypeAssertExpr(pos, x, typ))
1611
1612 case exprUnaryOp:
1613 op := r.op()
1614 pos := r.pos()
1615 x := r.expr()
1616
1617 switch op {
1618 case ir.OADDR:
1619 return typecheck.Expr(typecheck.NodAddrAt(pos, x))
1620 case ir.ODEREF:
1621 return typecheck.Expr(ir.NewStarExpr(pos, x))
1622 }
1623 return typecheck.Expr(ir.NewUnaryExpr(pos, op, x))
1624
1625 case exprBinaryOp:
1626 op := r.op()
1627 x := r.expr()
1628 pos := r.pos()
1629 y := r.expr()
1630
1631 switch op {
1632 case ir.OANDAND, ir.OOROR:
1633 return typecheck.Expr(ir.NewLogicalExpr(pos, op, x, y))
1634 }
1635 return typecheck.Expr(ir.NewBinaryExpr(pos, op, x, y))
1636
1637 case exprCall:
1638 fun := r.expr()
1639 if r.bool() {
1640 pos := r.pos()
1641 _, sym := r.selector()
1642 fun = typecheck.Callee(ir.NewSelectorExpr(pos, ir.OXDOT, fun, sym))
1643 }
1644 pos := r.pos()
1645 args := r.exprs()
1646 dots := r.bool()
1647 return typecheck.Call(pos, fun, args, dots)
1648
1649 case exprConvert:
1650 typ := r.typ()
1651 pos := r.pos()
1652 x := r.expr()
1653 return typecheck.Expr(ir.NewConvExpr(pos, ir.OCONV, typ, x))
1654 }
1655 }
1656
1657 func (r *reader) compLit() ir.Node {
1658 r.sync(syncCompLit)
1659 pos := r.pos()
1660 typ0 := r.typ()
1661
1662 typ := typ0
1663 if typ.IsPtr() {
1664 typ = typ.Elem()
1665 }
1666 if typ.Kind() == types.TFORW {
1667 base.FatalfAt(pos, "unresolved composite literal type: %v", typ)
1668 }
1669 isStruct := typ.Kind() == types.TSTRUCT
1670
1671 elems := make([]ir.Node, r.len())
1672 for i := range elems {
1673 elemp := &elems[i]
1674
1675 if isStruct {
1676 sk := ir.NewStructKeyExpr(r.pos(), typ.Field(r.len()), nil)
1677 *elemp, elemp = sk, &sk.Value
1678 } else if r.bool() {
1679 kv := ir.NewKeyExpr(r.pos(), r.expr(), nil)
1680 *elemp, elemp = kv, &kv.Value
1681 }
1682
1683 *elemp = wrapName(r.pos(), r.expr())
1684 }
1685
1686 lit := typecheck.Expr(ir.NewCompLitExpr(pos, ir.OCOMPLIT, ir.TypeNode(typ), elems))
1687 if typ0.IsPtr() {
1688 lit = typecheck.Expr(typecheck.NodAddrAt(pos, lit))
1689 lit.SetType(typ0)
1690 }
1691 return lit
1692 }
1693
1694 func wrapName(pos src.XPos, x ir.Node) ir.Node {
1695
1696
1697 switch ir.Orig(x).Op() {
1698 case ir.OTYPE, ir.OLITERAL:
1699 if x.Sym() == nil {
1700 break
1701 }
1702 fallthrough
1703 case ir.ONAME, ir.ONONAME, ir.OPACK, ir.ONIL:
1704 p := ir.NewParenExpr(pos, x)
1705 p.SetImplicit(true)
1706 return p
1707 }
1708 return x
1709 }
1710
1711 func (r *reader) funcLit() ir.Node {
1712 r.sync(syncFuncLit)
1713
1714 pos := r.pos()
1715 typPos := r.pos()
1716 xtype2 := r.signature(types.LocalPkg, nil)
1717
1718 opos := pos
1719 if quirksMode() {
1720 opos = r.origPos(pos)
1721 }
1722
1723 fn := ir.NewClosureFunc(opos, r.curfn != nil)
1724 clo := fn.OClosure
1725 ir.NameClosure(clo, r.curfn)
1726
1727 setType(fn.Nname, xtype2)
1728 if quirksMode() {
1729 fn.Nname.Ntype = ir.TypeNodeAt(typPos, xtype2)
1730 }
1731 typecheck.Func(fn)
1732 setType(clo, fn.Type())
1733
1734 fn.ClosureVars = make([]*ir.Name, 0, r.len())
1735 for len(fn.ClosureVars) < cap(fn.ClosureVars) {
1736 ir.NewClosureVar(r.pos(), fn, r.useLocal())
1737 }
1738
1739 r.addBody(fn)
1740
1741
1742 return ir.UseClosure(clo, typecheck.Target)
1743 }
1744
1745 func (r *reader) exprList() []ir.Node {
1746 r.sync(syncExprList)
1747 return r.exprs()
1748 }
1749
1750 func (r *reader) exprs() []ir.Node {
1751 r.sync(syncExprs)
1752 nodes := make([]ir.Node, r.len())
1753 if len(nodes) == 0 {
1754 return nil
1755 }
1756 for i := range nodes {
1757 nodes[i] = r.expr()
1758 }
1759 return nodes
1760 }
1761
1762 func (r *reader) op() ir.Op {
1763 r.sync(syncOp)
1764 return ir.Op(r.len())
1765 }
1766
1767
1768
1769 func (r *reader) pkgInit(self *types.Pkg, target *ir.Package) {
1770 if quirksMode() {
1771 for i, n := 0, r.len(); i < n; i++ {
1772
1773
1774 posBase := r.posBase()
1775 _ = base.Ctxt.PosTable.XPos(src.MakePos(posBase, 0, 0))
1776 }
1777
1778 for i, n := 0, r.len(); i < n; i++ {
1779
1780
1781 _, sym := r.qualifiedIdent()
1782 typecheck.Resolve(ir.NewIdent(src.NoXPos, sym))
1783 assert(sym.Def != nil)
1784 }
1785 }
1786
1787 cgoPragmas := make([][]string, r.len())
1788 for i := range cgoPragmas {
1789 cgoPragmas[i] = r.strings()
1790 }
1791 target.CgoPragmas = cgoPragmas
1792
1793 r.pkgDecls(target)
1794
1795 r.sync(syncEOF)
1796 }
1797
1798 func (r *reader) pkgDecls(target *ir.Package) {
1799 r.sync(syncDecls)
1800 for {
1801 switch code := codeDecl(r.code(syncDecl)); code {
1802 default:
1803 panic(fmt.Sprintf("unhandled decl: %v", code))
1804
1805 case declEnd:
1806 return
1807
1808 case declFunc:
1809 names := r.pkgObjs(target)
1810 assert(len(names) == 1)
1811 target.Decls = append(target.Decls, names[0].Func)
1812
1813 case declMethod:
1814 typ := r.typ()
1815 _, sym := r.selector()
1816
1817 method := typecheck.Lookdot1(nil, sym, typ, typ.Methods(), 0)
1818 target.Decls = append(target.Decls, method.Nname.(*ir.Name).Func)
1819
1820 case declVar:
1821 pos := r.pos()
1822 names := r.pkgObjs(target)
1823 values := r.exprList()
1824
1825 if len(names) > 1 && len(values) == 1 {
1826 as := ir.NewAssignListStmt(pos, ir.OAS2, nil, values)
1827 for _, name := range names {
1828 as.Lhs.Append(name)
1829 name.Defn = as
1830 }
1831 target.Decls = append(target.Decls, as)
1832 } else {
1833 for i, name := range names {
1834 as := ir.NewAssignStmt(pos, name, nil)
1835 if i < len(values) {
1836 as.Y = values[i]
1837 }
1838 name.Defn = as
1839 target.Decls = append(target.Decls, as)
1840 }
1841 }
1842
1843 if n := r.len(); n > 0 {
1844 assert(len(names) == 1)
1845 embeds := make([]ir.Embed, n)
1846 for i := range embeds {
1847 embeds[i] = ir.Embed{Pos: r.pos(), Patterns: r.strings()}
1848 }
1849 names[0].Embed = &embeds
1850 target.Embeds = append(target.Embeds, names[0])
1851 }
1852
1853 case declOther:
1854 r.pkgObjs(target)
1855 }
1856 }
1857 }
1858
1859 func (r *reader) pkgObjs(target *ir.Package) []*ir.Name {
1860 r.sync(syncDeclNames)
1861 nodes := make([]*ir.Name, r.len())
1862 for i := range nodes {
1863 r.sync(syncDeclName)
1864
1865 name := r.obj().(*ir.Name)
1866 nodes[i] = name
1867
1868 sym := name.Sym()
1869 if sym.IsBlank() {
1870 continue
1871 }
1872
1873 switch name.Class {
1874 default:
1875 base.FatalfAt(name.Pos(), "unexpected class: %v", name.Class)
1876
1877 case ir.PEXTERN:
1878 target.Externs = append(target.Externs, name)
1879
1880 case ir.PFUNC:
1881 assert(name.Type().Recv() == nil)
1882
1883
1884 if strings.HasPrefix(sym.Name, "init.") {
1885 target.Inits = append(target.Inits, name.Func)
1886 }
1887 }
1888
1889 if types.IsExported(sym.Name) {
1890 assert(!sym.OnExportList())
1891 target.Exports = append(target.Exports, name)
1892 sym.SetOnExportList(true)
1893 }
1894
1895 if base.Flag.AsmHdr != "" {
1896 assert(!sym.Asm())
1897 target.Asms = append(target.Asms, name)
1898 sym.SetAsm(true)
1899 }
1900 }
1901
1902 return nodes
1903 }
1904
1905
1906
1907 var inlgen = 0
1908
1909 func InlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr {
1910
1911 callerfn := ir.CurFunc
1912
1913 pri, ok := bodyReader[fn]
1914 if !ok {
1915
1916
1917 if haveLegacyImports {
1918 return nil
1919 }
1920
1921 base.FatalfAt(call.Pos(), "missing function body for call to %v", fn)
1922 }
1923
1924 if fn.Inl.Body == nil {
1925 expandInline(fn, pri)
1926 }
1927
1928 r := pri.asReader(relocBody, syncFuncBody)
1929
1930
1931 tmpfn := ir.NewFunc(fn.Pos())
1932 tmpfn.Nname = ir.NewNameAt(fn.Nname.Pos(), callerfn.Sym())
1933 tmpfn.Closgen = callerfn.Closgen
1934 defer func() { callerfn.Closgen = tmpfn.Closgen }()
1935
1936 setType(tmpfn.Nname, fn.Type())
1937 r.curfn = tmpfn
1938
1939 r.inlCaller = callerfn
1940 r.inlCall = call
1941 r.inlFunc = fn
1942 r.inlTreeIndex = inlIndex
1943 r.inlPosBases = make(map[*src.PosBase]*src.PosBase)
1944
1945 r.closureVars = make([]*ir.Name, len(r.inlFunc.ClosureVars))
1946 for i, cv := range r.inlFunc.ClosureVars {
1947 r.closureVars[i] = cv.Outer
1948 }
1949
1950 r.funcargs(fn)
1951
1952 assert(r.bool())
1953 r.delayResults = fn.Inl.CanDelayResults
1954
1955 r.retlabel = typecheck.AutoLabel(".i")
1956 inlgen++
1957
1958 init := ir.TakeInit(call)
1959
1960
1961
1962
1963 if call.Op() == ir.OCALLFUNC {
1964 inline.CalleeEffects(&init, call.X)
1965 }
1966
1967 var args ir.Nodes
1968 if call.Op() == ir.OCALLMETH {
1969 base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck")
1970 }
1971 args.Append(call.Args...)
1972
1973
1974 as2 := ir.NewAssignListStmt(call.Pos(), ir.OAS2, r.inlvars, args)
1975 as2.Def = true
1976 var as2init ir.Nodes
1977 for _, name := range r.inlvars {
1978 if ir.IsBlank(name) {
1979 continue
1980 }
1981
1982 name := name.(*ir.Name)
1983 as2init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
1984 name.Defn = as2
1985 }
1986 as2.SetInit(as2init)
1987 init.Append(typecheck.Stmt(as2))
1988
1989 if !r.delayResults {
1990
1991
1992 for _, name := range r.retvars {
1993
1994 name := name.(*ir.Name)
1995 init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
1996 ras := ir.NewAssignStmt(call.Pos(), name, nil)
1997 init.Append(typecheck.Stmt(ras))
1998 }
1999 }
2000
2001
2002
2003
2004
2005
2006 init.Append(ir.NewInlineMarkStmt(call.Pos().WithIsStmt(), int64(r.inlTreeIndex)))
2007
2008 nparams := len(r.curfn.Dcl)
2009
2010 ir.WithFunc(r.curfn, func() {
2011 r.curfn.Body = r.stmts()
2012 r.curfn.Endlineno = r.pos()
2013
2014 deadcode.Func(r.curfn)
2015
2016
2017 var edit func(ir.Node) ir.Node
2018 edit = func(n ir.Node) ir.Node {
2019 if ret, ok := n.(*ir.ReturnStmt); ok {
2020 n = typecheck.Stmt(r.inlReturn(ret))
2021 }
2022 ir.EditChildren(n, edit)
2023 return n
2024 }
2025 edit(r.curfn)
2026 })
2027
2028 body := ir.Nodes(r.curfn.Body)
2029
2030
2031
2032
2033
2034
2035 if quirksMode() && len(body) == 1 {
2036 if block, ok := body[0].(*ir.BlockStmt); ok && len(block.List) == 0 {
2037 block.SetPos(r.updatePos(src.NoXPos))
2038 }
2039 }
2040
2041
2042
2043
2044
2045
2046 used := usedLocals(body)
2047
2048 for i, name := range r.curfn.Dcl {
2049 if i < nparams || used.Has(name) {
2050 name.Curfn = callerfn
2051 callerfn.Dcl = append(callerfn.Dcl, name)
2052
2053
2054 if name.AutoTemp() {
2055 name.SetEsc(ir.EscUnknown)
2056
2057 if base.Flag.GenDwarfInl != 0 {
2058 name.SetInlLocal(true)
2059 } else {
2060 name.SetPos(r.inlCall.Pos())
2061 }
2062 }
2063 }
2064 }
2065
2066 body.Append(ir.NewLabelStmt(call.Pos(), r.retlabel))
2067
2068 res := ir.NewInlinedCallExpr(call.Pos(), body, append([]ir.Node(nil), r.retvars...))
2069 res.SetInit(init)
2070 res.SetType(call.Type())
2071 res.SetTypecheck(1)
2072
2073
2074 assert(len(todoBodies) == 0)
2075
2076 return res
2077 }
2078
2079
2080
2081 func (r *reader) inlReturn(ret *ir.ReturnStmt) *ir.BlockStmt {
2082 pos := r.inlCall.Pos()
2083
2084 block := ir.TakeInit(ret)
2085
2086 if results := ret.Results; len(results) != 0 {
2087 assert(len(r.retvars) == len(results))
2088
2089 as2 := ir.NewAssignListStmt(pos, ir.OAS2, append([]ir.Node(nil), r.retvars...), ret.Results)
2090
2091 if r.delayResults {
2092 for _, name := range r.retvars {
2093
2094 name := name.(*ir.Name)
2095 block.Append(ir.NewDecl(pos, ir.ODCL, name))
2096 name.Defn = as2
2097 }
2098 }
2099
2100 block.Append(as2)
2101 }
2102
2103 block.Append(ir.NewBranchStmt(pos, ir.OGOTO, r.retlabel))
2104 return ir.NewBlockStmt(pos, block)
2105 }
2106
2107
2108
2109 func expandInline(fn *ir.Func, pri pkgReaderIndex) {
2110
2111
2112
2113
2114
2115 fndcls := len(fn.Dcl)
2116 topdcls := len(typecheck.Target.Decls)
2117
2118 tmpfn := ir.NewFunc(fn.Pos())
2119 tmpfn.Nname = ir.NewNameAt(fn.Nname.Pos(), fn.Sym())
2120 tmpfn.ClosureVars = fn.ClosureVars
2121
2122 {
2123 r := pri.asReader(relocBody, syncFuncBody)
2124 setType(tmpfn.Nname, fn.Type())
2125
2126
2127 r.funarghack = true
2128
2129 r.funcBody(tmpfn)
2130
2131 ir.WithFunc(tmpfn, func() {
2132 deadcode.Func(tmpfn)
2133 })
2134 }
2135
2136 used := usedLocals(tmpfn.Body)
2137
2138 for _, name := range tmpfn.Dcl {
2139 if name.Class != ir.PAUTO || used.Has(name) {
2140 name.Curfn = fn
2141 fn.Inl.Dcl = append(fn.Inl.Dcl, name)
2142 }
2143 }
2144 fn.Inl.Body = tmpfn.Body
2145
2146
2147 assert(fndcls == len(fn.Dcl))
2148
2149
2150
2151
2152 typecheck.Target.Decls = typecheck.Target.Decls[:topdcls]
2153 }
2154
2155
2156 func usedLocals(body []ir.Node) ir.NameSet {
2157 var used ir.NameSet
2158 ir.VisitList(body, func(n ir.Node) {
2159 if n, ok := n.(*ir.Name); ok && n.Op() == ir.ONAME && n.Class == ir.PAUTO {
2160 used.Add(n)
2161 }
2162 })
2163 return used
2164 }
2165
2166
2167
2168
2169
2170 var needWrapperTypes []*types.Type
2171
2172
2173
2174 var haveWrapperTypes []*types.Type
2175
2176
2177
2178 var needMethodValueWrappers []methodValueWrapper
2179
2180
2181
2182
2183 var haveMethodValueWrappers []methodValueWrapper
2184
2185 type methodValueWrapper struct {
2186 rcvr *types.Type
2187 method *types.Field
2188 }
2189
2190 func (r *reader) needWrapper(typ *types.Type) {
2191 if typ.IsPtr() {
2192 return
2193 }
2194
2195
2196
2197
2198 if r.importedDef() {
2199 haveWrapperTypes = append(haveWrapperTypes, typ)
2200 } else {
2201 needWrapperTypes = append(needWrapperTypes, typ)
2202 }
2203 }
2204
2205 func (r *reader) importedDef() bool {
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217 return r.p != localPkgReader && !r.hasTypeParams()
2218 }
2219
2220 func MakeWrappers(target *ir.Package) {
2221
2222 if base.Debug.Unified == 0 || quirksMode() {
2223 return
2224 }
2225
2226
2227 needWrapperTypes = append(needWrapperTypes, types.ErrorType)
2228
2229 seen := make(map[string]*types.Type)
2230
2231 for _, typ := range haveWrapperTypes {
2232 wrapType(typ, target, seen, false)
2233 }
2234 haveWrapperTypes = nil
2235
2236 for _, typ := range needWrapperTypes {
2237 wrapType(typ, target, seen, true)
2238 }
2239 needWrapperTypes = nil
2240
2241 for _, wrapper := range haveMethodValueWrappers {
2242 wrapMethodValue(wrapper.rcvr, wrapper.method, target, false)
2243 }
2244 haveMethodValueWrappers = nil
2245
2246 for _, wrapper := range needMethodValueWrappers {
2247 wrapMethodValue(wrapper.rcvr, wrapper.method, target, true)
2248 }
2249 needMethodValueWrappers = nil
2250 }
2251
2252 func wrapType(typ *types.Type, target *ir.Package, seen map[string]*types.Type, needed bool) {
2253 key := typ.LinkString()
2254 if prev := seen[key]; prev != nil {
2255 if !types.Identical(typ, prev) {
2256 base.Fatalf("collision: types %v and %v have link string %q", typ, prev, key)
2257 }
2258 return
2259 }
2260 seen[key] = typ
2261
2262 if !needed {
2263
2264 return
2265 }
2266
2267 if !typ.IsInterface() {
2268 typecheck.CalcMethods(typ)
2269 }
2270 for _, meth := range typ.AllMethods().Slice() {
2271 if meth.Sym.IsBlank() || !meth.IsMethod() {
2272 base.FatalfAt(meth.Pos, "invalid method: %v", meth)
2273 }
2274
2275 methodWrapper(0, typ, meth, target)
2276
2277
2278 if !typ.IsInterface() {
2279 methodWrapper(1, typ, meth, target)
2280
2281
2282
2283 if typ.NotInHeap() {
2284 methodWrapper(2, typ, meth, target)
2285 }
2286 }
2287 }
2288 }
2289
2290 func methodWrapper(derefs int, tbase *types.Type, method *types.Field, target *ir.Package) {
2291 wrapper := tbase
2292 for i := 0; i < derefs; i++ {
2293 wrapper = types.NewPtr(wrapper)
2294 }
2295
2296 sym := ir.MethodSym(wrapper, method.Sym)
2297 base.Assertf(!sym.Siggen(), "already generated wrapper %v", sym)
2298 sym.SetSiggen(true)
2299
2300 wrappee := method.Type.Recv().Type
2301 if types.Identical(wrapper, wrappee) ||
2302 !types.IsMethodApplicable(wrapper, method) ||
2303 !reflectdata.NeedEmit(tbase) {
2304 return
2305 }
2306
2307
2308 pos := base.AutogeneratedPos
2309
2310 fn := newWrapperFunc(pos, sym, wrapper, method)
2311
2312 var recv ir.Node = fn.Nname.Type().Recv().Nname.(*ir.Name)
2313
2314
2315
2316 if wrapper.IsPtr() && types.Identical(wrapper.Elem(), wrappee) {
2317 cond := ir.NewBinaryExpr(pos, ir.OEQ, recv, types.BuiltinPkg.Lookup("nil").Def.(ir.Node))
2318 then := []ir.Node{ir.NewCallExpr(pos, ir.OCALL, typecheck.LookupRuntime("panicwrap"), nil)}
2319 fn.Body.Append(ir.NewIfStmt(pos, cond, then, nil))
2320 }
2321
2322
2323
2324 for i := 1; i < derefs; i++ {
2325 recv = Implicit(ir.NewStarExpr(pos, recv))
2326 }
2327
2328 addTailCall(pos, fn, recv, method)
2329
2330 finishWrapperFunc(fn, target)
2331 }
2332
2333 func wrapMethodValue(recvType *types.Type, method *types.Field, target *ir.Package, needed bool) {
2334 sym := ir.MethodSymSuffix(recvType, method.Sym, "-fm")
2335 if sym.Uniq() {
2336 return
2337 }
2338 sym.SetUniq(true)
2339
2340
2341 pos := base.AutogeneratedPos
2342
2343 fn := newWrapperFunc(pos, sym, nil, method)
2344 sym.Def = fn.Nname
2345
2346
2347 recv := ir.NewHiddenParam(pos, fn, typecheck.Lookup(".this"), recvType)
2348
2349 if !needed {
2350 typecheck.Func(fn)
2351 return
2352 }
2353
2354 addTailCall(pos, fn, recv, method)
2355
2356 finishWrapperFunc(fn, target)
2357 }
2358
2359 func newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field) *ir.Func {
2360 fn := ir.NewFunc(pos)
2361 fn.SetDupok(true)
2362
2363 name := ir.NewNameAt(pos, sym)
2364 ir.MarkFunc(name)
2365 name.Func = fn
2366 name.Defn = fn
2367 fn.Nname = name
2368
2369 sig := newWrapperType(wrapper, method)
2370 setType(name, sig)
2371
2372
2373 defParams := func(class ir.Class, params *types.Type) {
2374 for _, param := range params.FieldSlice() {
2375 name := ir.NewNameAt(param.Pos, param.Sym)
2376 name.Class = class
2377 setType(name, param.Type)
2378
2379 name.Curfn = fn
2380 fn.Dcl = append(fn.Dcl, name)
2381
2382 param.Nname = name
2383 }
2384 }
2385
2386 defParams(ir.PPARAM, sig.Recvs())
2387 defParams(ir.PPARAM, sig.Params())
2388 defParams(ir.PPARAMOUT, sig.Results())
2389
2390 return fn
2391 }
2392
2393 func finishWrapperFunc(fn *ir.Func, target *ir.Package) {
2394 typecheck.Func(fn)
2395
2396 ir.WithFunc(fn, func() {
2397 typecheck.Stmts(fn.Body)
2398 })
2399
2400
2401
2402 inline.InlineCalls(fn)
2403
2404 target.Decls = append(target.Decls, fn)
2405 }
2406
2407
2408
2409
2410
2411 func newWrapperType(recvType *types.Type, method *types.Field) *types.Type {
2412 clone := func(params []*types.Field) []*types.Field {
2413 res := make([]*types.Field, len(params))
2414 for i, param := range params {
2415 sym := param.Sym
2416 if sym == nil || sym.Name == "_" {
2417 sym = typecheck.LookupNum(".anon", i)
2418 }
2419 res[i] = types.NewField(param.Pos, sym, param.Type)
2420 res[i].SetIsDDD(param.IsDDD())
2421 }
2422 return res
2423 }
2424
2425 sig := method.Type
2426
2427 var recv *types.Field
2428 if recvType != nil {
2429 recv = types.NewField(sig.Recv().Pos, typecheck.Lookup(".this"), recvType)
2430 }
2431 params := clone(sig.Params().FieldSlice())
2432 results := clone(sig.Results().FieldSlice())
2433
2434 return types.NewSignature(types.NoPkg, recv, nil, params, results)
2435 }
2436
2437 func addTailCall(pos src.XPos, fn *ir.Func, recv ir.Node, method *types.Field) {
2438 sig := fn.Nname.Type()
2439 args := make([]ir.Node, sig.NumParams())
2440 for i, param := range sig.Params().FieldSlice() {
2441 args[i] = param.Nname.(*ir.Name)
2442 }
2443
2444
2445
2446
2447 fn.SetWrapper(true)
2448
2449 dot := ir.NewSelectorExpr(pos, ir.OXDOT, recv, method.Sym)
2450 call := typecheck.Call(pos, dot, args, method.Type.IsVariadic()).(*ir.CallExpr)
2451
2452 if method.Type.NumResults() == 0 {
2453 fn.Body.Append(call)
2454 return
2455 }
2456
2457 ret := ir.NewReturnStmt(pos, nil)
2458 ret.Results = []ir.Node{call}
2459 fn.Body.Append(ret)
2460 }
2461
View as plain text