1
2
3
4
5 package ssa
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108 import (
109 "fmt"
110 "go/ast"
111 "go/constant"
112 "go/token"
113 "go/types"
114 "os"
115 "sync"
116
117 "golang.org/x/tools/internal/typeparams"
118 )
119
120 type opaqueType struct {
121 types.Type
122 name string
123 }
124
125 func (t *opaqueType) String() string { return t.name }
126
127 var (
128 varOk = newVar("ok", tBool)
129 varIndex = newVar("index", tInt)
130
131
132 tBool = types.Typ[types.Bool]
133 tByte = types.Typ[types.Byte]
134 tInt = types.Typ[types.Int]
135 tInvalid = types.Typ[types.Invalid]
136 tString = types.Typ[types.String]
137 tUntypedNil = types.Typ[types.UntypedNil]
138 tRangeIter = &opaqueType{nil, "iter"}
139 tEface = types.NewInterfaceType(nil, nil).Complete()
140
141
142 vZero = intConst(0)
143 vOne = intConst(1)
144 vTrue = NewConst(constant.MakeBool(true), tBool)
145 )
146
147
148
149 type builder struct {
150
151 created *creator
152 finished int
153 rtypes int
154 }
155
156
157
158
159
160 func (b *builder) cond(fn *Function, e ast.Expr, t, f *BasicBlock) {
161 switch e := e.(type) {
162 case *ast.ParenExpr:
163 b.cond(fn, e.X, t, f)
164 return
165
166 case *ast.BinaryExpr:
167 switch e.Op {
168 case token.LAND:
169 ltrue := fn.newBasicBlock("cond.true")
170 b.cond(fn, e.X, ltrue, f)
171 fn.currentBlock = ltrue
172 b.cond(fn, e.Y, t, f)
173 return
174
175 case token.LOR:
176 lfalse := fn.newBasicBlock("cond.false")
177 b.cond(fn, e.X, t, lfalse)
178 fn.currentBlock = lfalse
179 b.cond(fn, e.Y, t, f)
180 return
181 }
182
183 case *ast.UnaryExpr:
184 if e.Op == token.NOT {
185 b.cond(fn, e.X, f, t)
186 return
187 }
188 }
189
190
191
192
193
194
195
196 emitIf(fn, b.expr(fn, e), t, f)
197 }
198
199
200
201
202 func (b *builder) logicalBinop(fn *Function, e *ast.BinaryExpr) Value {
203 rhs := fn.newBasicBlock("binop.rhs")
204 done := fn.newBasicBlock("binop.done")
205
206
207
208
209 t := fn.typeOf(e)
210
211 var short Value
212 switch e.Op {
213 case token.LAND:
214 b.cond(fn, e.X, rhs, done)
215 short = NewConst(constant.MakeBool(false), t)
216
217 case token.LOR:
218 b.cond(fn, e.X, done, rhs)
219 short = NewConst(constant.MakeBool(true), t)
220 }
221
222
223 if rhs.Preds == nil {
224
225 fn.currentBlock = done
226 return short
227 }
228
229
230 if done.Preds == nil {
231
232 fn.currentBlock = rhs
233 return b.expr(fn, e.Y)
234 }
235
236
237 var edges []Value
238 for range done.Preds {
239 edges = append(edges, short)
240 }
241
242
243 fn.currentBlock = rhs
244 edges = append(edges, b.expr(fn, e.Y))
245 emitJump(fn, done)
246 fn.currentBlock = done
247
248 phi := &Phi{Edges: edges, Comment: e.Op.String()}
249 phi.pos = e.OpPos
250 phi.typ = t
251 return done.emit(phi)
252 }
253
254
255
256
257
258
259
260
261
262 func (b *builder) exprN(fn *Function, e ast.Expr) Value {
263 typ := fn.typeOf(e).(*types.Tuple)
264 switch e := e.(type) {
265 case *ast.ParenExpr:
266 return b.exprN(fn, e.X)
267
268 case *ast.CallExpr:
269
270
271
272 var c Call
273 b.setCall(fn, e, &c.Call)
274 c.typ = typ
275 return fn.emit(&c)
276
277 case *ast.IndexExpr:
278 mapt := typeparams.CoreType(fn.typeOf(e.X)).(*types.Map)
279 lookup := &Lookup{
280 X: b.expr(fn, e.X),
281 Index: emitConv(fn, b.expr(fn, e.Index), mapt.Key()),
282 CommaOk: true,
283 }
284 lookup.setType(typ)
285 lookup.setPos(e.Lbrack)
286 return fn.emit(lookup)
287
288 case *ast.TypeAssertExpr:
289 return emitTypeTest(fn, b.expr(fn, e.X), typ.At(0).Type(), e.Lparen)
290
291 case *ast.UnaryExpr:
292 unop := &UnOp{
293 Op: token.ARROW,
294 X: b.expr(fn, e.X),
295 CommaOk: true,
296 }
297 unop.setType(typ)
298 unop.setPos(e.OpPos)
299 return fn.emit(unop)
300 }
301 panic(fmt.Sprintf("exprN(%T) in %s", e, fn))
302 }
303
304
305
306
307
308
309
310
311 func (b *builder) builtin(fn *Function, obj *types.Builtin, args []ast.Expr, typ types.Type, pos token.Pos) Value {
312 typ = fn.typ(typ)
313 switch obj.Name() {
314 case "make":
315 switch ct := typeparams.CoreType(typ).(type) {
316 case *types.Slice:
317 n := b.expr(fn, args[1])
318 m := n
319 if len(args) == 3 {
320 m = b.expr(fn, args[2])
321 }
322 if m, ok := m.(*Const); ok {
323
324 cap := m.Int64()
325 at := types.NewArray(ct.Elem(), cap)
326 alloc := emitNew(fn, at, pos)
327 alloc.Comment = "makeslice"
328 v := &Slice{
329 X: alloc,
330 High: n,
331 }
332 v.setPos(pos)
333 v.setType(typ)
334 return fn.emit(v)
335 }
336 v := &MakeSlice{
337 Len: n,
338 Cap: m,
339 }
340 v.setPos(pos)
341 v.setType(typ)
342 return fn.emit(v)
343
344 case *types.Map:
345 var res Value
346 if len(args) == 2 {
347 res = b.expr(fn, args[1])
348 }
349 v := &MakeMap{Reserve: res}
350 v.setPos(pos)
351 v.setType(typ)
352 return fn.emit(v)
353
354 case *types.Chan:
355 var sz Value = vZero
356 if len(args) == 2 {
357 sz = b.expr(fn, args[1])
358 }
359 v := &MakeChan{Size: sz}
360 v.setPos(pos)
361 v.setType(typ)
362 return fn.emit(v)
363 }
364
365 case "new":
366 alloc := emitNew(fn, deref(typ), pos)
367 alloc.Comment = "new"
368 return alloc
369
370 case "len", "cap":
371
372
373
374
375
376
377
378 t := deref(fn.typeOf(args[0])).Underlying()
379 if at, ok := t.(*types.Array); ok {
380 b.expr(fn, args[0])
381 return intConst(at.Len())
382 }
383
384
385 case "panic":
386 fn.emit(&Panic{
387 X: emitConv(fn, b.expr(fn, args[0]), tEface),
388 pos: pos,
389 })
390 fn.currentBlock = fn.newBasicBlock("unreachable")
391 return vTrue
392 }
393 return nil
394 }
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418 func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
419 switch e := e.(type) {
420 case *ast.Ident:
421 if isBlankIdent(e) {
422 return blank{}
423 }
424 obj := fn.objectOf(e)
425 var v Value
426 if g := fn.Prog.packageLevelMember(obj); g != nil {
427 v = g.(*Global)
428 } else {
429 v = fn.lookup(obj, escaping)
430 }
431 return &address{addr: v, pos: e.Pos(), expr: e}
432
433 case *ast.CompositeLit:
434 t := deref(fn.typeOf(e))
435 var v *Alloc
436 if escaping {
437 v = emitNew(fn, t, e.Lbrace)
438 } else {
439 v = fn.addLocal(t, e.Lbrace)
440 }
441 v.Comment = "complit"
442 var sb storebuf
443 b.compLit(fn, v, e, true, &sb)
444 sb.emit(fn)
445 return &address{addr: v, pos: e.Lbrace, expr: e}
446
447 case *ast.ParenExpr:
448 return b.addr(fn, e.X, escaping)
449
450 case *ast.SelectorExpr:
451 sel := fn.selection(e)
452 if sel == nil {
453
454 return b.addr(fn, e.Sel, escaping)
455 }
456 if sel.kind != types.FieldVal {
457 panic(sel)
458 }
459 wantAddr := true
460 v := b.receiver(fn, e.X, wantAddr, escaping, sel)
461 index := sel.index[len(sel.index)-1]
462 fld := typeparams.CoreType(deref(v.Type())).(*types.Struct).Field(index)
463
464
465
466
467 emit := func(fn *Function) Value {
468 return emitFieldSelection(fn, v, index, true, e.Sel)
469 }
470 return &lazyAddress{addr: emit, t: fld.Type(), pos: e.Sel.Pos(), expr: e.Sel}
471
472 case *ast.IndexExpr:
473 xt := fn.typeOf(e.X)
474 elem, mode := indexType(xt)
475 var x Value
476 var et types.Type
477 switch mode {
478 case ixArrVar:
479 x = b.addr(fn, e.X, escaping).address(fn)
480 et = types.NewPointer(elem)
481 case ixVar:
482 x = b.expr(fn, e.X)
483 et = types.NewPointer(elem)
484 case ixMap:
485 mt := typeparams.CoreType(xt).(*types.Map)
486 return &element{
487 m: b.expr(fn, e.X),
488 k: emitConv(fn, b.expr(fn, e.Index), mt.Key()),
489 t: mt.Elem(),
490 pos: e.Lbrack,
491 }
492 default:
493 panic("unexpected container type in IndexExpr: " + xt.String())
494 }
495 index := b.expr(fn, e.Index)
496 if isUntyped(index.Type()) {
497 index = emitConv(fn, index, tInt)
498 }
499
500
501
502 emit := func(fn *Function) Value {
503 v := &IndexAddr{
504 X: x,
505 Index: index,
506 }
507 v.setPos(e.Lbrack)
508 v.setType(et)
509 return fn.emit(v)
510 }
511 return &lazyAddress{addr: emit, t: deref(et), pos: e.Lbrack, expr: e}
512
513 case *ast.StarExpr:
514 return &address{addr: b.expr(fn, e.X), pos: e.Star, expr: e}
515 }
516
517 panic(fmt.Sprintf("unexpected address expression: %T", e))
518 }
519
520 type store struct {
521 lhs lvalue
522 rhs Value
523 }
524
525 type storebuf struct{ stores []store }
526
527 func (sb *storebuf) store(lhs lvalue, rhs Value) {
528 sb.stores = append(sb.stores, store{lhs, rhs})
529 }
530
531 func (sb *storebuf) emit(fn *Function) {
532 for _, s := range sb.stores {
533 s.lhs.store(fn, s.rhs)
534 }
535 }
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550 func (b *builder) assign(fn *Function, loc lvalue, e ast.Expr, isZero bool, sb *storebuf) {
551
552 if e, ok := unparen(e).(*ast.CompositeLit); ok {
553
554
555
556 if _, ok := loc.(blank); !ok {
557 if isPointer(loc.typ()) {
558 ptr := b.addr(fn, e, true).address(fn)
559
560 if sb != nil {
561 sb.store(loc, ptr)
562 } else {
563 loc.store(fn, ptr)
564 }
565 return
566 }
567 }
568
569 if _, ok := loc.(*address); ok {
570 if isNonTypeParamInterface(loc.typ()) {
571
572
573
574 } else {
575
576 addr := loc.address(fn)
577 if sb != nil {
578 b.compLit(fn, addr, e, isZero, sb)
579 } else {
580 var sb storebuf
581 b.compLit(fn, addr, e, isZero, &sb)
582 sb.emit(fn)
583 }
584
585
586
587 switch loc.typ().Underlying().(type) {
588 case *types.Struct, *types.Array:
589 emitDebugRef(fn, e, addr, true)
590 }
591
592 return
593 }
594 }
595 }
596
597
598 rhs := b.expr(fn, e)
599 if sb != nil {
600 sb.store(loc, rhs)
601 } else {
602 loc.store(fn, rhs)
603 }
604 }
605
606
607
608 func (b *builder) expr(fn *Function, e ast.Expr) Value {
609 e = unparen(e)
610
611 tv := fn.info.Types[e]
612
613
614 if tv.Value != nil {
615 return NewConst(tv.Value, fn.typ(tv.Type))
616 }
617
618 var v Value
619 if tv.Addressable() {
620
621
622
623 v = b.addr(fn, e, false).load(fn)
624 } else {
625 v = b.expr0(fn, e, tv)
626 }
627 if fn.debugInfo() {
628 emitDebugRef(fn, e, v, false)
629 }
630 return v
631 }
632
633 func (b *builder) expr0(fn *Function, e ast.Expr, tv types.TypeAndValue) Value {
634 switch e := e.(type) {
635 case *ast.BasicLit:
636 panic("non-constant BasicLit")
637
638 case *ast.FuncLit:
639 fn2 := &Function{
640 name: fmt.Sprintf("%s$%d", fn.Name(), 1+len(fn.AnonFuncs)),
641 Signature: fn.typeOf(e.Type).(*types.Signature),
642 pos: e.Type.Func,
643 parent: fn,
644 anonIdx: int32(len(fn.AnonFuncs)),
645 Pkg: fn.Pkg,
646 Prog: fn.Prog,
647 syntax: e,
648 topLevelOrigin: nil,
649 typeparams: fn.typeparams,
650 typeargs: fn.typeargs,
651 info: fn.info,
652 subst: fn.subst,
653 }
654 fn.AnonFuncs = append(fn.AnonFuncs, fn2)
655 b.created.Add(fn2)
656 b.buildFunctionBody(fn2)
657
658
659 if fn2.FreeVars == nil {
660 return fn2
661 }
662 v := &MakeClosure{Fn: fn2}
663 v.setType(fn.typ(tv.Type))
664 for _, fv := range fn2.FreeVars {
665 v.Bindings = append(v.Bindings, fv.outer)
666 fv.outer = nil
667 }
668 return fn.emit(v)
669
670 case *ast.TypeAssertExpr:
671 return emitTypeAssert(fn, b.expr(fn, e.X), fn.typ(tv.Type), e.Lparen)
672
673 case *ast.CallExpr:
674 if fn.info.Types[e.Fun].IsType() {
675
676 x := b.expr(fn, e.Args[0])
677 y := emitConv(fn, x, fn.typ(tv.Type))
678 if y != x {
679 switch y := y.(type) {
680 case *Convert:
681 y.pos = e.Lparen
682 case *ChangeType:
683 y.pos = e.Lparen
684 case *MakeInterface:
685 y.pos = e.Lparen
686 case *SliceToArrayPointer:
687 y.pos = e.Lparen
688 case *UnOp:
689 y.pos = e.Lparen
690 }
691 }
692 return y
693 }
694
695 if id, ok := unparen(e.Fun).(*ast.Ident); ok {
696 if obj, ok := fn.info.Uses[id].(*types.Builtin); ok {
697 if v := b.builtin(fn, obj, e.Args, fn.typ(tv.Type), e.Lparen); v != nil {
698 return v
699 }
700 }
701 }
702
703 var v Call
704 b.setCall(fn, e, &v.Call)
705 v.setType(fn.typ(tv.Type))
706 return fn.emit(&v)
707
708 case *ast.UnaryExpr:
709 switch e.Op {
710 case token.AND:
711 addr := b.addr(fn, e.X, true)
712 if _, ok := unparen(e.X).(*ast.StarExpr); ok {
713
714
715
716
717 addr.load(fn)
718 }
719 return addr.address(fn)
720 case token.ADD:
721 return b.expr(fn, e.X)
722 case token.NOT, token.ARROW, token.SUB, token.XOR:
723 v := &UnOp{
724 Op: e.Op,
725 X: b.expr(fn, e.X),
726 }
727 v.setPos(e.OpPos)
728 v.setType(fn.typ(tv.Type))
729 return fn.emit(v)
730 default:
731 panic(e.Op)
732 }
733
734 case *ast.BinaryExpr:
735 switch e.Op {
736 case token.LAND, token.LOR:
737 return b.logicalBinop(fn, e)
738 case token.SHL, token.SHR:
739 fallthrough
740 case token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.AND_NOT:
741 return emitArith(fn, e.Op, b.expr(fn, e.X), b.expr(fn, e.Y), fn.typ(tv.Type), e.OpPos)
742
743 case token.EQL, token.NEQ, token.GTR, token.LSS, token.LEQ, token.GEQ:
744 cmp := emitCompare(fn, e.Op, b.expr(fn, e.X), b.expr(fn, e.Y), e.OpPos)
745
746 return emitConv(fn, cmp, types.Default(fn.typ(tv.Type)))
747 default:
748 panic("illegal op in BinaryExpr: " + e.Op.String())
749 }
750
751 case *ast.SliceExpr:
752 var low, high, max Value
753 var x Value
754 xtyp := fn.typeOf(e.X)
755 switch typeparams.CoreType(xtyp).(type) {
756 case *types.Array:
757
758 x = b.addr(fn, e.X, true).address(fn)
759 case *types.Basic, *types.Slice, *types.Pointer:
760 x = b.expr(fn, e.X)
761 default:
762
763 if isBytestring(xtyp) {
764 x = b.expr(fn, e.X)
765 } else {
766 panic("unexpected sequence type in SliceExpr")
767 }
768 }
769 if e.Low != nil {
770 low = b.expr(fn, e.Low)
771 }
772 if e.High != nil {
773 high = b.expr(fn, e.High)
774 }
775 if e.Slice3 {
776 max = b.expr(fn, e.Max)
777 }
778 v := &Slice{
779 X: x,
780 Low: low,
781 High: high,
782 Max: max,
783 }
784 v.setPos(e.Lbrack)
785 v.setType(fn.typ(tv.Type))
786 return fn.emit(v)
787
788 case *ast.Ident:
789 obj := fn.info.Uses[e]
790
791 switch obj := obj.(type) {
792 case *types.Builtin:
793 return &Builtin{name: obj.Name(), sig: fn.instanceType(e).(*types.Signature)}
794 case *types.Nil:
795 return zeroConst(fn.instanceType(e))
796 }
797
798 if v := fn.Prog.packageLevelMember(obj); v != nil {
799 if g, ok := v.(*Global); ok {
800 return emitLoad(fn, g)
801 }
802 callee := v.(*Function)
803 if callee.typeparams.Len() > 0 {
804 targs := fn.subst.types(instanceArgs(fn.info, e))
805 callee = fn.Prog.needsInstance(callee, targs, b.created)
806 }
807 return callee
808 }
809
810 return emitLoad(fn, fn.lookup(obj, false))
811
812 case *ast.SelectorExpr:
813 sel := fn.selection(e)
814 if sel == nil {
815
816 if obj, ok := fn.info.Uses[e.Sel].(*types.Builtin); ok {
817 return &Builtin{name: obj.Name(), sig: fn.typ(tv.Type).(*types.Signature)}
818 }
819
820 return b.expr(fn, e.Sel)
821 }
822 switch sel.kind {
823 case types.MethodExpr:
824
825
826 thunk := makeThunk(fn.Prog, sel, b.created)
827 return emitConv(fn, thunk, fn.typ(tv.Type))
828
829 case types.MethodVal:
830
831
832 obj := sel.obj.(*types.Func)
833 rt := fn.typ(recvType(obj))
834 wantAddr := isPointer(rt)
835 escaping := true
836 v := b.receiver(fn, e.X, wantAddr, escaping, sel)
837
838 if types.IsInterface(rt) {
839
840
841 if recv, ok := sel.recv.(*typeparams.TypeParam); ok {
842
843
844 if typeSetOf(recv).Len() > 0 {
845
846
847
848
849
850
851
852
853 } else {
854
855
856 emitTypeAssert(fn, emitConv(fn, v, tEface), tEface, token.NoPos)
857 }
858 } else {
859
860
861 emitTypeAssert(fn, v, rt, token.NoPos)
862 }
863 }
864 if targs := receiverTypeArgs(obj); len(targs) > 0 {
865
866 obj = fn.Prog.canon.instantiateMethod(obj, fn.subst.types(targs), fn.Prog.ctxt)
867 }
868 c := &MakeClosure{
869 Fn: makeBound(fn.Prog, obj, b.created),
870 Bindings: []Value{v},
871 }
872 c.setPos(e.Sel.Pos())
873 c.setType(fn.typ(tv.Type))
874 return fn.emit(c)
875
876 case types.FieldVal:
877 indices := sel.index
878 last := len(indices) - 1
879 v := b.expr(fn, e.X)
880 v = emitImplicitSelections(fn, v, indices[:last], e.Pos())
881 v = emitFieldSelection(fn, v, indices[last], false, e.Sel)
882 return v
883 }
884
885 panic("unexpected expression-relative selector")
886
887 case *typeparams.IndexListExpr:
888
889 if !instance(fn.info, e.X) {
890 panic("unexpected expression-could not match index list to instantiation")
891 }
892 return b.expr(fn, e.X)
893
894 case *ast.IndexExpr:
895 if instance(fn.info, e.X) {
896 return b.expr(fn, e.X)
897 }
898
899 xt := fn.typeOf(e.X)
900 switch et, mode := indexType(xt); mode {
901 case ixVar:
902
903 return b.addr(fn, e, false).load(fn)
904
905 case ixArrVar, ixValue:
906
907
908
909
910 index := b.expr(fn, e.Index)
911 if isUntyped(index.Type()) {
912 index = emitConv(fn, index, tInt)
913 }
914 v := &Index{
915 X: b.expr(fn, e.X),
916 Index: index,
917 }
918 v.setPos(e.Lbrack)
919 v.setType(et)
920 return fn.emit(v)
921
922 case ixMap:
923 ct := typeparams.CoreType(xt).(*types.Map)
924 v := &Lookup{
925 X: b.expr(fn, e.X),
926 Index: emitConv(fn, b.expr(fn, e.Index), ct.Key()),
927 }
928 v.setPos(e.Lbrack)
929 v.setType(ct.Elem())
930 return fn.emit(v)
931 default:
932 panic("unexpected container type in IndexExpr: " + xt.String())
933 }
934
935 case *ast.CompositeLit, *ast.StarExpr:
936
937 return b.addr(fn, e, false).load(fn)
938 }
939
940 panic(fmt.Sprintf("unexpected expr: %T", e))
941 }
942
943
944 func (b *builder) stmtList(fn *Function, list []ast.Stmt) {
945 for _, s := range list {
946 b.stmt(fn, s)
947 }
948 }
949
950
951
952
953
954
955
956
957
958
959
960 func (b *builder) receiver(fn *Function, e ast.Expr, wantAddr, escaping bool, sel *selection) Value {
961 var v Value
962 if wantAddr && !sel.indirect && !isPointer(fn.typeOf(e)) {
963 v = b.addr(fn, e, escaping).address(fn)
964 } else {
965 v = b.expr(fn, e)
966 }
967
968 last := len(sel.index) - 1
969
970 v = emitImplicitSelections(fn, v, sel.index[:last], e.Pos())
971 if !wantAddr && isPointer(v.Type()) {
972 v = emitLoad(fn, v)
973 }
974 return v
975 }
976
977
978
979
980 func (b *builder) setCallFunc(fn *Function, e *ast.CallExpr, c *CallCommon) {
981 c.pos = e.Lparen
982
983
984 if selector, ok := unparen(e.Fun).(*ast.SelectorExpr); ok {
985 sel := fn.selection(selector)
986 if sel != nil && sel.kind == types.MethodVal {
987 obj := sel.obj.(*types.Func)
988 recv := recvType(obj)
989
990 wantAddr := isPointer(recv)
991 escaping := true
992 v := b.receiver(fn, selector.X, wantAddr, escaping, sel)
993 if types.IsInterface(recv) {
994
995 c.Value = v
996 c.Method = obj
997 } else {
998
999 callee := fn.Prog.originFunc(obj)
1000 if callee.typeparams.Len() > 0 {
1001 callee = fn.Prog.needsInstance(callee, receiverTypeArgs(obj), b.created)
1002 }
1003 c.Value = callee
1004 c.Args = append(c.Args, v)
1005 }
1006 return
1007 }
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038 }
1039
1040
1041 c.Value = b.expr(fn, e.Fun)
1042 }
1043
1044
1045
1046
1047 func (b *builder) emitCallArgs(fn *Function, sig *types.Signature, e *ast.CallExpr, args []Value) []Value {
1048
1049 if e.Ellipsis != 0 {
1050 for i, arg := range e.Args {
1051 v := emitConv(fn, b.expr(fn, arg), sig.Params().At(i).Type())
1052 args = append(args, v)
1053 }
1054 return args
1055 }
1056
1057 offset := len(args)
1058
1059
1060
1061
1062
1063
1064 for _, arg := range e.Args {
1065 v := b.expr(fn, arg)
1066 if ttuple, ok := v.Type().(*types.Tuple); ok {
1067 for i, n := 0, ttuple.Len(); i < n; i++ {
1068 args = append(args, emitExtract(fn, v, i))
1069 }
1070 } else {
1071 args = append(args, v)
1072 }
1073 }
1074
1075
1076 np := sig.Params().Len()
1077 if sig.Variadic() {
1078 np--
1079 }
1080 for i := 0; i < np; i++ {
1081 args[offset+i] = emitConv(fn, args[offset+i], sig.Params().At(i).Type())
1082 }
1083
1084
1085
1086 if sig.Variadic() {
1087 varargs := args[offset+np:]
1088 st := sig.Params().At(np).Type().(*types.Slice)
1089 vt := st.Elem()
1090 if len(varargs) == 0 {
1091 args = append(args, zeroConst(st))
1092 } else {
1093
1094 at := types.NewArray(vt, int64(len(varargs)))
1095 a := emitNew(fn, at, token.NoPos)
1096 a.setPos(e.Rparen)
1097 a.Comment = "varargs"
1098 for i, arg := range varargs {
1099 iaddr := &IndexAddr{
1100 X: a,
1101 Index: intConst(int64(i)),
1102 }
1103 iaddr.setType(types.NewPointer(vt))
1104 fn.emit(iaddr)
1105 emitStore(fn, iaddr, arg, arg.Pos())
1106 }
1107 s := &Slice{X: a}
1108 s.setType(st)
1109 args[offset+np] = fn.emit(s)
1110 args = args[:offset+np+1]
1111 }
1112 }
1113 return args
1114 }
1115
1116
1117
1118 func (b *builder) setCall(fn *Function, e *ast.CallExpr, c *CallCommon) {
1119
1120 b.setCallFunc(fn, e, c)
1121
1122
1123 sig, _ := typeparams.CoreType(fn.typeOf(e.Fun)).(*types.Signature)
1124 if sig == nil {
1125 panic(fmt.Sprintf("no signature for call of %s", e.Fun))
1126 }
1127 c.Args = b.emitCallArgs(fn, sig, e, c.Args)
1128 }
1129
1130
1131 func (b *builder) assignOp(fn *Function, loc lvalue, val Value, op token.Token, pos token.Pos) {
1132 loc.store(fn, emitArith(fn, op, loc.load(fn), val, loc.typ(), pos))
1133 }
1134
1135
1136
1137 func (b *builder) localValueSpec(fn *Function, spec *ast.ValueSpec) {
1138 switch {
1139 case len(spec.Values) == len(spec.Names):
1140
1141
1142 for i, id := range spec.Names {
1143 if !isBlankIdent(id) {
1144 fn.addLocalForIdent(id)
1145 }
1146 lval := b.addr(fn, id, false)
1147 b.assign(fn, lval, spec.Values[i], true, nil)
1148 }
1149
1150 case len(spec.Values) == 0:
1151
1152
1153 for _, id := range spec.Names {
1154 if !isBlankIdent(id) {
1155 lhs := fn.addLocalForIdent(id)
1156 if fn.debugInfo() {
1157 emitDebugRef(fn, id, lhs, true)
1158 }
1159 }
1160 }
1161
1162 default:
1163
1164 tuple := b.exprN(fn, spec.Values[0])
1165 for i, id := range spec.Names {
1166 if !isBlankIdent(id) {
1167 fn.addLocalForIdent(id)
1168 lhs := b.addr(fn, id, false)
1169 lhs.store(fn, emitExtract(fn, tuple, i))
1170 }
1171 }
1172 }
1173 }
1174
1175
1176
1177
1178
1179 func (b *builder) assignStmt(fn *Function, lhss, rhss []ast.Expr, isDef bool) {
1180
1181 lvals := make([]lvalue, len(lhss))
1182 isZero := make([]bool, len(lhss))
1183 for i, lhs := range lhss {
1184 var lval lvalue = blank{}
1185 if !isBlankIdent(lhs) {
1186 if isDef {
1187 if obj := fn.info.Defs[lhs.(*ast.Ident)]; obj != nil {
1188 fn.addNamedLocal(obj)
1189 isZero[i] = true
1190 }
1191 }
1192 lval = b.addr(fn, lhs, false)
1193 }
1194 lvals[i] = lval
1195 }
1196 if len(lhss) == len(rhss) {
1197
1198
1199
1200
1201
1202
1203 var sb storebuf
1204 for i := range rhss {
1205 b.assign(fn, lvals[i], rhss[i], isZero[i], &sb)
1206 }
1207 sb.emit(fn)
1208 } else {
1209
1210 tuple := b.exprN(fn, rhss[0])
1211 emitDebugRef(fn, rhss[0], tuple, false)
1212 for i, lval := range lvals {
1213 lval.store(fn, emitExtract(fn, tuple, i))
1214 }
1215 }
1216 }
1217
1218
1219 func (b *builder) arrayLen(fn *Function, elts []ast.Expr) int64 {
1220 var max int64 = -1
1221 var i int64 = -1
1222 for _, e := range elts {
1223 if kv, ok := e.(*ast.KeyValueExpr); ok {
1224 i = b.expr(fn, kv.Key).(*Const).Int64()
1225 } else {
1226 i++
1227 }
1228 if i > max {
1229 max = i
1230 }
1231 }
1232 return max + 1
1233 }
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255 func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, isZero bool, sb *storebuf) {
1256 typ := deref(fn.typeOf(e))
1257 t := deref(typeparams.CoreType(typ)).Underlying()
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281 switch t := t.(type) {
1282 case *types.Struct:
1283 if !isZero && len(e.Elts) != t.NumFields() {
1284
1285 sb.store(&address{addr, e.Lbrace, nil},
1286 zeroValue(fn, deref(addr.Type())))
1287 isZero = true
1288 }
1289 for i, e := range e.Elts {
1290 fieldIndex := i
1291 pos := e.Pos()
1292 if kv, ok := e.(*ast.KeyValueExpr); ok {
1293 fname := kv.Key.(*ast.Ident).Name
1294 for i, n := 0, t.NumFields(); i < n; i++ {
1295 sf := t.Field(i)
1296 if sf.Name() == fname {
1297 fieldIndex = i
1298 pos = kv.Colon
1299 e = kv.Value
1300 break
1301 }
1302 }
1303 }
1304 sf := t.Field(fieldIndex)
1305 faddr := &FieldAddr{
1306 X: addr,
1307 Field: fieldIndex,
1308 }
1309 faddr.setPos(pos)
1310 faddr.setType(types.NewPointer(sf.Type()))
1311 fn.emit(faddr)
1312 b.assign(fn, &address{addr: faddr, pos: pos, expr: e}, e, isZero, sb)
1313 }
1314
1315 case *types.Array, *types.Slice:
1316 var at *types.Array
1317 var array Value
1318 switch t := t.(type) {
1319 case *types.Slice:
1320 at = types.NewArray(t.Elem(), b.arrayLen(fn, e.Elts))
1321 alloc := emitNew(fn, at, e.Lbrace)
1322 alloc.Comment = "slicelit"
1323 array = alloc
1324 case *types.Array:
1325 at = t
1326 array = addr
1327
1328 if !isZero && int64(len(e.Elts)) != at.Len() {
1329
1330 sb.store(&address{array, e.Lbrace, nil},
1331 zeroValue(fn, deref(array.Type())))
1332 }
1333 }
1334
1335 var idx *Const
1336 for _, e := range e.Elts {
1337 pos := e.Pos()
1338 if kv, ok := e.(*ast.KeyValueExpr); ok {
1339 idx = b.expr(fn, kv.Key).(*Const)
1340 pos = kv.Colon
1341 e = kv.Value
1342 } else {
1343 var idxval int64
1344 if idx != nil {
1345 idxval = idx.Int64() + 1
1346 }
1347 idx = intConst(idxval)
1348 }
1349 iaddr := &IndexAddr{
1350 X: array,
1351 Index: idx,
1352 }
1353 iaddr.setType(types.NewPointer(at.Elem()))
1354 fn.emit(iaddr)
1355 if t != at {
1356
1357 b.assign(fn, &address{addr: iaddr, pos: pos, expr: e}, e, true, nil)
1358 } else {
1359 b.assign(fn, &address{addr: iaddr, pos: pos, expr: e}, e, true, sb)
1360 }
1361 }
1362
1363 if t != at {
1364 s := &Slice{X: array}
1365 s.setPos(e.Lbrace)
1366 s.setType(typ)
1367 sb.store(&address{addr: addr, pos: e.Lbrace, expr: e}, fn.emit(s))
1368 }
1369
1370 case *types.Map:
1371 m := &MakeMap{Reserve: intConst(int64(len(e.Elts)))}
1372 m.setPos(e.Lbrace)
1373 m.setType(typ)
1374 fn.emit(m)
1375 for _, e := range e.Elts {
1376 e := e.(*ast.KeyValueExpr)
1377
1378
1379
1380
1381
1382
1383
1384 var key Value
1385 if _, ok := unparen(e.Key).(*ast.CompositeLit); ok && isPointer(t.Key()) {
1386
1387
1388
1389 key = b.addr(fn, e.Key, true).address(fn)
1390 } else {
1391 key = b.expr(fn, e.Key)
1392 }
1393
1394 loc := element{
1395 m: m,
1396 k: emitConv(fn, key, t.Key()),
1397 t: t.Elem(),
1398 pos: e.Colon,
1399 }
1400
1401
1402
1403
1404
1405
1406
1407 b.assign(fn, &loc, e.Value, true, nil)
1408 }
1409 sb.store(&address{addr: addr, pos: e.Lbrace, expr: e}, m)
1410
1411 default:
1412 panic("unexpected CompositeLit type: " + t.String())
1413 }
1414 }
1415
1416
1417
1418 func (b *builder) switchStmt(fn *Function, s *ast.SwitchStmt, label *lblock) {
1419
1420
1421
1422 if s.Init != nil {
1423 b.stmt(fn, s.Init)
1424 }
1425 var tag Value = vTrue
1426 if s.Tag != nil {
1427 tag = b.expr(fn, s.Tag)
1428 }
1429 done := fn.newBasicBlock("switch.done")
1430 if label != nil {
1431 label._break = done
1432 }
1433
1434
1435
1436
1437
1438 var dfltBody *[]ast.Stmt
1439 var dfltFallthrough *BasicBlock
1440 var fallthru, dfltBlock *BasicBlock
1441 ncases := len(s.Body.List)
1442 for i, clause := range s.Body.List {
1443 body := fallthru
1444 if body == nil {
1445 body = fn.newBasicBlock("switch.body")
1446 }
1447
1448
1449 fallthru = done
1450 if i+1 < ncases {
1451 fallthru = fn.newBasicBlock("switch.body")
1452 }
1453
1454 cc := clause.(*ast.CaseClause)
1455 if cc.List == nil {
1456
1457 dfltBody = &cc.Body
1458 dfltFallthrough = fallthru
1459 dfltBlock = body
1460 continue
1461 }
1462
1463 var nextCond *BasicBlock
1464 for _, cond := range cc.List {
1465 nextCond = fn.newBasicBlock("switch.next")
1466
1467
1468
1469
1470
1471 cond := emitCompare(fn, token.EQL, tag, b.expr(fn, cond), cond.Pos())
1472 emitIf(fn, cond, body, nextCond)
1473 fn.currentBlock = nextCond
1474 }
1475 fn.currentBlock = body
1476 fn.targets = &targets{
1477 tail: fn.targets,
1478 _break: done,
1479 _fallthrough: fallthru,
1480 }
1481 b.stmtList(fn, cc.Body)
1482 fn.targets = fn.targets.tail
1483 emitJump(fn, done)
1484 fn.currentBlock = nextCond
1485 }
1486 if dfltBlock != nil {
1487 emitJump(fn, dfltBlock)
1488 fn.currentBlock = dfltBlock
1489 fn.targets = &targets{
1490 tail: fn.targets,
1491 _break: done,
1492 _fallthrough: dfltFallthrough,
1493 }
1494 b.stmtList(fn, *dfltBody)
1495 fn.targets = fn.targets.tail
1496 }
1497 emitJump(fn, done)
1498 fn.currentBlock = done
1499 }
1500
1501
1502
1503 func (b *builder) typeSwitchStmt(fn *Function, s *ast.TypeSwitchStmt, label *lblock) {
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548 if s.Init != nil {
1549 b.stmt(fn, s.Init)
1550 }
1551
1552 var x Value
1553 switch ass := s.Assign.(type) {
1554 case *ast.ExprStmt:
1555 x = b.expr(fn, unparen(ass.X).(*ast.TypeAssertExpr).X)
1556 case *ast.AssignStmt:
1557 x = b.expr(fn, unparen(ass.Rhs[0]).(*ast.TypeAssertExpr).X)
1558 }
1559
1560 done := fn.newBasicBlock("typeswitch.done")
1561 if label != nil {
1562 label._break = done
1563 }
1564 var default_ *ast.CaseClause
1565 for _, clause := range s.Body.List {
1566 cc := clause.(*ast.CaseClause)
1567 if cc.List == nil {
1568 default_ = cc
1569 continue
1570 }
1571 body := fn.newBasicBlock("typeswitch.body")
1572 var next *BasicBlock
1573 var casetype types.Type
1574 var ti Value
1575 for _, cond := range cc.List {
1576 next = fn.newBasicBlock("typeswitch.next")
1577 casetype = fn.typeOf(cond)
1578 var condv Value
1579 if casetype == tUntypedNil {
1580 condv = emitCompare(fn, token.EQL, x, zeroConst(x.Type()), cond.Pos())
1581 ti = x
1582 } else {
1583 yok := emitTypeTest(fn, x, casetype, cc.Case)
1584 ti = emitExtract(fn, yok, 0)
1585 condv = emitExtract(fn, yok, 1)
1586 }
1587 emitIf(fn, condv, body, next)
1588 fn.currentBlock = next
1589 }
1590 if len(cc.List) != 1 {
1591 ti = x
1592 }
1593 fn.currentBlock = body
1594 b.typeCaseBody(fn, cc, ti, done)
1595 fn.currentBlock = next
1596 }
1597 if default_ != nil {
1598 b.typeCaseBody(fn, default_, x, done)
1599 } else {
1600 emitJump(fn, done)
1601 }
1602 fn.currentBlock = done
1603 }
1604
1605 func (b *builder) typeCaseBody(fn *Function, cc *ast.CaseClause, x Value, done *BasicBlock) {
1606 if obj := fn.info.Implicits[cc]; obj != nil {
1607
1608
1609
1610
1611
1612 emitStore(fn, fn.addNamedLocal(obj), x, obj.Pos())
1613 }
1614 fn.targets = &targets{
1615 tail: fn.targets,
1616 _break: done,
1617 }
1618 b.stmtList(fn, cc.Body)
1619 fn.targets = fn.targets.tail
1620 emitJump(fn, done)
1621 }
1622
1623
1624
1625 func (b *builder) selectStmt(fn *Function, s *ast.SelectStmt, label *lblock) {
1626
1627
1628
1629 if len(s.Body.List) == 1 {
1630 clause := s.Body.List[0].(*ast.CommClause)
1631 if clause.Comm != nil {
1632 b.stmt(fn, clause.Comm)
1633 done := fn.newBasicBlock("select.done")
1634 if label != nil {
1635 label._break = done
1636 }
1637 fn.targets = &targets{
1638 tail: fn.targets,
1639 _break: done,
1640 }
1641 b.stmtList(fn, clause.Body)
1642 fn.targets = fn.targets.tail
1643 emitJump(fn, done)
1644 fn.currentBlock = done
1645 return
1646 }
1647 }
1648
1649
1650
1651 var states []*SelectState
1652 blocking := true
1653 debugInfo := fn.debugInfo()
1654 for _, clause := range s.Body.List {
1655 var st *SelectState
1656 switch comm := clause.(*ast.CommClause).Comm.(type) {
1657 case nil:
1658 blocking = false
1659 continue
1660
1661 case *ast.SendStmt:
1662 ch := b.expr(fn, comm.Chan)
1663 chtyp := typeparams.CoreType(fn.typ(ch.Type())).(*types.Chan)
1664 st = &SelectState{
1665 Dir: types.SendOnly,
1666 Chan: ch,
1667 Send: emitConv(fn, b.expr(fn, comm.Value), chtyp.Elem()),
1668 Pos: comm.Arrow,
1669 }
1670 if debugInfo {
1671 st.DebugNode = comm
1672 }
1673
1674 case *ast.AssignStmt:
1675 recv := unparen(comm.Rhs[0]).(*ast.UnaryExpr)
1676 st = &SelectState{
1677 Dir: types.RecvOnly,
1678 Chan: b.expr(fn, recv.X),
1679 Pos: recv.OpPos,
1680 }
1681 if debugInfo {
1682 st.DebugNode = recv
1683 }
1684
1685 case *ast.ExprStmt:
1686 recv := unparen(comm.X).(*ast.UnaryExpr)
1687 st = &SelectState{
1688 Dir: types.RecvOnly,
1689 Chan: b.expr(fn, recv.X),
1690 Pos: recv.OpPos,
1691 }
1692 if debugInfo {
1693 st.DebugNode = recv
1694 }
1695 }
1696 states = append(states, st)
1697 }
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711 sel := &Select{
1712 States: states,
1713 Blocking: blocking,
1714 }
1715 sel.setPos(s.Select)
1716 var vars []*types.Var
1717 vars = append(vars, varIndex, varOk)
1718 for _, st := range states {
1719 if st.Dir == types.RecvOnly {
1720 chtyp := typeparams.CoreType(fn.typ(st.Chan.Type())).(*types.Chan)
1721 vars = append(vars, anonVar(chtyp.Elem()))
1722 }
1723 }
1724 sel.setType(types.NewTuple(vars...))
1725
1726 fn.emit(sel)
1727 idx := emitExtract(fn, sel, 0)
1728
1729 done := fn.newBasicBlock("select.done")
1730 if label != nil {
1731 label._break = done
1732 }
1733
1734 var defaultBody *[]ast.Stmt
1735 state := 0
1736 r := 2
1737 for _, cc := range s.Body.List {
1738 clause := cc.(*ast.CommClause)
1739 if clause.Comm == nil {
1740 defaultBody = &clause.Body
1741 continue
1742 }
1743 body := fn.newBasicBlock("select.body")
1744 next := fn.newBasicBlock("select.next")
1745 emitIf(fn, emitCompare(fn, token.EQL, idx, intConst(int64(state)), token.NoPos), body, next)
1746 fn.currentBlock = body
1747 fn.targets = &targets{
1748 tail: fn.targets,
1749 _break: done,
1750 }
1751 switch comm := clause.Comm.(type) {
1752 case *ast.ExprStmt:
1753 if debugInfo {
1754 v := emitExtract(fn, sel, r)
1755 emitDebugRef(fn, states[state].DebugNode.(ast.Expr), v, false)
1756 }
1757 r++
1758
1759 case *ast.AssignStmt:
1760 if comm.Tok == token.DEFINE {
1761 fn.addLocalForIdent(comm.Lhs[0].(*ast.Ident))
1762 }
1763 x := b.addr(fn, comm.Lhs[0], false)
1764 v := emitExtract(fn, sel, r)
1765 if debugInfo {
1766 emitDebugRef(fn, states[state].DebugNode.(ast.Expr), v, false)
1767 }
1768 x.store(fn, v)
1769
1770 if len(comm.Lhs) == 2 {
1771 if comm.Tok == token.DEFINE {
1772 fn.addLocalForIdent(comm.Lhs[1].(*ast.Ident))
1773 }
1774 ok := b.addr(fn, comm.Lhs[1], false)
1775 ok.store(fn, emitExtract(fn, sel, 1))
1776 }
1777 r++
1778 }
1779 b.stmtList(fn, clause.Body)
1780 fn.targets = fn.targets.tail
1781 emitJump(fn, done)
1782 fn.currentBlock = next
1783 state++
1784 }
1785 if defaultBody != nil {
1786 fn.targets = &targets{
1787 tail: fn.targets,
1788 _break: done,
1789 }
1790 b.stmtList(fn, *defaultBody)
1791 fn.targets = fn.targets.tail
1792 } else {
1793
1794
1795 fn.emit(&Panic{
1796 X: emitConv(fn, stringConst("blocking select matched no case"), tEface),
1797 })
1798 fn.currentBlock = fn.newBasicBlock("unreachable")
1799 }
1800 emitJump(fn, done)
1801 fn.currentBlock = done
1802 }
1803
1804
1805
1806 func (b *builder) forStmt(fn *Function, s *ast.ForStmt, label *lblock) {
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818 if s.Init != nil {
1819 b.stmt(fn, s.Init)
1820 }
1821 body := fn.newBasicBlock("for.body")
1822 done := fn.newBasicBlock("for.done")
1823 loop := body
1824 if s.Cond != nil {
1825 loop = fn.newBasicBlock("for.loop")
1826 }
1827 cont := loop
1828 if s.Post != nil {
1829 cont = fn.newBasicBlock("for.post")
1830 }
1831 if label != nil {
1832 label._break = done
1833 label._continue = cont
1834 }
1835 emitJump(fn, loop)
1836 fn.currentBlock = loop
1837 if loop != body {
1838 b.cond(fn, s.Cond, body, done)
1839 fn.currentBlock = body
1840 }
1841 fn.targets = &targets{
1842 tail: fn.targets,
1843 _break: done,
1844 _continue: cont,
1845 }
1846 b.stmt(fn, s.Body)
1847 fn.targets = fn.targets.tail
1848 emitJump(fn, cont)
1849
1850 if s.Post != nil {
1851 fn.currentBlock = cont
1852 b.stmt(fn, s.Post)
1853 emitJump(fn, loop)
1854 }
1855 fn.currentBlock = done
1856 }
1857
1858
1859
1860
1861
1862 func (b *builder) rangeIndexed(fn *Function, x Value, tv types.Type, pos token.Pos) (k, v Value, loop, done *BasicBlock) {
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877 var length Value
1878 if arr, ok := deref(x.Type()).Underlying().(*types.Array); ok {
1879
1880
1881
1882
1883
1884
1885
1886
1887 length = intConst(arr.Len())
1888 } else {
1889
1890 var c Call
1891 c.Call.Value = makeLen(x.Type())
1892 c.Call.Args = []Value{x}
1893 c.setType(tInt)
1894 length = fn.emit(&c)
1895 }
1896
1897 index := fn.addLocal(tInt, token.NoPos)
1898 emitStore(fn, index, intConst(-1), pos)
1899
1900 loop = fn.newBasicBlock("rangeindex.loop")
1901 emitJump(fn, loop)
1902 fn.currentBlock = loop
1903
1904 incr := &BinOp{
1905 Op: token.ADD,
1906 X: emitLoad(fn, index),
1907 Y: vOne,
1908 }
1909 incr.setType(tInt)
1910 emitStore(fn, index, fn.emit(incr), pos)
1911
1912 body := fn.newBasicBlock("rangeindex.body")
1913 done = fn.newBasicBlock("rangeindex.done")
1914 emitIf(fn, emitCompare(fn, token.LSS, incr, length, token.NoPos), body, done)
1915 fn.currentBlock = body
1916
1917 k = emitLoad(fn, index)
1918 if tv != nil {
1919 switch t := typeparams.CoreType(x.Type()).(type) {
1920 case *types.Array:
1921 instr := &Index{
1922 X: x,
1923 Index: k,
1924 }
1925 instr.setType(t.Elem())
1926 instr.setPos(x.Pos())
1927 v = fn.emit(instr)
1928
1929 case *types.Pointer:
1930 instr := &IndexAddr{
1931 X: x,
1932 Index: k,
1933 }
1934 instr.setType(types.NewPointer(t.Elem().Underlying().(*types.Array).Elem()))
1935 instr.setPos(x.Pos())
1936 v = emitLoad(fn, fn.emit(instr))
1937
1938 case *types.Slice:
1939 instr := &IndexAddr{
1940 X: x,
1941 Index: k,
1942 }
1943 instr.setType(types.NewPointer(t.Elem()))
1944 instr.setPos(x.Pos())
1945 v = emitLoad(fn, fn.emit(instr))
1946
1947 default:
1948 panic("rangeIndexed x:" + t.String())
1949 }
1950 }
1951 return
1952 }
1953
1954
1955
1956
1957
1958 func (b *builder) rangeIter(fn *Function, x Value, tk, tv types.Type, pos token.Pos) (k, v Value, loop, done *BasicBlock) {
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973 if tk == nil {
1974 tk = tInvalid
1975 }
1976 if tv == nil {
1977 tv = tInvalid
1978 }
1979
1980 rng := &Range{X: x}
1981 rng.setPos(pos)
1982 rng.setType(tRangeIter)
1983 it := fn.emit(rng)
1984
1985 loop = fn.newBasicBlock("rangeiter.loop")
1986 emitJump(fn, loop)
1987 fn.currentBlock = loop
1988
1989 okv := &Next{
1990 Iter: it,
1991 IsString: isBasic(typeparams.CoreType(x.Type())),
1992 }
1993 okv.setType(types.NewTuple(
1994 varOk,
1995 newVar("k", tk),
1996 newVar("v", tv),
1997 ))
1998 fn.emit(okv)
1999
2000 body := fn.newBasicBlock("rangeiter.body")
2001 done = fn.newBasicBlock("rangeiter.done")
2002 emitIf(fn, emitExtract(fn, okv, 0), body, done)
2003 fn.currentBlock = body
2004
2005 if tk != tInvalid {
2006 k = emitExtract(fn, okv, 1)
2007 }
2008 if tv != tInvalid {
2009 v = emitExtract(fn, okv, 2)
2010 }
2011 return
2012 }
2013
2014
2015
2016
2017
2018
2019 func (b *builder) rangeChan(fn *Function, x Value, tk types.Type, pos token.Pos) (k Value, loop, done *BasicBlock) {
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031 loop = fn.newBasicBlock("rangechan.loop")
2032 emitJump(fn, loop)
2033 fn.currentBlock = loop
2034 recv := &UnOp{
2035 Op: token.ARROW,
2036 X: x,
2037 CommaOk: true,
2038 }
2039 recv.setPos(pos)
2040 recv.setType(types.NewTuple(
2041 newVar("k", typeparams.CoreType(x.Type()).(*types.Chan).Elem()),
2042 varOk,
2043 ))
2044 ko := fn.emit(recv)
2045 body := fn.newBasicBlock("rangechan.body")
2046 done = fn.newBasicBlock("rangechan.done")
2047 emitIf(fn, emitExtract(fn, ko, 1), body, done)
2048 fn.currentBlock = body
2049 if tk != nil {
2050 k = emitExtract(fn, ko, 0)
2051 }
2052 return
2053 }
2054
2055
2056
2057 func (b *builder) rangeStmt(fn *Function, s *ast.RangeStmt, label *lblock) {
2058 var tk, tv types.Type
2059 if s.Key != nil && !isBlankIdent(s.Key) {
2060 tk = fn.typeOf(s.Key)
2061 }
2062 if s.Value != nil && !isBlankIdent(s.Value) {
2063 tv = fn.typeOf(s.Value)
2064 }
2065
2066
2067
2068
2069
2070
2071
2072 if s.Tok == token.DEFINE {
2073 if tk != nil {
2074 fn.addLocalForIdent(s.Key.(*ast.Ident))
2075 }
2076 if tv != nil {
2077 fn.addLocalForIdent(s.Value.(*ast.Ident))
2078 }
2079 }
2080
2081 x := b.expr(fn, s.X)
2082
2083 var k, v Value
2084 var loop, done *BasicBlock
2085 switch rt := typeparams.CoreType(x.Type()).(type) {
2086 case *types.Slice, *types.Array, *types.Pointer:
2087 k, v, loop, done = b.rangeIndexed(fn, x, tv, s.For)
2088
2089 case *types.Chan:
2090 k, loop, done = b.rangeChan(fn, x, tk, s.For)
2091
2092 case *types.Map, *types.Basic:
2093 k, v, loop, done = b.rangeIter(fn, x, tk, tv, s.For)
2094
2095 default:
2096 panic("Cannot range over: " + rt.String())
2097 }
2098
2099
2100 var kl, vl lvalue
2101 if tk != nil {
2102 kl = b.addr(fn, s.Key, false)
2103 }
2104 if tv != nil {
2105 vl = b.addr(fn, s.Value, false)
2106 }
2107 if tk != nil {
2108 kl.store(fn, k)
2109 }
2110 if tv != nil {
2111 vl.store(fn, v)
2112 }
2113
2114 if label != nil {
2115 label._break = done
2116 label._continue = loop
2117 }
2118
2119 fn.targets = &targets{
2120 tail: fn.targets,
2121 _break: done,
2122 _continue: loop,
2123 }
2124 b.stmt(fn, s.Body)
2125 fn.targets = fn.targets.tail
2126 emitJump(fn, loop)
2127 fn.currentBlock = done
2128 }
2129
2130
2131 func (b *builder) stmt(fn *Function, _s ast.Stmt) {
2132
2133
2134
2135
2136 var label *lblock
2137 start:
2138 switch s := _s.(type) {
2139 case *ast.EmptyStmt:
2140
2141
2142 case *ast.DeclStmt:
2143 d := s.Decl.(*ast.GenDecl)
2144 if d.Tok == token.VAR {
2145 for _, spec := range d.Specs {
2146 if vs, ok := spec.(*ast.ValueSpec); ok {
2147 b.localValueSpec(fn, vs)
2148 }
2149 }
2150 }
2151
2152 case *ast.LabeledStmt:
2153 label = fn.labelledBlock(s.Label)
2154 emitJump(fn, label._goto)
2155 fn.currentBlock = label._goto
2156 _s = s.Stmt
2157 goto start
2158
2159 case *ast.ExprStmt:
2160 b.expr(fn, s.X)
2161
2162 case *ast.SendStmt:
2163 chtyp := typeparams.CoreType(fn.typeOf(s.Chan)).(*types.Chan)
2164 fn.emit(&Send{
2165 Chan: b.expr(fn, s.Chan),
2166 X: emitConv(fn, b.expr(fn, s.Value), chtyp.Elem()),
2167 pos: s.Arrow,
2168 })
2169
2170 case *ast.IncDecStmt:
2171 op := token.ADD
2172 if s.Tok == token.DEC {
2173 op = token.SUB
2174 }
2175 loc := b.addr(fn, s.X, false)
2176 b.assignOp(fn, loc, NewConst(constant.MakeInt64(1), loc.typ()), op, s.Pos())
2177
2178 case *ast.AssignStmt:
2179 switch s.Tok {
2180 case token.ASSIGN, token.DEFINE:
2181 b.assignStmt(fn, s.Lhs, s.Rhs, s.Tok == token.DEFINE)
2182
2183 default:
2184 op := s.Tok + token.ADD - token.ADD_ASSIGN
2185 b.assignOp(fn, b.addr(fn, s.Lhs[0], false), b.expr(fn, s.Rhs[0]), op, s.Pos())
2186 }
2187
2188 case *ast.GoStmt:
2189
2190
2191 v := Go{pos: s.Go}
2192 b.setCall(fn, s.Call, &v.Call)
2193 fn.emit(&v)
2194
2195 case *ast.DeferStmt:
2196
2197
2198 v := Defer{pos: s.Defer}
2199 b.setCall(fn, s.Call, &v.Call)
2200 fn.emit(&v)
2201
2202
2203
2204 createRecoverBlock(fn)
2205
2206 case *ast.ReturnStmt:
2207 var results []Value
2208 if len(s.Results) == 1 && fn.Signature.Results().Len() > 1 {
2209
2210 tuple := b.exprN(fn, s.Results[0])
2211 ttuple := tuple.Type().(*types.Tuple)
2212 for i, n := 0, ttuple.Len(); i < n; i++ {
2213 results = append(results,
2214 emitConv(fn, emitExtract(fn, tuple, i),
2215 fn.Signature.Results().At(i).Type()))
2216 }
2217 } else {
2218
2219 for i, r := range s.Results {
2220 v := emitConv(fn, b.expr(fn, r), fn.Signature.Results().At(i).Type())
2221 results = append(results, v)
2222 }
2223 }
2224 if fn.namedResults != nil {
2225
2226
2227 for i, r := range results {
2228 emitStore(fn, fn.namedResults[i], r, s.Return)
2229 }
2230 }
2231
2232
2233 fn.emit(new(RunDefers))
2234 if fn.namedResults != nil {
2235
2236 results = results[:0]
2237 for _, r := range fn.namedResults {
2238 results = append(results, emitLoad(fn, r))
2239 }
2240 }
2241 fn.emit(&Return{Results: results, pos: s.Return})
2242 fn.currentBlock = fn.newBasicBlock("unreachable")
2243
2244 case *ast.BranchStmt:
2245 var block *BasicBlock
2246 switch s.Tok {
2247 case token.BREAK:
2248 if s.Label != nil {
2249 block = fn.labelledBlock(s.Label)._break
2250 } else {
2251 for t := fn.targets; t != nil && block == nil; t = t.tail {
2252 block = t._break
2253 }
2254 }
2255
2256 case token.CONTINUE:
2257 if s.Label != nil {
2258 block = fn.labelledBlock(s.Label)._continue
2259 } else {
2260 for t := fn.targets; t != nil && block == nil; t = t.tail {
2261 block = t._continue
2262 }
2263 }
2264
2265 case token.FALLTHROUGH:
2266 for t := fn.targets; t != nil && block == nil; t = t.tail {
2267 block = t._fallthrough
2268 }
2269
2270 case token.GOTO:
2271 block = fn.labelledBlock(s.Label)._goto
2272 }
2273 emitJump(fn, block)
2274 fn.currentBlock = fn.newBasicBlock("unreachable")
2275
2276 case *ast.BlockStmt:
2277 b.stmtList(fn, s.List)
2278
2279 case *ast.IfStmt:
2280 if s.Init != nil {
2281 b.stmt(fn, s.Init)
2282 }
2283 then := fn.newBasicBlock("if.then")
2284 done := fn.newBasicBlock("if.done")
2285 els := done
2286 if s.Else != nil {
2287 els = fn.newBasicBlock("if.else")
2288 }
2289 b.cond(fn, s.Cond, then, els)
2290 fn.currentBlock = then
2291 b.stmt(fn, s.Body)
2292 emitJump(fn, done)
2293
2294 if s.Else != nil {
2295 fn.currentBlock = els
2296 b.stmt(fn, s.Else)
2297 emitJump(fn, done)
2298 }
2299
2300 fn.currentBlock = done
2301
2302 case *ast.SwitchStmt:
2303 b.switchStmt(fn, s, label)
2304
2305 case *ast.TypeSwitchStmt:
2306 b.typeSwitchStmt(fn, s, label)
2307
2308 case *ast.SelectStmt:
2309 b.selectStmt(fn, s, label)
2310
2311 case *ast.ForStmt:
2312 b.forStmt(fn, s, label)
2313
2314 case *ast.RangeStmt:
2315 b.rangeStmt(fn, s, label)
2316
2317 default:
2318 panic(fmt.Sprintf("unexpected statement kind: %T", s))
2319 }
2320 }
2321
2322
2323 func (b *builder) buildFunction(fn *Function) {
2324 if !fn.built {
2325 assert(fn.parent == nil, "anonymous functions should not be built by buildFunction()")
2326 b.buildFunctionBody(fn)
2327 fn.done()
2328 }
2329 }
2330
2331
2332
2333
2334 func (b *builder) buildFunctionBody(fn *Function) {
2335
2336 if fn.Blocks != nil {
2337 return
2338 }
2339
2340 var recvField *ast.FieldList
2341 var body *ast.BlockStmt
2342 var functype *ast.FuncType
2343 switch n := fn.syntax.(type) {
2344 case nil:
2345 if fn.Params != nil {
2346 return
2347 }
2348 case *ast.FuncDecl:
2349 functype = n.Type
2350 recvField = n.Recv
2351 body = n.Body
2352 case *ast.FuncLit:
2353 functype = n.Type
2354 body = n.Body
2355 default:
2356 panic(n)
2357 }
2358
2359 if body == nil {
2360
2361 if fn.Params == nil {
2362
2363
2364
2365
2366
2367
2368
2369 if recv := fn.Signature.Recv(); recv != nil {
2370 fn.addParamObj(recv)
2371 }
2372 params := fn.Signature.Params()
2373 for i, n := 0, params.Len(); i < n; i++ {
2374 fn.addParamObj(params.At(i))
2375 }
2376 }
2377 return
2378 }
2379
2380
2381 if fn.topLevelOrigin != nil && fn.subst == nil {
2382 buildInstantiationWrapper(fn)
2383 return
2384 }
2385
2386 if fn.Prog.mode&LogSource != 0 {
2387 defer logStack("build function %s @ %s", fn, fn.Prog.Fset.Position(fn.pos))()
2388 }
2389 fn.startBody()
2390 fn.createSyntacticParams(recvField, functype)
2391 b.stmt(fn, body)
2392 if cb := fn.currentBlock; cb != nil && (cb == fn.Blocks[0] || cb == fn.Recover || cb.Preds != nil) {
2393
2394
2395
2396
2397
2398
2399
2400 fn.emit(new(RunDefers))
2401 fn.emit(new(Return))
2402 }
2403 fn.finishBody()
2404 }
2405
2406
2407
2408
2409
2410 func (b *builder) buildCreated() {
2411 for ; b.finished < b.created.Len(); b.finished++ {
2412 fn := b.created.At(b.finished)
2413 b.buildFunction(fn)
2414 }
2415 }
2416
2417
2418
2419
2420
2421
2422 func (b *builder) needsRuntimeTypes() {
2423 if b.created.Len() == 0 {
2424 return
2425 }
2426 prog := b.created.At(0).Prog
2427
2428 var rtypes []types.Type
2429 for ; b.rtypes < b.finished; b.rtypes++ {
2430 fn := b.created.At(b.rtypes)
2431 rtypes = append(rtypes, mayNeedRuntimeTypes(fn)...)
2432 }
2433
2434
2435
2436 rtypes = nonbasicTypes(rtypes)
2437
2438 for _, T := range rtypes {
2439 prog.needMethodsOf(T, b.created)
2440 }
2441 }
2442
2443 func (b *builder) done() bool {
2444 return b.rtypes >= b.created.Len()
2445 }
2446
2447
2448
2449
2450
2451
2452
2453
2454 func (prog *Program) Build() {
2455 var wg sync.WaitGroup
2456 for _, p := range prog.packages {
2457 if prog.mode&BuildSerially != 0 {
2458 p.Build()
2459 } else {
2460 wg.Add(1)
2461 go func(p *Package) {
2462 p.Build()
2463 wg.Done()
2464 }(p)
2465 }
2466 }
2467 wg.Wait()
2468 }
2469
2470
2471
2472
2473
2474
2475
2476
2477 func (p *Package) Build() { p.buildOnce.Do(p.build) }
2478
2479 func (p *Package) build() {
2480 if p.info == nil {
2481 return
2482 }
2483
2484
2485
2486
2487
2488
2489 for name, mem := range p.Members {
2490 isGround := func(m Member) bool {
2491 switch m := m.(type) {
2492 case *Type:
2493 named, _ := m.Type().(*types.Named)
2494 return named == nil || typeparams.ForNamed(named) == nil
2495 case *Function:
2496 return m.typeparams.Len() == 0
2497 }
2498 return true
2499 }
2500 if ast.IsExported(name) && isGround(mem) {
2501 p.Prog.needMethodsOf(mem.Type(), &p.created)
2502 }
2503 }
2504 if p.Prog.mode&LogSource != 0 {
2505 defer logStack("build %s", p)()
2506 }
2507
2508 b := builder{created: &p.created}
2509 init := p.init
2510 init.startBody()
2511
2512 var done *BasicBlock
2513
2514 if p.Prog.mode&BareInits == 0 {
2515
2516 initguard := p.Var("init$guard")
2517 doinit := init.newBasicBlock("init.start")
2518 done = init.newBasicBlock("init.done")
2519 emitIf(init, emitLoad(init, initguard), done, doinit)
2520 init.currentBlock = doinit
2521 emitStore(init, initguard, vTrue, token.NoPos)
2522
2523
2524 for _, pkg := range p.Pkg.Imports() {
2525 prereq := p.Prog.packages[pkg]
2526 if prereq == nil {
2527 panic(fmt.Sprintf("Package(%q).Build(): unsatisfied import: Program.CreatePackage(%q) was not called", p.Pkg.Path(), pkg.Path()))
2528 }
2529 var v Call
2530 v.Call.Value = prereq.init
2531 v.Call.pos = init.pos
2532 v.setType(types.NewTuple())
2533 init.emit(&v)
2534 }
2535 }
2536
2537
2538 if len(p.info.InitOrder) > 0 && len(p.files) == 0 {
2539 panic("no source files provided for package. cannot initialize globals")
2540 }
2541 for _, varinit := range p.info.InitOrder {
2542 if init.Prog.mode&LogSource != 0 {
2543 fmt.Fprintf(os.Stderr, "build global initializer %v @ %s\n",
2544 varinit.Lhs, p.Prog.Fset.Position(varinit.Rhs.Pos()))
2545 }
2546 if len(varinit.Lhs) == 1 {
2547
2548 var lval lvalue
2549 if v := varinit.Lhs[0]; v.Name() != "_" {
2550 lval = &address{addr: p.objects[v].(*Global), pos: v.Pos()}
2551 } else {
2552 lval = blank{}
2553 }
2554 b.assign(init, lval, varinit.Rhs, true, nil)
2555 } else {
2556
2557 tuple := b.exprN(init, varinit.Rhs)
2558 for i, v := range varinit.Lhs {
2559 if v.Name() == "_" {
2560 continue
2561 }
2562 emitStore(init, p.objects[v].(*Global), emitExtract(init, tuple, i), v.Pos())
2563 }
2564 }
2565 }
2566
2567
2568 for _, file := range p.files {
2569 for _, decl := range file.Decls {
2570 if decl, ok := decl.(*ast.FuncDecl); ok {
2571 id := decl.Name
2572 if !isBlankIdent(id) && id.Name == "init" && decl.Recv == nil {
2573 fn := p.objects[p.info.Defs[id]].(*Function)
2574 var v Call
2575 v.Call.Value = fn
2576 v.setType(types.NewTuple())
2577 p.init.emit(&v)
2578 }
2579 }
2580 }
2581 }
2582
2583
2584 if p.Prog.mode&BareInits == 0 {
2585 emitJump(init, done)
2586 init.currentBlock = done
2587 }
2588 init.emit(new(Return))
2589 init.finishBody()
2590 init.done()
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605 for !b.done() {
2606 b.buildCreated()
2607 b.needsRuntimeTypes()
2608 }
2609
2610 p.info = nil
2611 p.created = nil
2612
2613 if p.Prog.mode&SanityCheckFunctions != 0 {
2614 sanityCheckPackage(p)
2615 }
2616 }
2617
View as plain text