1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package noder
20
21 import (
22 "cmd/compile/internal/base"
23 "cmd/compile/internal/ir"
24 "cmd/compile/internal/typecheck"
25 "cmd/compile/internal/types"
26 "fmt"
27 "go/constant"
28 )
29
30
31
32
33
34 func transformAdd(n *ir.BinaryExpr) ir.Node {
35 assert(n.Type() != nil && n.Typecheck() == 1)
36 l := n.X
37 if l.Type().IsString() {
38 var add *ir.AddStringExpr
39 if l.Op() == ir.OADDSTR {
40 add = l.(*ir.AddStringExpr)
41 add.SetPos(n.Pos())
42 } else {
43 add = ir.NewAddStringExpr(n.Pos(), []ir.Node{l})
44 }
45 r := n.Y
46 if r.Op() == ir.OADDSTR {
47 r := r.(*ir.AddStringExpr)
48 add.List.Append(r.List.Take()...)
49 } else {
50 add.List.Append(r)
51 }
52 typed(l.Type(), add)
53 return add
54 }
55 return n
56 }
57
58
59 func stringtoruneslit(n *ir.ConvExpr) ir.Node {
60 if n.X.Op() != ir.OLITERAL || n.X.Val().Kind() != constant.String {
61 base.Fatalf("stringtoarraylit %v", n)
62 }
63
64 var list []ir.Node
65 i := 0
66 eltType := n.Type().Elem()
67 for _, r := range ir.StringVal(n.X) {
68 elt := ir.NewKeyExpr(base.Pos, ir.NewInt(int64(i)), ir.NewInt(int64(r)))
69
70
71
72 elt.Value.SetType(eltType)
73 list = append(list, elt)
74 i++
75 }
76
77 nn := ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, ir.TypeNode(n.Type()), nil)
78 nn.List = list
79 typed(n.Type(), nn)
80
81 return transformCompLit(nn)
82 }
83
84
85
86 func transformConv(n *ir.ConvExpr) ir.Node {
87 t := n.X.Type()
88 op, _ := typecheck.Convertop(n.X.Op() == ir.OLITERAL, t, n.Type())
89 n.SetOp(op)
90 switch n.Op() {
91 case ir.OCONVNOP:
92 if t.Kind() == n.Type().Kind() {
93 switch t.Kind() {
94 case types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128:
95
96
97 n.SetOp(ir.OCONV)
98 }
99 }
100
101
102
103 case ir.OSTR2BYTES:
104
105
106 case ir.OSTR2RUNES:
107 if n.X.Op() == ir.OLITERAL {
108 return stringtoruneslit(n)
109 }
110 }
111 return n
112 }
113
114
115
116 func transformConvCall(n *ir.CallExpr) ir.Node {
117 assert(n.Type() != nil && n.Typecheck() == 1)
118 arg := n.Args[0]
119 n1 := ir.NewConvExpr(n.Pos(), ir.OCONV, nil, arg)
120 typed(n.X.Type(), n1)
121 return transformConv(n1)
122 }
123
124
125
126 func transformCall(n *ir.CallExpr) {
127
128 assert(n.Typecheck() == 1)
129 transformArgs(n)
130 l := n.X
131 t := l.Type()
132
133 switch l.Op() {
134 case ir.ODOTINTER:
135 n.SetOp(ir.OCALLINTER)
136
137 case ir.ODOTMETH:
138 l := l.(*ir.SelectorExpr)
139 n.SetOp(ir.OCALLMETH)
140
141 tp := t.Recv().Type
142
143 if l.X == nil || !types.Identical(l.X.Type(), tp) {
144 base.Fatalf("method receiver")
145 }
146
147 default:
148 n.SetOp(ir.OCALLFUNC)
149 }
150
151 typecheckaste(ir.OCALL, n.X, n.IsDDD, t.Params(), n.Args)
152 if t.NumResults() == 1 {
153 n.SetType(l.Type().Results().Field(0).Type)
154
155 if n.Op() == ir.OCALLFUNC && n.X.Op() == ir.ONAME {
156 if sym := n.X.(*ir.Name).Sym(); types.IsRuntimePkg(sym.Pkg) && sym.Name == "getg" {
157
158
159
160
161
162
163 n.SetOp(ir.OGETG)
164 }
165 }
166 return
167 }
168 }
169
170
171
172
173 func transformCompare(n *ir.BinaryExpr) {
174 assert(n.Type() != nil && n.Typecheck() == 1)
175 if (n.Op() == ir.OEQ || n.Op() == ir.ONE) && !types.Identical(n.X.Type(), n.Y.Type()) {
176
177
178
179
180
181 l, r := n.X, n.Y
182 lt, rt := l.Type(), r.Type()
183 converted := false
184 if rt.Kind() != types.TBLANK {
185 aop, _ := typecheck.Assignop(lt, rt)
186 if aop != ir.OXXX {
187 types.CalcSize(lt)
188 if rt.IsInterface() == lt.IsInterface() || lt.Width >= 1<<16 {
189 l = ir.NewConvExpr(base.Pos, aop, rt, l)
190 l.SetTypecheck(1)
191 }
192
193 converted = true
194 }
195 }
196
197 if !converted && lt.Kind() != types.TBLANK {
198 aop, _ := typecheck.Assignop(rt, lt)
199 if aop != ir.OXXX {
200 types.CalcSize(rt)
201 if rt.IsInterface() == lt.IsInterface() || rt.Width >= 1<<16 {
202 r = ir.NewConvExpr(base.Pos, aop, lt, r)
203 r.SetTypecheck(1)
204 }
205 }
206 }
207 n.X, n.Y = l, r
208 }
209 }
210
211
212 func implicitstar(n ir.Node) ir.Node {
213
214 t := n.Type()
215 if !t.IsPtr() {
216 return n
217 }
218 t = t.Elem()
219 if !t.IsArray() {
220 return n
221 }
222 star := ir.NewStarExpr(base.Pos, n)
223 star.SetImplicit(true)
224 return typed(t, star)
225 }
226
227
228 func transformIndex(n *ir.IndexExpr) {
229 assert(n.Type() != nil && n.Typecheck() == 1)
230 n.X = implicitstar(n.X)
231 l := n.X
232 t := l.Type()
233 if t.Kind() == types.TMAP {
234 n.Index = assignconvfn(n.Index, t.Key())
235 n.SetOp(ir.OINDEXMAP)
236
237
238
239 n.SetType(t.Elem())
240 n.Assigned = false
241 }
242 }
243
244
245 func transformSlice(n *ir.SliceExpr) {
246 assert(n.Type() != nil && n.Typecheck() == 1)
247 l := n.X
248 if l.Type().IsArray() {
249 addr := typecheck.NodAddr(n.X)
250 addr.SetImplicit(true)
251 typed(types.NewPtr(n.X.Type()), addr)
252 n.X = addr
253 l = addr
254 }
255 t := l.Type()
256 if t.IsString() {
257 n.SetOp(ir.OSLICESTR)
258 } else if t.IsPtr() && t.Elem().IsArray() {
259 if n.Op().IsSlice3() {
260 n.SetOp(ir.OSLICE3ARR)
261 } else {
262 n.SetOp(ir.OSLICEARR)
263 }
264 }
265 }
266
267
268
269
270 func transformCheckAssign(stmt ir.Node, n ir.Node) {
271 if n.Op() == ir.OINDEXMAP {
272 n := n.(*ir.IndexExpr)
273 n.Assigned = true
274 return
275 }
276 }
277
278
279 func transformAssign(stmt ir.Node, lhs, rhs []ir.Node) {
280 checkLHS := func(i int, typ *types.Type) {
281 transformCheckAssign(stmt, lhs[i])
282 }
283
284 cr := len(rhs)
285 if len(rhs) == 1 {
286 if rtyp := rhs[0].Type(); rtyp != nil && rtyp.IsFuncArgStruct() {
287 cr = rtyp.NumFields()
288 }
289 }
290
291
292 assignOK:
293 for len(lhs) == 2 && cr == 1 {
294 stmt := stmt.(*ir.AssignListStmt)
295 r := rhs[0]
296
297 switch r.Op() {
298 case ir.OINDEXMAP:
299 stmt.SetOp(ir.OAS2MAPR)
300 case ir.ORECV:
301 stmt.SetOp(ir.OAS2RECV)
302 case ir.ODOTTYPE:
303 r := r.(*ir.TypeAssertExpr)
304 stmt.SetOp(ir.OAS2DOTTYPE)
305 r.SetOp(ir.ODOTTYPE2)
306 default:
307 break assignOK
308 }
309 checkLHS(0, r.Type())
310 checkLHS(1, types.UntypedBool)
311 return
312 }
313
314 if len(lhs) != cr {
315 for i := range lhs {
316 checkLHS(i, nil)
317 }
318 return
319 }
320
321
322 if cr > len(rhs) {
323 stmt := stmt.(*ir.AssignListStmt)
324 stmt.SetOp(ir.OAS2FUNC)
325 r := rhs[0].(*ir.CallExpr)
326 r.Use = ir.CallUseList
327 rtyp := r.Type()
328
329 for i := range lhs {
330 checkLHS(i, rtyp.Field(i).Type)
331 }
332 return
333 }
334
335 for i, r := range rhs {
336 checkLHS(i, r.Type())
337 if lhs[i].Type() != nil {
338 rhs[i] = assignconvfn(r, lhs[i].Type())
339 }
340 }
341 }
342
343
344 func transformArgs(n ir.InitNode) {
345 var list []ir.Node
346 switch n := n.(type) {
347 default:
348 base.Fatalf("typecheckargs %+v", n.Op())
349 case *ir.CallExpr:
350 list = n.Args
351 if n.IsDDD {
352 return
353 }
354 case *ir.ReturnStmt:
355 list = n.Results
356 }
357 if len(list) != 1 {
358 return
359 }
360
361 t := list[0].Type()
362 if t == nil || !t.IsFuncArgStruct() {
363 return
364 }
365
366
367
368
369 if ir.Orig(n) == n {
370 n.(ir.OrigNode).SetOrig(ir.SepCopy(n))
371 }
372
373 as := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, nil)
374 as.Rhs.Append(list...)
375
376
377
378
379
380
381 static := ir.CurFunc == nil
382 if static {
383 ir.CurFunc = typecheck.InitTodoFunc
384 }
385 list = nil
386 for _, f := range t.FieldSlice() {
387 t := typecheck.Temp(f.Type)
388 as.PtrInit().Append(ir.NewDecl(base.Pos, ir.ODCL, t))
389 as.Lhs.Append(t)
390 list = append(list, t)
391 }
392 if static {
393 ir.CurFunc = nil
394 }
395
396 switch n := n.(type) {
397 case *ir.CallExpr:
398 n.Args = list
399 case *ir.ReturnStmt:
400 n.Results = list
401 }
402
403 transformAssign(as, as.Lhs, as.Rhs)
404 as.SetTypecheck(1)
405 n.PtrInit().Append(as)
406 }
407
408
409
410 func assignconvfn(n ir.Node, t *types.Type) ir.Node {
411 if t.Kind() == types.TBLANK {
412 return n
413 }
414
415 if types.Identical(n.Type(), t) {
416 return n
417 }
418
419 op, _ := typecheck.Assignop(n.Type(), t)
420
421 r := ir.NewConvExpr(base.Pos, op, t, n)
422 r.SetTypecheck(1)
423 r.SetImplicit(true)
424 return r
425 }
426
427
428 func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl ir.Nodes) {
429 var t *types.Type
430 var i int
431
432 lno := base.Pos
433 defer func() { base.Pos = lno }()
434
435 var n ir.Node
436 if len(nl) == 1 {
437 n = nl[0]
438 }
439
440 i = 0
441 for _, tl := range tstruct.Fields().Slice() {
442 t = tl.Type
443 if tl.IsDDD() {
444 if isddd {
445 n = nl[i]
446 ir.SetPos(n)
447 if n.Type() != nil {
448 nl[i] = assignconvfn(n, t)
449 }
450 return
451 }
452
453
454 for ; i < len(nl); i++ {
455 n = nl[i]
456 ir.SetPos(n)
457 if n.Type() != nil {
458 nl[i] = assignconvfn(n, t.Elem())
459 }
460 }
461 return
462 }
463
464 n = nl[i]
465 ir.SetPos(n)
466 if n.Type() != nil {
467 nl[i] = assignconvfn(n, t)
468 }
469 i++
470 }
471 }
472
473
474
475 func transformSend(n *ir.SendStmt) {
476 n.Value = assignconvfn(n.Value, n.Chan.Type().Elem())
477 }
478
479
480
481 func transformReturn(rs *ir.ReturnStmt) {
482 transformArgs(rs)
483 nl := rs.Results
484 if ir.HasNamedResults(ir.CurFunc) && len(nl) == 0 {
485 return
486 }
487
488 typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), nl)
489 }
490
491
492
493 func transformSelect(sel *ir.SelectStmt) {
494 for _, ncase := range sel.Cases {
495 if ncase.Comm != nil {
496 n := ncase.Comm
497 oselrecv2 := func(dst, recv ir.Node, def bool) {
498 n := ir.NewAssignListStmt(n.Pos(), ir.OSELRECV2, []ir.Node{dst, ir.BlankNode}, []ir.Node{recv})
499 n.Def = def
500 n.SetTypecheck(1)
501 ncase.Comm = n
502 }
503 switch n.Op() {
504 case ir.OAS:
505
506
507
508 n := n.(*ir.AssignStmt)
509 if r := n.Y; r.Op() == ir.OCONVNOP || r.Op() == ir.OCONVIFACE {
510 r := r.(*ir.ConvExpr)
511 if r.Implicit() {
512 n.Y = r.X
513 }
514 }
515 oselrecv2(n.X, n.Y, n.Def)
516
517 case ir.OAS2RECV:
518 n := n.(*ir.AssignListStmt)
519 n.SetOp(ir.OSELRECV2)
520
521 case ir.ORECV:
522
523 n := n.(*ir.UnaryExpr)
524 oselrecv2(ir.BlankNode, n, false)
525
526 case ir.OSEND:
527 break
528 }
529 }
530 }
531 }
532
533
534
535 func transformAsOp(n *ir.AssignOpStmt) {
536 transformCheckAssign(n, n.X)
537 }
538
539
540
541
542 func transformDot(n *ir.SelectorExpr, isCall bool) ir.Node {
543 assert(n.Type() != nil && n.Typecheck() == 1)
544 if n.Op() == ir.OXDOT {
545 n = typecheck.AddImplicitDots(n)
546 n.SetOp(ir.ODOT)
547 }
548
549 t := n.X.Type()
550
551 if n.X.Op() == ir.OTYPE {
552 return transformMethodExpr(n)
553 }
554
555 if t.IsPtr() && !t.Elem().IsInterface() {
556 t = t.Elem()
557 n.SetOp(ir.ODOTPTR)
558 }
559
560 f := typecheck.Lookdot(n, t, 0)
561 assert(f != nil)
562
563 if (n.Op() == ir.ODOTINTER || n.Op() == ir.ODOTMETH) && !isCall {
564 n.SetOp(ir.OCALLPART)
565 n.SetType(typecheck.MethodValueWrapper(n).Type())
566 }
567 return n
568 }
569
570
571 func transformMethodExpr(n *ir.SelectorExpr) (res ir.Node) {
572 t := n.X.Type()
573
574
575 var ms *types.Fields
576 if t.IsInterface() {
577 ms = t.AllMethods()
578 } else {
579 mt := types.ReceiverBaseType(t)
580 typecheck.CalcMethods(mt)
581 ms = mt.AllMethods()
582
583
584
585
586
587
588
589
590 if mt.Sym() == nil {
591 typecheck.NeedRuntimeType(t)
592 }
593 }
594
595 s := n.Sel
596 m := typecheck.Lookdot1(n, s, t, ms, 0)
597 assert(m != nil)
598
599 n.SetOp(ir.OMETHEXPR)
600 n.Selection = m
601 n.SetType(typecheck.NewMethodType(m.Type, n.X.Type()))
602 return n
603 }
604
605
606 func transformAppend(n *ir.CallExpr) ir.Node {
607 transformArgs(n)
608 args := n.Args
609 t := args[0].Type()
610 assert(t.IsSlice())
611
612 if n.IsDDD {
613 if t.Elem().IsKind(types.TUINT8) && args[1].Type().IsString() {
614 return n
615 }
616
617 args[1] = assignconvfn(args[1], t.Underlying())
618 return n
619 }
620
621 as := args[1:]
622 for i, n := range as {
623 assert(n.Type() != nil)
624 as[i] = assignconvfn(n, t.Elem())
625 }
626 return n
627 }
628
629
630 func transformComplex(n *ir.BinaryExpr) ir.Node {
631 l := n.X
632 r := n.Y
633
634 assert(types.Identical(l.Type(), r.Type()))
635
636 var t *types.Type
637 switch l.Type().Kind() {
638 case types.TFLOAT32:
639 t = types.Types[types.TCOMPLEX64]
640 case types.TFLOAT64:
641 t = types.Types[types.TCOMPLEX128]
642 default:
643 panic(fmt.Sprintf("transformComplex: unexpected type %v", l.Type()))
644 }
645
646
647
648 typed(t, n)
649 return n
650 }
651
652
653 func transformDelete(n *ir.CallExpr) ir.Node {
654 transformArgs(n)
655 args := n.Args
656 assert(len(args) == 2)
657
658 l := args[0]
659 r := args[1]
660
661 args[1] = assignconvfn(r, l.Type().Key())
662 return n
663 }
664
665
666 func transformMake(n *ir.CallExpr) ir.Node {
667 args := n.Args
668
669 n.Args = nil
670 l := args[0]
671 t := l.Type()
672 assert(t != nil)
673
674 i := 1
675 var nn ir.Node
676 switch t.Kind() {
677 case types.TSLICE:
678 l = args[i]
679 i++
680 var r ir.Node
681 if i < len(args) {
682 r = args[i]
683 i++
684 }
685 nn = ir.NewMakeExpr(n.Pos(), ir.OMAKESLICE, l, r)
686
687 case types.TMAP:
688 if i < len(args) {
689 l = args[i]
690 i++
691 } else {
692 l = ir.NewInt(0)
693 }
694 nn = ir.NewMakeExpr(n.Pos(), ir.OMAKEMAP, l, nil)
695 nn.SetEsc(n.Esc())
696
697 case types.TCHAN:
698 l = nil
699 if i < len(args) {
700 l = args[i]
701 i++
702 } else {
703 l = ir.NewInt(0)
704 }
705 nn = ir.NewMakeExpr(n.Pos(), ir.OMAKECHAN, l, nil)
706 default:
707 panic(fmt.Sprintf("transformMake: unexpected type %v", t))
708 }
709
710 assert(i == len(args))
711 typed(n.Type(), nn)
712 return nn
713 }
714
715
716 func transformPanic(n *ir.UnaryExpr) ir.Node {
717 n.X = assignconvfn(n.X, types.Types[types.TINTER])
718 return n
719 }
720
721
722 func transformPrint(n *ir.CallExpr) ir.Node {
723 transformArgs(n)
724 return n
725 }
726
727
728 func transformRealImag(n *ir.UnaryExpr) ir.Node {
729 l := n.X
730 var t *types.Type
731
732
733 switch l.Type().Kind() {
734 case types.TCOMPLEX64:
735 t = types.Types[types.TFLOAT32]
736 case types.TCOMPLEX128:
737 t = types.Types[types.TFLOAT64]
738 default:
739 panic(fmt.Sprintf("transformRealImag: unexpected type %v", l.Type()))
740 }
741
742
743
744 typed(t, n)
745 return n
746 }
747
748
749 func transformLenCap(n *ir.UnaryExpr) ir.Node {
750 n.X = implicitstar(n.X)
751 return n
752 }
753
754
755 func transformBuiltin(n *ir.CallExpr) ir.Node {
756
757 assert(n.Typecheck() == 1)
758 fun := n.X.(*ir.Name)
759 op := fun.BuiltinOp
760
761 switch op {
762 case ir.OAPPEND, ir.ODELETE, ir.OMAKE, ir.OPRINT, ir.OPRINTN, ir.ORECOVER:
763 n.SetOp(op)
764 n.X = nil
765 switch op {
766 case ir.OAPPEND:
767 return transformAppend(n)
768 case ir.ODELETE:
769 return transformDelete(n)
770 case ir.OMAKE:
771 return transformMake(n)
772 case ir.OPRINT, ir.OPRINTN:
773 return transformPrint(n)
774 case ir.ORECOVER:
775
776 return n
777 }
778
779 case ir.OCAP, ir.OCLOSE, ir.OIMAG, ir.OLEN, ir.OPANIC, ir.OREAL:
780 transformArgs(n)
781 fallthrough
782
783 case ir.ONEW, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF:
784 u := ir.NewUnaryExpr(n.Pos(), op, n.Args[0])
785 u1 := typed(n.Type(), ir.InitExpr(n.Init(), u))
786 switch op {
787 case ir.OCAP, ir.OLEN:
788 return transformLenCap(u1.(*ir.UnaryExpr))
789 case ir.OREAL, ir.OIMAG:
790 return transformRealImag(u1.(*ir.UnaryExpr))
791 case ir.OPANIC:
792 return transformPanic(u1.(*ir.UnaryExpr))
793 case ir.OCLOSE, ir.ONEW, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF:
794
795 return u1
796 }
797
798 case ir.OCOMPLEX, ir.OCOPY, ir.OUNSAFEADD, ir.OUNSAFESLICE:
799 transformArgs(n)
800 b := ir.NewBinaryExpr(n.Pos(), op, n.Args[0], n.Args[1])
801 n1 := typed(n.Type(), ir.InitExpr(n.Init(), b))
802 if op != ir.OCOMPLEX {
803
804 return n1
805 }
806 return transformComplex(n1.(*ir.BinaryExpr))
807
808 default:
809 panic(fmt.Sprintf("transformBuiltin: unexpected op %v", op))
810 }
811
812 return n
813 }
814
815 func hasKeys(l ir.Nodes) bool {
816 for _, n := range l {
817 if n.Op() == ir.OKEY || n.Op() == ir.OSTRUCTKEY {
818 return true
819 }
820 }
821 return false
822 }
823
824
825
826
827 func transformArrayLit(elemType *types.Type, bound int64, elts []ir.Node) int64 {
828 var key, length int64
829 for i, elt := range elts {
830 ir.SetPos(elt)
831 r := elts[i]
832 var kv *ir.KeyExpr
833 if elt.Op() == ir.OKEY {
834 elt := elt.(*ir.KeyExpr)
835 key = typecheck.IndexConst(elt.Key)
836 assert(key >= 0)
837 kv = elt
838 r = elt.Value
839 }
840
841 r = assignconvfn(r, elemType)
842 if kv != nil {
843 kv.Value = r
844 } else {
845 elts[i] = r
846 }
847
848 key++
849 if key > length {
850 length = key
851 }
852 }
853
854 return length
855 }
856
857
858
859
860 func transformCompLit(n *ir.CompLitExpr) (res ir.Node) {
861 assert(n.Type() != nil && n.Typecheck() == 1)
862 lno := base.Pos
863 defer func() {
864 base.Pos = lno
865 }()
866
867
868 n.SetOrig(ir.Copy(n))
869
870 ir.SetPos(n)
871
872 t := n.Type()
873
874 switch t.Kind() {
875 default:
876 base.Fatalf("transformCompLit %v", t.Kind())
877
878 case types.TARRAY:
879 transformArrayLit(t.Elem(), t.NumElem(), n.List)
880 n.SetOp(ir.OARRAYLIT)
881
882 case types.TSLICE:
883 length := transformArrayLit(t.Elem(), -1, n.List)
884 n.SetOp(ir.OSLICELIT)
885 n.Len = length
886
887 case types.TMAP:
888 for _, l := range n.List {
889 ir.SetPos(l)
890 assert(l.Op() == ir.OKEY)
891 l := l.(*ir.KeyExpr)
892
893 r := l.Key
894 l.Key = assignconvfn(r, t.Key())
895
896 r = l.Value
897 l.Value = assignconvfn(r, t.Elem())
898 }
899
900 n.SetOp(ir.OMAPLIT)
901
902 case types.TSTRUCT:
903
904 types.CalcSize(t)
905
906 if len(n.List) != 0 && !hasKeys(n.List) {
907
908 ls := n.List
909 for i, n1 := range ls {
910 ir.SetPos(n1)
911
912 f := t.Field(i)
913 n1 = assignconvfn(n1, f.Type)
914 sk := ir.NewStructKeyExpr(base.Pos, f.Sym, n1)
915 sk.Offset = f.Offset
916 ls[i] = sk
917 }
918 assert(len(ls) >= t.NumFields())
919 } else {
920
921 ls := n.List
922 for i, l := range ls {
923 ir.SetPos(l)
924
925 if l.Op() == ir.OKEY {
926 kv := l.(*ir.KeyExpr)
927 key := kv.Key
928
929
930
931
932 s := key.Sym()
933 if id, ok := key.(*ir.Ident); ok && typecheck.DotImportRefs[id] != nil {
934 s = typecheck.Lookup(s.Name)
935 }
936
937
938
939
940
941 assert(!(s == nil || s.Pkg != types.LocalPkg || key.Op() == ir.OXDOT || s.IsBlank()))
942
943 l = ir.NewStructKeyExpr(l.Pos(), s, kv.Value)
944 ls[i] = l
945 }
946
947 assert(l.Op() == ir.OSTRUCTKEY)
948 l := l.(*ir.StructKeyExpr)
949
950 f := typecheck.Lookdot1(nil, l.Field, t, t.Fields(), 0)
951 l.Offset = f.Offset
952
953 l.Value = assignconvfn(l.Value, f.Type)
954 }
955 }
956
957 n.SetOp(ir.OSTRUCTLIT)
958 }
959
960 return n
961 }
962
View as plain text