1
2
3
4
5 package typecheck
6
7 import (
8 "cmd/compile/internal/base"
9 "cmd/compile/internal/ir"
10 "cmd/compile/internal/types"
11 "cmd/internal/src"
12
13 "fmt"
14 "go/constant"
15 "go/token"
16 )
17
18
19 func MakeDotArgs(pos src.XPos, typ *types.Type, args []ir.Node) ir.Node {
20 if len(args) == 0 {
21 return ir.NewNilExpr(pos, typ)
22 }
23
24 args = append([]ir.Node(nil), args...)
25 lit := ir.NewCompLitExpr(pos, ir.OCOMPLIT, typ, args)
26 lit.SetImplicit(true)
27
28 n := Expr(lit)
29 if n.Type() == nil {
30 base.FatalfAt(pos, "mkdotargslice: typecheck failed")
31 }
32 return n
33 }
34
35
36
37 func FixVariadicCall(call *ir.CallExpr) {
38 fntype := call.Fun.Type()
39 if !fntype.IsVariadic() || call.IsDDD {
40 return
41 }
42
43 vi := fntype.NumParams() - 1
44 vt := fntype.Param(vi).Type
45
46 args := call.Args
47 extra := args[vi:]
48 slice := MakeDotArgs(call.Pos(), vt, extra)
49 for i := range extra {
50 extra[i] = nil
51 }
52
53 call.Args = append(args[:vi], slice)
54 call.IsDDD = true
55 }
56
57
58 func FixMethodCall(call *ir.CallExpr) {
59 if call.Fun.Op() != ir.ODOTMETH {
60 return
61 }
62
63 dot := call.Fun.(*ir.SelectorExpr)
64
65 fn := NewMethodExpr(dot.Pos(), dot.X.Type(), dot.Selection.Sym)
66
67 args := make([]ir.Node, 1+len(call.Args))
68 args[0] = dot.X
69 copy(args[1:], call.Args)
70
71 call.SetOp(ir.OCALLFUNC)
72 call.Fun = fn
73 call.Args = args
74 }
75
76 func AssertFixedCall(call *ir.CallExpr) {
77 if call.Fun.Type().IsVariadic() && !call.IsDDD {
78 base.FatalfAt(call.Pos(), "missed FixVariadicCall")
79 }
80 if call.Op() == ir.OCALLMETH {
81 base.FatalfAt(call.Pos(), "missed FixMethodCall")
82 }
83 }
84
85
86
87
88 func ClosureType(clo *ir.ClosureExpr) *types.Type {
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 fields := make([]*types.Field, 1+len(clo.Func.ClosureVars))
105 fields[0] = types.NewField(base.AutogeneratedPos, types.LocalPkg.Lookup("F"), types.Types[types.TUINTPTR])
106 it := NewClosureStructIter(clo.Func.ClosureVars)
107 i := 0
108 for {
109 n, typ, _ := it.Next()
110 if n == nil {
111 break
112 }
113 fields[1+i] = types.NewField(base.AutogeneratedPos, types.LocalPkg.LookupNum("X", i), typ)
114 i++
115 }
116 typ := types.NewStruct(fields)
117 typ.SetNoalg(true)
118 return typ
119 }
120
121
122
123
124 func MethodValueType(n *ir.SelectorExpr) *types.Type {
125 t := types.NewStruct([]*types.Field{
126 types.NewField(base.Pos, Lookup("F"), types.Types[types.TUINTPTR]),
127 types.NewField(base.Pos, Lookup("R"), n.X.Type()),
128 })
129 t.SetNoalg(true)
130 return t
131 }
132
133
134
135
136 func tcFunc(n *ir.Func) {
137 if base.EnableTrace && base.Flag.LowerT {
138 defer tracePrint("tcFunc", n)(nil)
139 }
140
141 if name := n.Nname; name.Typecheck() == 0 {
142 base.AssertfAt(name.Type() != nil, n.Pos(), "missing type: %v", name)
143 name.SetTypecheck(1)
144 }
145 }
146
147
148 func tcCall(n *ir.CallExpr, top int) ir.Node {
149 Stmts(n.Init())
150 n.Fun = typecheck(n.Fun, ctxExpr|ctxType|ctxCallee)
151
152 l := n.Fun
153
154 if l.Op() == ir.ONAME && l.(*ir.Name).BuiltinOp != 0 {
155 l := l.(*ir.Name)
156 if n.IsDDD && l.BuiltinOp != ir.OAPPEND {
157 base.Errorf("invalid use of ... with builtin %v", l)
158 }
159
160
161 switch l.BuiltinOp {
162 default:
163 base.Fatalf("unknown builtin %v", l)
164
165 case ir.OAPPEND, ir.ODELETE, ir.OMAKE, ir.OMAX, ir.OMIN, ir.OPRINT, ir.OPRINTLN, ir.ORECOVER:
166 n.SetOp(l.BuiltinOp)
167 n.Fun = nil
168 n.SetTypecheck(0)
169 return typecheck(n, top)
170
171 case ir.OCAP, ir.OCLEAR, ir.OCLOSE, ir.OIMAG, ir.OLEN, ir.OPANIC, ir.OREAL, ir.OUNSAFESTRINGDATA, ir.OUNSAFESLICEDATA:
172 typecheckargs(n)
173 fallthrough
174 case ir.ONEW:
175 arg, ok := needOneArg(n, "%v", n.Op())
176 if !ok {
177 n.SetType(nil)
178 return n
179 }
180 u := ir.NewUnaryExpr(n.Pos(), l.BuiltinOp, arg)
181 return typecheck(ir.InitExpr(n.Init(), u), top)
182
183 case ir.OCOMPLEX, ir.OCOPY, ir.OUNSAFEADD, ir.OUNSAFESLICE, ir.OUNSAFESTRING:
184 typecheckargs(n)
185 arg1, arg2, ok := needTwoArgs(n)
186 if !ok {
187 n.SetType(nil)
188 return n
189 }
190 b := ir.NewBinaryExpr(n.Pos(), l.BuiltinOp, arg1, arg2)
191 return typecheck(ir.InitExpr(n.Init(), b), top)
192 }
193 panic("unreachable")
194 }
195
196 n.Fun = DefaultLit(n.Fun, nil)
197 l = n.Fun
198 if l.Op() == ir.OTYPE {
199 if n.IsDDD {
200 base.Fatalf("invalid use of ... in type conversion to %v", l.Type())
201 }
202
203
204 arg, ok := needOneArg(n, "conversion to %v", l.Type())
205 if !ok {
206 n.SetType(nil)
207 return n
208 }
209
210 n := ir.NewConvExpr(n.Pos(), ir.OCONV, nil, arg)
211 n.SetType(l.Type())
212 return tcConv(n)
213 }
214
215 RewriteNonNameCall(n)
216 typecheckargs(n)
217 t := l.Type()
218 if t == nil {
219 n.SetType(nil)
220 return n
221 }
222 types.CheckSize(t)
223
224 switch l.Op() {
225 case ir.ODOTINTER:
226 n.SetOp(ir.OCALLINTER)
227
228 case ir.ODOTMETH:
229 l := l.(*ir.SelectorExpr)
230 n.SetOp(ir.OCALLMETH)
231
232
233
234
235
236 tp := t.Recv().Type
237
238 if l.X == nil || !types.Identical(l.X.Type(), tp) {
239 base.Fatalf("method receiver")
240 }
241
242 default:
243 n.SetOp(ir.OCALLFUNC)
244 if t.Kind() != types.TFUNC {
245 if o := l; o.Name() != nil && types.BuiltinPkg.Lookup(o.Sym().Name).Def != nil {
246
247
248 base.Errorf("cannot call non-function %L, declared at %s",
249 l, base.FmtPos(o.Name().Pos()))
250 } else {
251 base.Errorf("cannot call non-function %L", l)
252 }
253 n.SetType(nil)
254 return n
255 }
256 }
257
258 typecheckaste(ir.OCALL, n.Fun, n.IsDDD, t.Params(), n.Args, func() string { return fmt.Sprintf("argument to %v", n.Fun) })
259 FixVariadicCall(n)
260 FixMethodCall(n)
261 if t.NumResults() == 0 {
262 return n
263 }
264 if t.NumResults() == 1 {
265 n.SetType(l.Type().Result(0).Type)
266
267 if n.Op() == ir.OCALLFUNC && n.Fun.Op() == ir.ONAME {
268 if sym := n.Fun.(*ir.Name).Sym(); types.RuntimeSymName(sym) == "getg" {
269
270
271
272
273
274
275 n.SetOp(ir.OGETG)
276 }
277 }
278 return n
279 }
280
281
282 if top&(ctxMultiOK|ctxStmt) == 0 {
283 base.Errorf("multiple-value %v() in single-value context", l)
284 return n
285 }
286
287 n.SetType(l.Type().ResultsTuple())
288 return n
289 }
290
291
292 func tcAppend(n *ir.CallExpr) ir.Node {
293 typecheckargs(n)
294 args := n.Args
295 if len(args) == 0 {
296 base.Errorf("missing arguments to append")
297 n.SetType(nil)
298 return n
299 }
300
301 t := args[0].Type()
302 if t == nil {
303 n.SetType(nil)
304 return n
305 }
306
307 n.SetType(t)
308 if !t.IsSlice() {
309 if ir.IsNil(args[0]) {
310 base.Errorf("first argument to append must be typed slice; have untyped nil")
311 n.SetType(nil)
312 return n
313 }
314
315 base.Errorf("first argument to append must be slice; have %L", t)
316 n.SetType(nil)
317 return n
318 }
319
320 if n.IsDDD {
321 if len(args) == 1 {
322 base.Errorf("cannot use ... on first argument to append")
323 n.SetType(nil)
324 return n
325 }
326
327 if len(args) != 2 {
328 base.Errorf("too many arguments to append")
329 n.SetType(nil)
330 return n
331 }
332
333
334
335
336
337
338 return n
339 }
340
341 as := args[1:]
342 for i, n := range as {
343 if n.Type() == nil {
344 continue
345 }
346 as[i] = AssignConv(n, t.Elem(), "append")
347 types.CheckSize(as[i].Type())
348 }
349 return n
350 }
351
352
353 func tcClear(n *ir.UnaryExpr) ir.Node {
354 n.X = Expr(n.X)
355 n.X = DefaultLit(n.X, nil)
356 l := n.X
357 t := l.Type()
358 if t == nil {
359 n.SetType(nil)
360 return n
361 }
362
363 switch {
364 case t.IsMap(), t.IsSlice():
365 default:
366 base.Errorf("invalid operation: %v (argument must be a map or slice)", n)
367 n.SetType(nil)
368 return n
369 }
370
371 return n
372 }
373
374
375 func tcClose(n *ir.UnaryExpr) ir.Node {
376 n.X = Expr(n.X)
377 n.X = DefaultLit(n.X, nil)
378 l := n.X
379 t := l.Type()
380 if t == nil {
381 n.SetType(nil)
382 return n
383 }
384 if !t.IsChan() {
385 base.Errorf("invalid operation: %v (non-chan type %v)", n, t)
386 n.SetType(nil)
387 return n
388 }
389
390 if !t.ChanDir().CanSend() {
391 base.Errorf("invalid operation: %v (cannot close receive-only channel)", n)
392 n.SetType(nil)
393 return n
394 }
395 return n
396 }
397
398
399 func tcComplex(n *ir.BinaryExpr) ir.Node {
400 l := Expr(n.X)
401 r := Expr(n.Y)
402 if l.Type() == nil || r.Type() == nil {
403 n.SetType(nil)
404 return n
405 }
406 l, r = defaultlit2(l, r, false)
407 if l.Type() == nil || r.Type() == nil {
408 n.SetType(nil)
409 return n
410 }
411 n.X = l
412 n.Y = r
413
414 if !types.Identical(l.Type(), r.Type()) {
415 base.Errorf("invalid operation: %v (mismatched types %v and %v)", n, l.Type(), r.Type())
416 n.SetType(nil)
417 return n
418 }
419
420 var t *types.Type
421 switch l.Type().Kind() {
422 default:
423 base.Errorf("invalid operation: %v (arguments have type %v, expected floating-point)", n, l.Type())
424 n.SetType(nil)
425 return n
426
427 case types.TIDEAL:
428 t = types.UntypedComplex
429
430 case types.TFLOAT32:
431 t = types.Types[types.TCOMPLEX64]
432
433 case types.TFLOAT64:
434 t = types.Types[types.TCOMPLEX128]
435 }
436 n.SetType(t)
437 return n
438 }
439
440
441 func tcCopy(n *ir.BinaryExpr) ir.Node {
442 n.SetType(types.Types[types.TINT])
443 n.X = Expr(n.X)
444 n.X = DefaultLit(n.X, nil)
445 n.Y = Expr(n.Y)
446 n.Y = DefaultLit(n.Y, nil)
447 if n.X.Type() == nil || n.Y.Type() == nil {
448 n.SetType(nil)
449 return n
450 }
451
452
453 if n.X.Type().IsSlice() && n.Y.Type().IsString() {
454 if types.Identical(n.X.Type().Elem(), types.ByteType) {
455 return n
456 }
457 base.Errorf("arguments to copy have different element types: %L and string", n.X.Type())
458 n.SetType(nil)
459 return n
460 }
461
462 if !n.X.Type().IsSlice() || !n.Y.Type().IsSlice() {
463 if !n.X.Type().IsSlice() && !n.Y.Type().IsSlice() {
464 base.Errorf("arguments to copy must be slices; have %L, %L", n.X.Type(), n.Y.Type())
465 } else if !n.X.Type().IsSlice() {
466 base.Errorf("first argument to copy should be slice; have %L", n.X.Type())
467 } else {
468 base.Errorf("second argument to copy should be slice or string; have %L", n.Y.Type())
469 }
470 n.SetType(nil)
471 return n
472 }
473
474 if !types.Identical(n.X.Type().Elem(), n.Y.Type().Elem()) {
475 base.Errorf("arguments to copy have different element types: %L and %L", n.X.Type(), n.Y.Type())
476 n.SetType(nil)
477 return n
478 }
479 return n
480 }
481
482
483 func tcDelete(n *ir.CallExpr) ir.Node {
484 typecheckargs(n)
485 args := n.Args
486 if len(args) == 0 {
487 base.Errorf("missing arguments to delete")
488 n.SetType(nil)
489 return n
490 }
491
492 if len(args) == 1 {
493 base.Errorf("missing second (key) argument to delete")
494 n.SetType(nil)
495 return n
496 }
497
498 if len(args) != 2 {
499 base.Errorf("too many arguments to delete")
500 n.SetType(nil)
501 return n
502 }
503
504 l := args[0]
505 r := args[1]
506 if l.Type() != nil && !l.Type().IsMap() {
507 base.Errorf("first argument to delete must be map; have %L", l.Type())
508 n.SetType(nil)
509 return n
510 }
511
512 args[1] = AssignConv(r, l.Type().Key(), "delete")
513 return n
514 }
515
516
517 func tcMake(n *ir.CallExpr) ir.Node {
518 args := n.Args
519 if len(args) == 0 {
520 base.Errorf("missing argument to make")
521 n.SetType(nil)
522 return n
523 }
524
525 n.Args = nil
526 l := args[0]
527 l = typecheck(l, ctxType)
528 t := l.Type()
529 if t == nil {
530 n.SetType(nil)
531 return n
532 }
533
534 i := 1
535 var nn ir.Node
536 switch t.Kind() {
537 default:
538 base.Errorf("cannot make type %v", t)
539 n.SetType(nil)
540 return n
541
542 case types.TSLICE:
543 if i >= len(args) {
544 base.Errorf("missing len argument to make(%v)", t)
545 n.SetType(nil)
546 return n
547 }
548
549 l = args[i]
550 i++
551 l = Expr(l)
552 var r ir.Node
553 if i < len(args) {
554 r = args[i]
555 i++
556 r = Expr(r)
557 }
558
559 if l.Type() == nil || (r != nil && r.Type() == nil) {
560 n.SetType(nil)
561 return n
562 }
563 if !checkmake(t, "len", &l) || r != nil && !checkmake(t, "cap", &r) {
564 n.SetType(nil)
565 return n
566 }
567 if ir.IsConst(l, constant.Int) && r != nil && ir.IsConst(r, constant.Int) && constant.Compare(l.Val(), token.GTR, r.Val()) {
568 base.Errorf("len larger than cap in make(%v)", t)
569 n.SetType(nil)
570 return n
571 }
572 nn = ir.NewMakeExpr(n.Pos(), ir.OMAKESLICE, l, r)
573
574 case types.TMAP:
575 if i < len(args) {
576 l = args[i]
577 i++
578 l = Expr(l)
579 l = DefaultLit(l, types.Types[types.TINT])
580 if l.Type() == nil {
581 n.SetType(nil)
582 return n
583 }
584 if !checkmake(t, "size", &l) {
585 n.SetType(nil)
586 return n
587 }
588 } else {
589 l = ir.NewInt(base.Pos, 0)
590 }
591 nn = ir.NewMakeExpr(n.Pos(), ir.OMAKEMAP, l, nil)
592 nn.SetEsc(n.Esc())
593
594 case types.TCHAN:
595 l = nil
596 if i < len(args) {
597 l = args[i]
598 i++
599 l = Expr(l)
600 l = DefaultLit(l, types.Types[types.TINT])
601 if l.Type() == nil {
602 n.SetType(nil)
603 return n
604 }
605 if !checkmake(t, "buffer", &l) {
606 n.SetType(nil)
607 return n
608 }
609 } else {
610 l = ir.NewInt(base.Pos, 0)
611 }
612 nn = ir.NewMakeExpr(n.Pos(), ir.OMAKECHAN, l, nil)
613 }
614
615 if i < len(args) {
616 base.Errorf("too many arguments to make(%v)", t)
617 n.SetType(nil)
618 return n
619 }
620
621 nn.SetType(t)
622 return nn
623 }
624
625
626 func tcMakeSliceCopy(n *ir.MakeExpr) ir.Node {
627
628
629
630
631 t := n.Type()
632
633 if t == nil {
634 base.Fatalf("no type specified for OMAKESLICECOPY")
635 }
636
637 if !t.IsSlice() {
638 base.Fatalf("invalid type %v for OMAKESLICECOPY", n.Type())
639 }
640
641 if n.Len == nil {
642 base.Fatalf("missing len argument for OMAKESLICECOPY")
643 }
644
645 if n.Cap == nil {
646 base.Fatalf("missing slice argument to copy for OMAKESLICECOPY")
647 }
648
649 n.Len = Expr(n.Len)
650 n.Cap = Expr(n.Cap)
651
652 n.Len = DefaultLit(n.Len, types.Types[types.TINT])
653
654 if !n.Len.Type().IsInteger() && n.Type().Kind() != types.TIDEAL {
655 base.Errorf("non-integer len argument in OMAKESLICECOPY")
656 }
657
658 if ir.IsConst(n.Len, constant.Int) {
659 if ir.ConstOverflow(n.Len.Val(), types.Types[types.TINT]) {
660 base.Fatalf("len for OMAKESLICECOPY too large")
661 }
662 if constant.Sign(n.Len.Val()) < 0 {
663 base.Fatalf("len for OMAKESLICECOPY must be non-negative")
664 }
665 }
666 return n
667 }
668
669
670 func tcNew(n *ir.UnaryExpr) ir.Node {
671 if n.X == nil {
672
673
674 base.Fatalf("missing argument to new")
675 }
676 l := n.X
677 l = typecheck(l, ctxType)
678 t := l.Type()
679 if t == nil {
680 n.SetType(nil)
681 return n
682 }
683 n.X = l
684 n.SetType(types.NewPtr(t))
685 return n
686 }
687
688
689 func tcPanic(n *ir.UnaryExpr) ir.Node {
690 n.X = Expr(n.X)
691 n.X = AssignConv(n.X, types.Types[types.TINTER], "argument to panic")
692 if n.X.Type() == nil {
693 n.SetType(nil)
694 return n
695 }
696 return n
697 }
698
699
700 func tcPrint(n *ir.CallExpr) ir.Node {
701 typecheckargs(n)
702 ls := n.Args
703 for i1, n1 := range ls {
704
705 if ir.IsConst(n1, constant.Int) {
706 ls[i1] = DefaultLit(ls[i1], types.Types[types.TINT64])
707 } else {
708 ls[i1] = DefaultLit(ls[i1], nil)
709 }
710 }
711 return n
712 }
713
714
715 func tcMinMax(n *ir.CallExpr) ir.Node {
716 typecheckargs(n)
717 arg0 := n.Args[0]
718 for _, arg := range n.Args[1:] {
719 if !types.Identical(arg.Type(), arg0.Type()) {
720 base.FatalfAt(n.Pos(), "mismatched arguments: %L and %L", arg0, arg)
721 }
722 }
723 n.SetType(arg0.Type())
724 return n
725 }
726
727
728 func tcRealImag(n *ir.UnaryExpr) ir.Node {
729 n.X = Expr(n.X)
730 l := n.X
731 t := l.Type()
732 if t == nil {
733 n.SetType(nil)
734 return n
735 }
736
737
738 switch t.Kind() {
739 case types.TIDEAL:
740 n.SetType(types.UntypedFloat)
741 case types.TCOMPLEX64:
742 n.SetType(types.Types[types.TFLOAT32])
743 case types.TCOMPLEX128:
744 n.SetType(types.Types[types.TFLOAT64])
745 default:
746 base.Errorf("invalid argument %L for %v", l, n.Op())
747 n.SetType(nil)
748 return n
749 }
750 return n
751 }
752
753
754 func tcRecover(n *ir.CallExpr) ir.Node {
755 if len(n.Args) != 0 {
756 base.Errorf("too many arguments to recover")
757 n.SetType(nil)
758 return n
759 }
760
761
762 var fp ir.Node = ir.NewCallExpr(n.Pos(), ir.OGETCALLERSP, nil, nil)
763 if off := base.Ctxt.Arch.FixedFrameSize; off != 0 {
764 fp = ir.NewBinaryExpr(n.Pos(), ir.OADD, fp, ir.NewInt(base.Pos, off))
765 }
766
767 fp = ir.NewConvExpr(n.Pos(), ir.OCONVNOP, types.NewPtr(types.Types[types.TINT32]), fp)
768
769 n.SetOp(ir.ORECOVERFP)
770 n.SetType(types.Types[types.TINTER])
771 n.Args = []ir.Node{Expr(fp)}
772 return n
773 }
774
775
776 func tcUnsafeAdd(n *ir.BinaryExpr) *ir.BinaryExpr {
777 n.X = AssignConv(Expr(n.X), types.Types[types.TUNSAFEPTR], "argument to unsafe.Add")
778 n.Y = DefaultLit(Expr(n.Y), types.Types[types.TINT])
779 if n.X.Type() == nil || n.Y.Type() == nil {
780 n.SetType(nil)
781 return n
782 }
783 if !n.Y.Type().IsInteger() {
784 n.SetType(nil)
785 return n
786 }
787 n.SetType(n.X.Type())
788 return n
789 }
790
791
792 func tcUnsafeSlice(n *ir.BinaryExpr) *ir.BinaryExpr {
793 n.X = Expr(n.X)
794 n.Y = Expr(n.Y)
795 if n.X.Type() == nil || n.Y.Type() == nil {
796 n.SetType(nil)
797 return n
798 }
799 t := n.X.Type()
800 if !t.IsPtr() {
801 base.Errorf("first argument to unsafe.Slice must be pointer; have %L", t)
802 } else if t.Elem().NotInHeap() {
803
804
805
806
807 base.Errorf("unsafe.Slice of incomplete (or unallocatable) type not allowed")
808 }
809
810 if !checkunsafesliceorstring(n.Op(), &n.Y) {
811 n.SetType(nil)
812 return n
813 }
814 n.SetType(types.NewSlice(t.Elem()))
815 return n
816 }
817
818
819 func tcUnsafeString(n *ir.BinaryExpr) *ir.BinaryExpr {
820 n.X = Expr(n.X)
821 n.Y = Expr(n.Y)
822 if n.X.Type() == nil || n.Y.Type() == nil {
823 n.SetType(nil)
824 return n
825 }
826 t := n.X.Type()
827 if !t.IsPtr() || !types.Identical(t.Elem(), types.Types[types.TUINT8]) {
828 base.Errorf("first argument to unsafe.String must be *byte; have %L", t)
829 }
830
831 if !checkunsafesliceorstring(n.Op(), &n.Y) {
832 n.SetType(nil)
833 return n
834 }
835 n.SetType(types.Types[types.TSTRING])
836 return n
837 }
838
839
840
841 type ClosureStructIter struct {
842 closureVars []*ir.Name
843 offset int64
844 next int
845 }
846
847
848 func NewClosureStructIter(closureVars []*ir.Name) *ClosureStructIter {
849 return &ClosureStructIter{
850 closureVars: closureVars,
851 offset: int64(types.PtrSize),
852 next: 0,
853 }
854 }
855
856
857
858 func (iter *ClosureStructIter) Next() (n *ir.Name, typ *types.Type, offset int64) {
859 if iter.next >= len(iter.closureVars) {
860 return nil, nil, 0
861 }
862 n = iter.closureVars[iter.next]
863 typ = n.Type()
864 if !n.Byval() {
865 typ = types.NewPtr(typ)
866 }
867 iter.next++
868 offset = types.RoundUp(iter.offset, typ.Alignment())
869 iter.offset = offset + typ.Size()
870 return n, typ, offset
871 }
872
View as plain text