1
2
3
4
5 package typecheck
6
7 import (
8 "fmt"
9 "go/constant"
10 "go/token"
11 "math"
12 "math/big"
13 "strings"
14 "unicode"
15
16 "cmd/compile/internal/base"
17 "cmd/compile/internal/ir"
18 "cmd/compile/internal/types"
19 "cmd/internal/src"
20 )
21
22 func roundFloat(v constant.Value, sz int64) constant.Value {
23 switch sz {
24 case 4:
25 f, _ := constant.Float32Val(v)
26 return makeFloat64(float64(f))
27 case 8:
28 f, _ := constant.Float64Val(v)
29 return makeFloat64(f)
30 }
31 base.Fatalf("unexpected size: %v", sz)
32 panic("unreachable")
33 }
34
35
36
37 func truncfltlit(v constant.Value, t *types.Type) constant.Value {
38 if t.IsUntyped() || overflow(v, t) {
39
40
41
42 return v
43 }
44
45 return roundFloat(v, t.Size())
46 }
47
48
49
50
51 func trunccmplxlit(v constant.Value, t *types.Type) constant.Value {
52 if t.IsUntyped() || overflow(v, t) {
53
54
55
56 return v
57 }
58
59 fsz := t.Size() / 2
60 return makeComplex(roundFloat(constant.Real(v), fsz), roundFloat(constant.Imag(v), fsz))
61 }
62
63
64 func convlit(n ir.Node, t *types.Type) ir.Node { return convlit1(n, t, false, nil) }
65 func DefaultLit(n ir.Node, t *types.Type) ir.Node { return convlit1(n, t, false, nil) }
66
67
68
69
70
71
72
73
74
75
76
77
78 func convlit1(n ir.Node, t *types.Type, explicit bool, context func() string) ir.Node {
79 if explicit && t == nil {
80 base.Fatalf("explicit conversion missing type")
81 }
82 if t != nil && t.IsUntyped() {
83 base.Fatalf("bad conversion to untyped: %v", t)
84 }
85
86 if n == nil || n.Type() == nil {
87
88 return n
89 }
90 if !n.Type().IsUntyped() {
91
92 return n
93 }
94
95
96 if n.Type().Kind() == types.TNIL {
97 if n.Op() != ir.ONIL {
98 base.Fatalf("unexpected op: %v (%v)", n, n.Op())
99 }
100 n = ir.Copy(n)
101 if t == nil {
102 base.Errorf("use of untyped nil")
103 n.SetDiag(true)
104 n.SetType(nil)
105 return n
106 }
107
108 if !t.HasNil() {
109
110 return n
111 }
112
113 n.SetType(t)
114 return n
115 }
116
117 if t == nil || !ir.OKForConst[t.Kind()] {
118 t = defaultType(n.Type())
119 }
120
121 switch n.Op() {
122 default:
123 base.Fatalf("unexpected untyped expression: %v", n)
124
125 case ir.OLITERAL:
126 v := convertVal(n.Val(), t, explicit)
127 if v.Kind() == constant.Unknown {
128 n = ir.NewConstExpr(n.Val(), n)
129 break
130 }
131 n = ir.NewConstExpr(v, n)
132 n.SetType(t)
133 return n
134
135 case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.OREAL, ir.OIMAG:
136 ot := operandType(n.Op(), t)
137 if ot == nil {
138 n = DefaultLit(n, nil)
139 break
140 }
141
142 n := n.(*ir.UnaryExpr)
143 n.X = convlit(n.X, ot)
144 if n.X.Type() == nil {
145 n.SetType(nil)
146 return n
147 }
148 n.SetType(t)
149 return n
150
151 case ir.OADD, ir.OSUB, ir.OMUL, ir.ODIV, ir.OMOD, ir.OOR, ir.OXOR, ir.OAND, ir.OANDNOT, ir.OOROR, ir.OANDAND, ir.OCOMPLEX:
152 ot := operandType(n.Op(), t)
153 if ot == nil {
154 n = DefaultLit(n, nil)
155 break
156 }
157
158 var l, r ir.Node
159 switch n := n.(type) {
160 case *ir.BinaryExpr:
161 n.X = convlit(n.X, ot)
162 n.Y = convlit(n.Y, ot)
163 l, r = n.X, n.Y
164 case *ir.LogicalExpr:
165 n.X = convlit(n.X, ot)
166 n.Y = convlit(n.Y, ot)
167 l, r = n.X, n.Y
168 }
169
170 if l.Type() == nil || r.Type() == nil {
171 n.SetType(nil)
172 return n
173 }
174 if !types.Identical(l.Type(), r.Type()) {
175 base.Errorf("invalid operation: %v (mismatched types %v and %v)", n, l.Type(), r.Type())
176 n.SetType(nil)
177 return n
178 }
179
180 n.SetType(t)
181 return n
182
183 case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
184 n := n.(*ir.BinaryExpr)
185 if !t.IsBoolean() {
186 break
187 }
188 n.SetType(t)
189 return n
190
191 case ir.OLSH, ir.ORSH:
192 n := n.(*ir.BinaryExpr)
193 n.X = convlit1(n.X, t, explicit, nil)
194 n.SetType(n.X.Type())
195 if n.Type() != nil && !n.Type().IsInteger() {
196 base.Errorf("invalid operation: %v (shift of type %v)", n, n.Type())
197 n.SetType(nil)
198 }
199 return n
200 }
201
202 if !n.Diag() {
203 if !t.Broke() {
204 if explicit {
205 base.Errorf("cannot convert %L to type %v", n, t)
206 } else if context != nil {
207 base.Errorf("cannot use %L as type %v in %s", n, t, context())
208 } else {
209 base.Errorf("cannot use %L as type %v", n, t)
210 }
211 }
212 n.SetDiag(true)
213 }
214 n.SetType(nil)
215 return n
216 }
217
218 func operandType(op ir.Op, t *types.Type) *types.Type {
219 switch op {
220 case ir.OCOMPLEX:
221 if t.IsComplex() {
222 return types.FloatForComplex(t)
223 }
224 case ir.OREAL, ir.OIMAG:
225 if t.IsFloat() {
226 return types.ComplexForFloat(t)
227 }
228 default:
229 if okfor[op][t.Kind()] {
230 return t
231 }
232 }
233 return nil
234 }
235
236
237
238
239
240
241 func convertVal(v constant.Value, t *types.Type, explicit bool) constant.Value {
242 switch ct := v.Kind(); ct {
243 case constant.Bool:
244 if t.IsBoolean() {
245 return v
246 }
247
248 case constant.String:
249 if t.IsString() {
250 return v
251 }
252
253 case constant.Int:
254 if explicit && t.IsString() {
255 return tostr(v)
256 }
257 fallthrough
258 case constant.Float, constant.Complex:
259 switch {
260 case t.IsInteger():
261 v = toint(v)
262 overflow(v, t)
263 return v
264 case t.IsFloat():
265 v = toflt(v)
266 v = truncfltlit(v, t)
267 return v
268 case t.IsComplex():
269 v = tocplx(v)
270 v = trunccmplxlit(v, t)
271 return v
272 }
273 }
274
275 return constant.MakeUnknown()
276 }
277
278 func tocplx(v constant.Value) constant.Value {
279 return constant.ToComplex(v)
280 }
281
282 func toflt(v constant.Value) constant.Value {
283 if v.Kind() == constant.Complex {
284 if constant.Sign(constant.Imag(v)) != 0 {
285 base.Errorf("constant %v truncated to real", v)
286 }
287 v = constant.Real(v)
288 }
289
290 return constant.ToFloat(v)
291 }
292
293 func toint(v constant.Value) constant.Value {
294 if v.Kind() == constant.Complex {
295 if constant.Sign(constant.Imag(v)) != 0 {
296 base.Errorf("constant %v truncated to integer", v)
297 }
298 v = constant.Real(v)
299 }
300
301 if v := constant.ToInt(v); v.Kind() == constant.Int {
302 return v
303 }
304
305
306
307
308
309
310
311
312
313
314 f := ir.BigFloat(v)
315 if f.MantExp(nil) > 2*ir.ConstPrec {
316 base.Errorf("integer too large")
317 } else {
318 var t big.Float
319 t.Parse(fmt.Sprint(v), 0)
320 if t.IsInt() {
321 base.Errorf("constant truncated to integer")
322 } else {
323 base.Errorf("constant %v truncated to integer", v)
324 }
325 }
326
327
328
329 return constant.MakeInt64(1)
330 }
331
332
333
334 func overflow(v constant.Value, t *types.Type) bool {
335
336
337 if t.IsUntyped() {
338 return false
339 }
340 if v.Kind() == constant.Int && constant.BitLen(v) > ir.ConstPrec {
341 base.Errorf("integer too large")
342 return true
343 }
344 if ir.ConstOverflow(v, t) {
345 base.Errorf("constant %v overflows %v", types.FmtConst(v, false), t)
346 return true
347 }
348 return false
349 }
350
351 func tostr(v constant.Value) constant.Value {
352 if v.Kind() == constant.Int {
353 r := unicode.ReplacementChar
354 if x, ok := constant.Uint64Val(v); ok && x <= unicode.MaxRune {
355 r = rune(x)
356 }
357 v = constant.MakeString(string(r))
358 }
359 return v
360 }
361
362 var tokenForOp = [...]token.Token{
363 ir.OPLUS: token.ADD,
364 ir.ONEG: token.SUB,
365 ir.ONOT: token.NOT,
366 ir.OBITNOT: token.XOR,
367
368 ir.OADD: token.ADD,
369 ir.OSUB: token.SUB,
370 ir.OMUL: token.MUL,
371 ir.ODIV: token.QUO,
372 ir.OMOD: token.REM,
373 ir.OOR: token.OR,
374 ir.OXOR: token.XOR,
375 ir.OAND: token.AND,
376 ir.OANDNOT: token.AND_NOT,
377 ir.OOROR: token.LOR,
378 ir.OANDAND: token.LAND,
379
380 ir.OEQ: token.EQL,
381 ir.ONE: token.NEQ,
382 ir.OLT: token.LSS,
383 ir.OLE: token.LEQ,
384 ir.OGT: token.GTR,
385 ir.OGE: token.GEQ,
386
387 ir.OLSH: token.SHL,
388 ir.ORSH: token.SHR,
389 }
390
391
392
393
394
395 func EvalConst(n ir.Node) ir.Node {
396
397 switch n.Op() {
398 case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT:
399 n := n.(*ir.UnaryExpr)
400 nl := n.X
401 if nl.Op() == ir.OLITERAL {
402 var prec uint
403 if n.Type().IsUnsigned() {
404 prec = uint(n.Type().Size() * 8)
405 }
406 return OrigConst(n, constant.UnaryOp(tokenForOp[n.Op()], nl.Val(), prec))
407 }
408
409 case ir.OADD, ir.OSUB, ir.OMUL, ir.ODIV, ir.OMOD, ir.OOR, ir.OXOR, ir.OAND, ir.OANDNOT:
410 n := n.(*ir.BinaryExpr)
411 nl, nr := n.X, n.Y
412 if nl.Op() == ir.OLITERAL && nr.Op() == ir.OLITERAL {
413 rval := nr.Val()
414
415
416 if n.Op() == ir.ODIV && n.Type().IsComplex() && constant.Sign(square(constant.Real(rval))) == 0 && constant.Sign(square(constant.Imag(rval))) == 0 {
417 base.Errorf("complex division by zero")
418 n.SetType(nil)
419 return n
420 }
421 if (n.Op() == ir.ODIV || n.Op() == ir.OMOD) && constant.Sign(rval) == 0 {
422 base.Errorf("division by zero")
423 n.SetType(nil)
424 return n
425 }
426
427 tok := tokenForOp[n.Op()]
428 if n.Op() == ir.ODIV && n.Type().IsInteger() {
429 tok = token.QUO_ASSIGN
430 }
431 return OrigConst(n, constant.BinaryOp(nl.Val(), tok, rval))
432 }
433
434 case ir.OOROR, ir.OANDAND:
435 n := n.(*ir.LogicalExpr)
436 nl, nr := n.X, n.Y
437 if nl.Op() == ir.OLITERAL && nr.Op() == ir.OLITERAL {
438 return OrigConst(n, constant.BinaryOp(nl.Val(), tokenForOp[n.Op()], nr.Val()))
439 }
440
441 case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
442 n := n.(*ir.BinaryExpr)
443 nl, nr := n.X, n.Y
444 if nl.Op() == ir.OLITERAL && nr.Op() == ir.OLITERAL {
445 return OrigBool(n, constant.Compare(nl.Val(), tokenForOp[n.Op()], nr.Val()))
446 }
447
448 case ir.OLSH, ir.ORSH:
449 n := n.(*ir.BinaryExpr)
450 nl, nr := n.X, n.Y
451 if nl.Op() == ir.OLITERAL && nr.Op() == ir.OLITERAL {
452
453 const shiftBound = 1023 - 1 + 52
454 s, ok := constant.Uint64Val(nr.Val())
455 if !ok || s > shiftBound {
456 base.Errorf("invalid shift count %v", nr)
457 n.SetType(nil)
458 break
459 }
460 return OrigConst(n, constant.Shift(toint(nl.Val()), tokenForOp[n.Op()], uint(s)))
461 }
462
463 case ir.OCONV, ir.ORUNESTR:
464 n := n.(*ir.ConvExpr)
465 nl := n.X
466 if ir.OKForConst[n.Type().Kind()] && nl.Op() == ir.OLITERAL {
467 return OrigConst(n, convertVal(nl.Val(), n.Type(), true))
468 }
469
470 case ir.OCONVNOP:
471 n := n.(*ir.ConvExpr)
472 nl := n.X
473 if ir.OKForConst[n.Type().Kind()] && nl.Op() == ir.OLITERAL {
474
475 n.SetOp(ir.OCONV)
476 return OrigConst(n, nl.Val())
477 }
478
479 case ir.OADDSTR:
480
481 n := n.(*ir.AddStringExpr)
482 s := n.List
483 need := 0
484 for i := 0; i < len(s); i++ {
485 if i == 0 || !ir.IsConst(s[i-1], constant.String) || !ir.IsConst(s[i], constant.String) {
486
487 need++
488 }
489 }
490 if need == len(s) {
491 return n
492 }
493 if need == 1 {
494 var strs []string
495 for _, c := range s {
496 strs = append(strs, ir.StringVal(c))
497 }
498 return OrigConst(n, constant.MakeString(strings.Join(strs, "")))
499 }
500 newList := make([]ir.Node, 0, need)
501 for i := 0; i < len(s); i++ {
502 if ir.IsConst(s[i], constant.String) && i+1 < len(s) && ir.IsConst(s[i+1], constant.String) {
503
504 var strs []string
505 i2 := i
506 for i2 < len(s) && ir.IsConst(s[i2], constant.String) {
507 strs = append(strs, ir.StringVal(s[i2]))
508 i2++
509 }
510
511 nl := ir.Copy(n).(*ir.AddStringExpr)
512 nl.List = s[i:i2]
513 newList = append(newList, OrigConst(nl, constant.MakeString(strings.Join(strs, ""))))
514 i = i2 - 1
515 } else {
516 newList = append(newList, s[i])
517 }
518 }
519
520 nn := ir.Copy(n).(*ir.AddStringExpr)
521 nn.List = newList
522 return nn
523
524 case ir.OCAP, ir.OLEN:
525 n := n.(*ir.UnaryExpr)
526 nl := n.X
527 switch nl.Type().Kind() {
528 case types.TSTRING:
529 if ir.IsConst(nl, constant.String) {
530 return OrigInt(n, int64(len(ir.StringVal(nl))))
531 }
532 case types.TARRAY:
533 if !anyCallOrChan(nl) {
534 return OrigInt(n, nl.Type().NumElem())
535 }
536 }
537
538 case ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF:
539 n := n.(*ir.UnaryExpr)
540 return OrigInt(n, evalunsafe(n))
541
542 case ir.OREAL:
543 n := n.(*ir.UnaryExpr)
544 nl := n.X
545 if nl.Op() == ir.OLITERAL {
546 return OrigConst(n, constant.Real(nl.Val()))
547 }
548
549 case ir.OIMAG:
550 n := n.(*ir.UnaryExpr)
551 nl := n.X
552 if nl.Op() == ir.OLITERAL {
553 return OrigConst(n, constant.Imag(nl.Val()))
554 }
555
556 case ir.OCOMPLEX:
557 n := n.(*ir.BinaryExpr)
558 nl, nr := n.X, n.Y
559 if nl.Op() == ir.OLITERAL && nr.Op() == ir.OLITERAL {
560 return OrigConst(n, makeComplex(nl.Val(), nr.Val()))
561 }
562 }
563
564 return n
565 }
566
567 func makeFloat64(f float64) constant.Value {
568 if math.IsInf(f, 0) {
569 base.Fatalf("infinity is not a valid constant")
570 }
571 return constant.MakeFloat64(f)
572 }
573
574 func makeComplex(real, imag constant.Value) constant.Value {
575 return constant.BinaryOp(constant.ToFloat(real), token.ADD, constant.MakeImag(constant.ToFloat(imag)))
576 }
577
578 func square(x constant.Value) constant.Value {
579 return constant.BinaryOp(x, token.MUL, x)
580 }
581
582
583
584 var overflowNames = [...]string{
585 ir.OADD: "addition",
586 ir.OSUB: "subtraction",
587 ir.OMUL: "multiplication",
588 ir.OLSH: "shift",
589 ir.OXOR: "bitwise XOR",
590 ir.OBITNOT: "bitwise complement",
591 }
592
593
594 func OrigConst(n ir.Node, v constant.Value) ir.Node {
595 lno := ir.SetPos(n)
596 v = convertVal(v, n.Type(), false)
597 base.Pos = lno
598
599 switch v.Kind() {
600 case constant.Int:
601 if constant.BitLen(v) <= ir.ConstPrec {
602 break
603 }
604 fallthrough
605 case constant.Unknown:
606 what := overflowNames[n.Op()]
607 if what == "" {
608 base.Fatalf("unexpected overflow: %v", n.Op())
609 }
610 base.ErrorfAt(n.Pos(), "constant %v overflow", what)
611 n.SetType(nil)
612 return n
613 }
614
615 return ir.NewConstExpr(v, n)
616 }
617
618 func OrigBool(n ir.Node, v bool) ir.Node {
619 return OrigConst(n, constant.MakeBool(v))
620 }
621
622 func OrigInt(n ir.Node, v int64) ir.Node {
623 return OrigConst(n, constant.MakeInt64(v))
624 }
625
626
627
628
629
630
631
632 func defaultlit2(l ir.Node, r ir.Node, force bool) (ir.Node, ir.Node) {
633 if l.Type() == nil || r.Type() == nil {
634 return l, r
635 }
636
637 if !l.Type().IsInterface() && !r.Type().IsInterface() {
638
639 if l.Type().IsBoolean() != r.Type().IsBoolean() {
640 return l, r
641 }
642 if l.Type().IsString() != r.Type().IsString() {
643 return l, r
644 }
645 }
646
647 if !l.Type().IsUntyped() {
648 r = convlit(r, l.Type())
649 return l, r
650 }
651
652 if !r.Type().IsUntyped() {
653 l = convlit(l, r.Type())
654 return l, r
655 }
656
657 if !force {
658 return l, r
659 }
660
661
662 if ir.IsNil(l) || ir.IsNil(r) {
663 return l, r
664 }
665 t := defaultType(mixUntyped(l.Type(), r.Type()))
666 l = convlit(l, t)
667 r = convlit(r, t)
668 return l, r
669 }
670
671 func mixUntyped(t1, t2 *types.Type) *types.Type {
672 if t1 == t2 {
673 return t1
674 }
675
676 rank := func(t *types.Type) int {
677 switch t {
678 case types.UntypedInt:
679 return 0
680 case types.UntypedRune:
681 return 1
682 case types.UntypedFloat:
683 return 2
684 case types.UntypedComplex:
685 return 3
686 }
687 base.Fatalf("bad type %v", t)
688 panic("unreachable")
689 }
690
691 if rank(t2) > rank(t1) {
692 return t2
693 }
694 return t1
695 }
696
697 func defaultType(t *types.Type) *types.Type {
698 if !t.IsUntyped() || t.Kind() == types.TNIL {
699 return t
700 }
701
702 switch t {
703 case types.UntypedBool:
704 return types.Types[types.TBOOL]
705 case types.UntypedString:
706 return types.Types[types.TSTRING]
707 case types.UntypedInt:
708 return types.Types[types.TINT]
709 case types.UntypedRune:
710 return types.RuneType
711 case types.UntypedFloat:
712 return types.Types[types.TFLOAT64]
713 case types.UntypedComplex:
714 return types.Types[types.TCOMPLEX128]
715 }
716
717 base.Fatalf("bad type %v", t)
718 return nil
719 }
720
721
722
723
724
725
726 func IndexConst(n ir.Node) int64 {
727 if n.Op() != ir.OLITERAL {
728 return -1
729 }
730 if !n.Type().IsInteger() && n.Type().Kind() != types.TIDEAL {
731 return -1
732 }
733
734 v := toint(n.Val())
735 if v.Kind() != constant.Int || constant.Sign(v) < 0 {
736 return -1
737 }
738 if ir.ConstOverflow(v, types.Types[types.TINT]) {
739 return -2
740 }
741 return ir.IntVal(types.Types[types.TINT], v)
742 }
743
744
745 func anyCallOrChan(n ir.Node) bool {
746 return ir.Any(n, func(n ir.Node) bool {
747 switch n.Op() {
748 case ir.OAPPEND,
749 ir.OCALL,
750 ir.OCALLFUNC,
751 ir.OCALLINTER,
752 ir.OCALLMETH,
753 ir.OCAP,
754 ir.OCLOSE,
755 ir.OCOMPLEX,
756 ir.OCOPY,
757 ir.ODELETE,
758 ir.OIMAG,
759 ir.OLEN,
760 ir.OMAKE,
761 ir.ONEW,
762 ir.OPANIC,
763 ir.OPRINT,
764 ir.OPRINTN,
765 ir.OREAL,
766 ir.ORECOVER,
767 ir.ORECV,
768 ir.OUNSAFEADD,
769 ir.OUNSAFESLICE:
770 return true
771 }
772 return false
773 })
774 }
775
776
777 type constSet struct {
778 m map[constSetKey]src.XPos
779 }
780
781 type constSetKey struct {
782 typ *types.Type
783 val interface{}
784 }
785
786
787
788
789
790
791
792
793
794
795 func (s *constSet) add(pos src.XPos, n ir.Node, what, where string) {
796 if conv := n; conv.Op() == ir.OCONVIFACE {
797 conv := conv.(*ir.ConvExpr)
798 if conv.Implicit() {
799 n = conv.X
800 }
801 }
802
803 if !ir.IsConstNode(n) || n.Type() == nil {
804 return
805 }
806 if n.Type().IsUntyped() {
807 base.Fatalf("%v is untyped", n)
808 }
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825 typ := n.Type()
826 switch typ {
827 case types.ByteType:
828 typ = types.Types[types.TUINT8]
829 case types.RuneType:
830 typ = types.Types[types.TINT32]
831 }
832 k := constSetKey{typ, ir.ConstValue(n)}
833
834 if ir.HasUniquePos(n) {
835 pos = n.Pos()
836 }
837
838 if s.m == nil {
839 s.m = make(map[constSetKey]src.XPos)
840 }
841
842 if prevPos, isDup := s.m[k]; isDup {
843 base.ErrorfAt(pos, "duplicate %s %s in %s\n\tprevious %s at %v",
844 what, nodeAndVal(n), where,
845 what, base.FmtPos(prevPos))
846 } else {
847 s.m[k] = pos
848 }
849 }
850
851
852
853
854
855 func nodeAndVal(n ir.Node) string {
856 show := fmt.Sprint(n)
857 val := ir.ConstValue(n)
858 if s := fmt.Sprintf("%#v", val); show != s {
859 show += " (value " + s + ")"
860 }
861 return show
862 }
863
864
865 func evalunsafe(n ir.Node) int64 {
866 switch n.Op() {
867 case ir.OALIGNOF, ir.OSIZEOF:
868 n := n.(*ir.UnaryExpr)
869 n.X = Expr(n.X)
870 n.X = DefaultLit(n.X, nil)
871 tr := n.X.Type()
872 if tr == nil {
873 return 0
874 }
875 types.CalcSize(tr)
876 if n.Op() == ir.OALIGNOF {
877 return tr.Alignment()
878 }
879 return tr.Size()
880
881 case ir.OOFFSETOF:
882
883 n := n.(*ir.UnaryExpr)
884
885
886 if n.X.Op() != ir.OXDOT && n.X.Op() != ir.ODOT && n.X.Op() != ir.ODOTPTR {
887 base.Errorf("invalid expression %v", n)
888 return 0
889 }
890 sel := n.X.(*ir.SelectorExpr)
891
892
893
894
895 sel.X = Expr(sel.X)
896 sbase := sel.X
897
898 tsel := Expr(sel)
899 n.X = tsel
900 if tsel.Type() == nil {
901 return 0
902 }
903 switch tsel.Op() {
904 case ir.ODOT, ir.ODOTPTR:
905 break
906 case ir.OMETHVALUE:
907 base.Errorf("invalid expression %v: argument is a method value", n)
908 return 0
909 default:
910 base.Errorf("invalid expression %v", n)
911 return 0
912 }
913
914
915 var v int64
916 var next ir.Node
917 for r := tsel; r != sbase; r = next {
918 switch r.Op() {
919 case ir.ODOTPTR:
920
921
922
923 r := r.(*ir.SelectorExpr)
924 if r.X != sbase {
925 base.Errorf("invalid expression %v: selector implies indirection of embedded %v", n, r.X)
926 return 0
927 }
928 fallthrough
929 case ir.ODOT:
930 r := r.(*ir.SelectorExpr)
931 v += r.Offset()
932 next = r.X
933 default:
934 ir.Dump("unsafenmagic", tsel)
935 base.Fatalf("impossible %v node after dot insertion", r.Op())
936 }
937 }
938 return v
939 }
940
941 base.Fatalf("unexpected op %v", n.Op())
942 return 0
943 }
944
View as plain text