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