Source file src/pkg/cmd/compile/internal/gc/iexport.go
1
2
3
4
5
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199 package gc
200
201 import (
202 "bufio"
203 "bytes"
204 "cmd/compile/internal/types"
205 "cmd/internal/src"
206 "encoding/binary"
207 "fmt"
208 "io"
209 "math/big"
210 "sort"
211 "strings"
212 )
213
214
215
216 const iexportVersion = 0
217
218
219
220 const predeclReserved = 32
221
222
223
224 type itag uint64
225
226 const (
227
228 definedType itag = iota
229 pointerType
230 sliceType
231 arrayType
232 chanType
233 mapType
234 signatureType
235 structType
236 interfaceType
237 )
238
239 func iexport(out *bufio.Writer) {
240
241
242 {
243
244 p := &exporter{marked: make(map[*types.Type]bool)}
245 for _, n := range exportlist {
246 sym := n.Sym
247 p.markType(asNode(sym.Def).Type)
248 }
249 }
250
251 p := iexporter{
252 allPkgs: map[*types.Pkg]bool{},
253 stringIndex: map[string]uint64{},
254 declIndex: map[*Node]uint64{},
255 inlineIndex: map[*Node]uint64{},
256 typIndex: map[*types.Type]uint64{},
257 }
258
259 for i, pt := range predeclared() {
260 p.typIndex[pt] = uint64(i)
261 }
262 if len(p.typIndex) > predeclReserved {
263 Fatalf("too many predeclared types: %d > %d", len(p.typIndex), predeclReserved)
264 }
265
266
267 for _, n := range exportlist {
268 p.pushDecl(n)
269 }
270
271
272
273
274 for !p.declTodo.empty() {
275 p.doDecl(p.declTodo.popLeft())
276 }
277
278
279 dataLen := uint64(p.data0.Len())
280 w := p.newWriter()
281 w.writeIndex(p.declIndex, true)
282 w.writeIndex(p.inlineIndex, false)
283 w.flush()
284
285
286 var hdr intWriter
287 hdr.WriteByte('i')
288 hdr.uint64(iexportVersion)
289 hdr.uint64(uint64(p.strings.Len()))
290 hdr.uint64(dataLen)
291
292
293 io.Copy(out, &hdr)
294 io.Copy(out, &p.strings)
295 io.Copy(out, &p.data0)
296 }
297
298
299
300
301
302 func (w *exportWriter) writeIndex(index map[*Node]uint64, mainIndex bool) {
303
304 pkgObjs := map[*types.Pkg][]*Node{}
305
306
307
308
309 if mainIndex {
310 pkgObjs[localpkg] = nil
311 for pkg := range w.p.allPkgs {
312 pkgObjs[pkg] = nil
313 }
314 }
315
316 for n := range index {
317 pkgObjs[n.Sym.Pkg] = append(pkgObjs[n.Sym.Pkg], n)
318 }
319
320 var pkgs []*types.Pkg
321 for pkg, objs := range pkgObjs {
322 pkgs = append(pkgs, pkg)
323
324 sort.Slice(objs, func(i, j int) bool {
325 return objs[i].Sym.Name < objs[j].Sym.Name
326 })
327 }
328
329 sort.Slice(pkgs, func(i, j int) bool {
330 return pkgs[i].Path < pkgs[j].Path
331 })
332
333 w.uint64(uint64(len(pkgs)))
334 for _, pkg := range pkgs {
335 w.string(pkg.Path)
336 if mainIndex {
337 w.string(pkg.Name)
338 w.uint64(uint64(pkg.Height))
339 }
340
341 objs := pkgObjs[pkg]
342 w.uint64(uint64(len(objs)))
343 for _, n := range objs {
344 w.string(n.Sym.Name)
345 w.uint64(index[n])
346 }
347 }
348 }
349
350 type iexporter struct {
351
352
353
354 allPkgs map[*types.Pkg]bool
355
356 declTodo nodeQueue
357
358 strings intWriter
359 stringIndex map[string]uint64
360
361 data0 intWriter
362 declIndex map[*Node]uint64
363 inlineIndex map[*Node]uint64
364 typIndex map[*types.Type]uint64
365 }
366
367
368
369 func (p *iexporter) stringOff(s string) uint64 {
370 off, ok := p.stringIndex[s]
371 if !ok {
372 off = uint64(p.strings.Len())
373 p.stringIndex[s] = off
374
375 p.strings.uint64(uint64(len(s)))
376 p.strings.WriteString(s)
377 }
378 return off
379 }
380
381
382 func (p *iexporter) pushDecl(n *Node) {
383 if n.Sym == nil || asNode(n.Sym.Def) != n && n.Op != OTYPE {
384 Fatalf("weird Sym: %v, %v", n, n.Sym)
385 }
386
387
388 if n.Sym.Pkg == builtinpkg || n.Sym.Pkg == unsafepkg {
389 return
390 }
391
392 if _, ok := p.declIndex[n]; ok {
393 return
394 }
395
396 p.declIndex[n] = ^uint64(0)
397 p.declTodo.pushRight(n)
398 }
399
400
401 type exportWriter struct {
402 p *iexporter
403
404 data intWriter
405 currPkg *types.Pkg
406 prevFile string
407 prevLine int64
408 }
409
410 func (p *iexporter) doDecl(n *Node) {
411 w := p.newWriter()
412 w.setPkg(n.Sym.Pkg, false)
413
414 switch n.Op {
415 case ONAME:
416 switch n.Class() {
417 case PEXTERN:
418
419 w.tag('V')
420 w.pos(n.Pos)
421 w.typ(n.Type)
422 w.varExt(n)
423
424 case PFUNC:
425 if n.IsMethod() {
426 Fatalf("unexpected method: %v", n)
427 }
428
429
430 w.tag('F')
431 w.pos(n.Pos)
432 w.signature(n.Type)
433 w.funcExt(n)
434
435 default:
436 Fatalf("unexpected class: %v, %v", n, n.Class())
437 }
438
439 case OLITERAL:
440
441 n = typecheck(n, ctxExpr)
442 w.tag('C')
443 w.pos(n.Pos)
444 w.value(n.Type, n.Val())
445
446 case OTYPE:
447 if IsAlias(n.Sym) {
448
449 w.tag('A')
450 w.pos(n.Pos)
451 w.typ(n.Type)
452 break
453 }
454
455
456 w.tag('T')
457 w.pos(n.Pos)
458
459 underlying := n.Type.Orig
460 if underlying == types.Errortype.Orig {
461
462
463
464
465
466
467 underlying = types.Errortype
468 }
469 w.typ(underlying)
470
471 t := n.Type
472 if t.IsInterface() {
473 break
474 }
475
476 ms := t.Methods()
477 w.uint64(uint64(ms.Len()))
478 for _, m := range ms.Slice() {
479 w.pos(m.Pos)
480 w.selector(m.Sym)
481 w.param(m.Type.Recv())
482 w.signature(m.Type)
483 }
484
485 for _, m := range ms.Slice() {
486 w.methExt(m)
487 }
488
489 default:
490 Fatalf("unexpected node: %v", n)
491 }
492
493 p.declIndex[n] = w.flush()
494 }
495
496 func (w *exportWriter) tag(tag byte) {
497 w.data.WriteByte(tag)
498 }
499
500 func (p *iexporter) doInline(f *Node) {
501 w := p.newWriter()
502 w.setPkg(fnpkg(f), false)
503
504 w.stmtList(asNodes(f.Func.Inl.Body))
505
506 p.inlineIndex[f] = w.flush()
507 }
508
509 func (w *exportWriter) pos(pos src.XPos) {
510 p := Ctxt.PosTable.Pos(pos)
511 file := p.Base().AbsFilename()
512 line := int64(p.RelLine())
513
514
515
516
517
518
519
520
521
522
523 if file == w.prevFile {
524 delta := line - w.prevLine
525 w.int64(delta)
526 if delta == deltaNewFile {
527 w.int64(-1)
528 }
529 } else {
530 w.int64(deltaNewFile)
531 w.int64(line)
532 w.string(file)
533 w.prevFile = file
534 }
535 w.prevLine = line
536 }
537
538 func (w *exportWriter) pkg(pkg *types.Pkg) {
539
540 w.p.allPkgs[pkg] = true
541
542 w.string(pkg.Path)
543 }
544
545 func (w *exportWriter) qualifiedIdent(n *Node) {
546
547 w.p.pushDecl(n)
548
549 s := n.Sym
550 w.string(s.Name)
551 w.pkg(s.Pkg)
552 }
553
554 func (w *exportWriter) selector(s *types.Sym) {
555 if w.currPkg == nil {
556 Fatalf("missing currPkg")
557 }
558
559
560
561
562 name := s.Name
563 if i := strings.LastIndex(name, "."); i >= 0 {
564 name = name[i+1:]
565 } else {
566 pkg := w.currPkg
567 if types.IsExported(name) {
568 pkg = localpkg
569 }
570 if s.Pkg != pkg {
571 Fatalf("package mismatch in selector: %v in package %q, but want %q", s, s.Pkg.Path, pkg.Path)
572 }
573 }
574
575 w.string(name)
576 }
577
578 func (w *exportWriter) typ(t *types.Type) {
579 w.data.uint64(w.p.typOff(t))
580 }
581
582 func (p *iexporter) newWriter() *exportWriter {
583 return &exportWriter{p: p}
584 }
585
586 func (w *exportWriter) flush() uint64 {
587 off := uint64(w.p.data0.Len())
588 io.Copy(&w.p.data0, &w.data)
589 return off
590 }
591
592 func (p *iexporter) typOff(t *types.Type) uint64 {
593 off, ok := p.typIndex[t]
594 if !ok {
595 w := p.newWriter()
596 w.doTyp(t)
597 off = predeclReserved + w.flush()
598 p.typIndex[t] = off
599 }
600 return off
601 }
602
603 func (w *exportWriter) startType(k itag) {
604 w.data.uint64(uint64(k))
605 }
606
607 func (w *exportWriter) doTyp(t *types.Type) {
608 if t.Sym != nil {
609 if t.Sym.Pkg == builtinpkg || t.Sym.Pkg == unsafepkg {
610 Fatalf("builtin type missing from typIndex: %v", t)
611 }
612
613 w.startType(definedType)
614 w.qualifiedIdent(typenod(t))
615 return
616 }
617
618 switch t.Etype {
619 case TPTR:
620 w.startType(pointerType)
621 w.typ(t.Elem())
622
623 case TSLICE:
624 w.startType(sliceType)
625 w.typ(t.Elem())
626
627 case TARRAY:
628 w.startType(arrayType)
629 w.uint64(uint64(t.NumElem()))
630 w.typ(t.Elem())
631
632 case TCHAN:
633 w.startType(chanType)
634 w.uint64(uint64(t.ChanDir()))
635 w.typ(t.Elem())
636
637 case TMAP:
638 w.startType(mapType)
639 w.typ(t.Key())
640 w.typ(t.Elem())
641
642 case TFUNC:
643 w.startType(signatureType)
644 w.setPkg(t.Pkg(), true)
645 w.signature(t)
646
647 case TSTRUCT:
648 w.startType(structType)
649 w.setPkg(t.Pkg(), true)
650
651 w.uint64(uint64(t.NumFields()))
652 for _, f := range t.FieldSlice() {
653 w.pos(f.Pos)
654 w.selector(f.Sym)
655 w.typ(f.Type)
656 w.bool(f.Embedded != 0)
657 w.string(f.Note)
658 }
659
660 case TINTER:
661 var embeddeds, methods []*types.Field
662 for _, m := range t.Methods().Slice() {
663 if m.Sym != nil {
664 methods = append(methods, m)
665 } else {
666 embeddeds = append(embeddeds, m)
667 }
668 }
669
670 w.startType(interfaceType)
671 w.setPkg(t.Pkg(), true)
672
673 w.uint64(uint64(len(embeddeds)))
674 for _, f := range embeddeds {
675 w.pos(f.Pos)
676 w.typ(f.Type)
677 }
678
679 w.uint64(uint64(len(methods)))
680 for _, f := range methods {
681 w.pos(f.Pos)
682 w.selector(f.Sym)
683 w.signature(f.Type)
684 }
685
686 default:
687 Fatalf("unexpected type: %v", t)
688 }
689 }
690
691 func (w *exportWriter) setPkg(pkg *types.Pkg, write bool) {
692 if pkg == nil {
693
694
695 pkg = localpkg
696 }
697
698 if write {
699 w.pkg(pkg)
700 }
701
702 w.currPkg = pkg
703 }
704
705 func (w *exportWriter) signature(t *types.Type) {
706 w.paramList(t.Params().FieldSlice())
707 w.paramList(t.Results().FieldSlice())
708 if n := t.Params().NumFields(); n > 0 {
709 w.bool(t.Params().Field(n - 1).IsDDD())
710 }
711 }
712
713 func (w *exportWriter) paramList(fs []*types.Field) {
714 w.uint64(uint64(len(fs)))
715 for _, f := range fs {
716 w.param(f)
717 }
718 }
719
720 func (w *exportWriter) param(f *types.Field) {
721 w.pos(f.Pos)
722 w.localIdent(origSym(f.Sym), 0)
723 w.typ(f.Type)
724 }
725
726 func constTypeOf(typ *types.Type) Ctype {
727 switch typ {
728 case types.Idealint, types.Idealrune:
729 return CTINT
730 case types.Idealfloat:
731 return CTFLT
732 case types.Idealcomplex:
733 return CTCPLX
734 }
735
736 switch typ.Etype {
737 case TCHAN, TFUNC, TMAP, TNIL, TINTER, TSLICE:
738 return CTNIL
739 case TBOOL:
740 return CTBOOL
741 case TSTRING:
742 return CTSTR
743 case TINT, TINT8, TINT16, TINT32, TINT64,
744 TUINT, TUINT8, TUINT16, TUINT32, TUINT64, TUINTPTR,
745 TPTR, TUNSAFEPTR:
746 return CTINT
747 case TFLOAT32, TFLOAT64:
748 return CTFLT
749 case TCOMPLEX64, TCOMPLEX128:
750 return CTCPLX
751 }
752
753 Fatalf("unexpected constant type: %v", typ)
754 return 0
755 }
756
757 func (w *exportWriter) value(typ *types.Type, v Val) {
758 if typ.IsUntyped() {
759 typ = untype(v.Ctype())
760 }
761 w.typ(typ)
762
763
764
765
766
767
768 switch constTypeOf(typ) {
769 case CTNIL:
770
771 _ = v.U.(*NilVal)
772 case CTBOOL:
773 w.bool(v.U.(bool))
774 case CTSTR:
775 w.string(v.U.(string))
776 case CTINT:
777 w.mpint(&v.U.(*Mpint).Val, typ)
778 case CTFLT:
779 w.mpfloat(&v.U.(*Mpflt).Val, typ)
780 case CTCPLX:
781 x := v.U.(*Mpcplx)
782 w.mpfloat(&x.Real.Val, typ)
783 w.mpfloat(&x.Imag.Val, typ)
784 }
785 }
786
787 func intSize(typ *types.Type) (signed bool, maxBytes uint) {
788 if typ.IsUntyped() {
789 return true, Mpprec / 8
790 }
791
792 switch typ.Etype {
793 case TFLOAT32, TCOMPLEX64:
794 return true, 3
795 case TFLOAT64, TCOMPLEX128:
796 return true, 7
797 }
798
799 signed = typ.IsSigned()
800 maxBytes = uint(typ.Size())
801
802
803
804 switch typ.Etype {
805 case TINT, TUINT, TUINTPTR:
806 maxBytes = 8
807 }
808
809 return
810 }
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832 func (w *exportWriter) mpint(x *big.Int, typ *types.Type) {
833 signed, maxBytes := intSize(typ)
834
835 negative := x.Sign() < 0
836 if !signed && negative {
837 Fatalf("negative unsigned integer; type %v, value %v", typ, x)
838 }
839
840 b := x.Bytes()
841 if len(b) > 0 && b[0] == 0 {
842 Fatalf("leading zeros")
843 }
844 if uint(len(b)) > maxBytes {
845 Fatalf("bad mpint length: %d > %d (type %v, value %v)", len(b), maxBytes, typ, x)
846 }
847
848 maxSmall := 256 - maxBytes
849 if signed {
850 maxSmall = 256 - 2*maxBytes
851 }
852 if maxBytes == 1 {
853 maxSmall = 256
854 }
855
856
857 if len(b) <= 1 {
858 var ux uint
859 if len(b) == 1 {
860 ux = uint(b[0])
861 }
862 if signed {
863 ux <<= 1
864 if negative {
865 ux--
866 }
867 }
868 if ux < maxSmall {
869 w.data.WriteByte(byte(ux))
870 return
871 }
872 }
873
874 n := 256 - uint(len(b))
875 if signed {
876 n = 256 - 2*uint(len(b))
877 if negative {
878 n |= 1
879 }
880 }
881 if n < maxSmall || n >= 256 {
882 Fatalf("encoding mistake: %d, %v, %v => %d", len(b), signed, negative, n)
883 }
884
885 w.data.WriteByte(byte(n))
886 w.data.Write(b)
887 }
888
889
890
891
892
893
894
895 func (w *exportWriter) mpfloat(f *big.Float, typ *types.Type) {
896 if f.IsInf() {
897 Fatalf("infinite constant")
898 }
899
900
901 var mant big.Float
902 exp := int64(f.MantExp(&mant))
903
904
905 prec := mant.MinPrec()
906 mant.SetMantExp(&mant, int(prec))
907 exp -= int64(prec)
908
909 manti, acc := mant.Int(nil)
910 if acc != big.Exact {
911 Fatalf("mantissa scaling failed for %f (%s)", f, acc)
912 }
913 w.mpint(manti, typ)
914 if manti.Sign() != 0 {
915 w.int64(exp)
916 }
917 }
918
919 func (w *exportWriter) bool(b bool) bool {
920 var x uint64
921 if b {
922 x = 1
923 }
924 w.uint64(x)
925 return b
926 }
927
928 func (w *exportWriter) int64(x int64) { w.data.int64(x) }
929 func (w *exportWriter) uint64(x uint64) { w.data.uint64(x) }
930 func (w *exportWriter) string(s string) { w.uint64(w.p.stringOff(s)) }
931
932
933
934 func (w *exportWriter) varExt(n *Node) {
935 w.linkname(n.Sym)
936 }
937
938 func (w *exportWriter) funcExt(n *Node) {
939 w.linkname(n.Sym)
940
941
942 for _, fs := range types.RecvsParams {
943 for _, f := range fs(n.Type).FieldSlice() {
944 w.string(f.Note)
945 }
946 }
947
948
949 if n.Func.Inl != nil {
950 w.uint64(1 + uint64(n.Func.Inl.Cost))
951 if n.Func.ExportInline() {
952 w.p.doInline(n)
953 }
954
955
956 if n.Name.Defn != nil {
957 w.pos(n.Name.Defn.Func.Endlineno)
958 } else {
959
960
961
962 w.pos(n.Func.Endlineno)
963 }
964 } else {
965 w.uint64(0)
966 }
967 }
968
969 func (w *exportWriter) methExt(m *types.Field) {
970 w.bool(m.Nointerface())
971 w.funcExt(asNode(m.Type.Nname()))
972 }
973
974 func (w *exportWriter) linkname(s *types.Sym) {
975 w.string(s.Linkname)
976 }
977
978
979
980 func (w *exportWriter) stmtList(list Nodes) {
981 for _, n := range list.Slice() {
982 w.node(n)
983 }
984 w.op(OEND)
985 }
986
987 func (w *exportWriter) node(n *Node) {
988 if opprec[n.Op] < 0 {
989 w.stmt(n)
990 } else {
991 w.expr(n)
992 }
993 }
994
995
996
997 func (w *exportWriter) stmt(n *Node) {
998 if n.Ninit.Len() > 0 && !stmtwithinit(n.Op) {
999
1000 for _, n := range n.Ninit.Slice() {
1001 w.stmt(n)
1002 }
1003 }
1004
1005 switch op := n.Op; op {
1006 case ODCL:
1007 w.op(ODCL)
1008 w.pos(n.Left.Pos)
1009 w.localName(n.Left)
1010 w.typ(n.Left.Type)
1011
1012
1013
1014
1015 case OAS:
1016
1017
1018
1019 if n.Right != nil {
1020 w.op(OAS)
1021 w.pos(n.Pos)
1022 w.expr(n.Left)
1023 w.expr(n.Right)
1024 }
1025
1026 case OASOP:
1027 w.op(OASOP)
1028 w.pos(n.Pos)
1029 w.op(n.SubOp())
1030 w.expr(n.Left)
1031 if w.bool(!n.Implicit()) {
1032 w.expr(n.Right)
1033 }
1034
1035 case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
1036 w.op(OAS2)
1037 w.pos(n.Pos)
1038 w.exprList(n.List)
1039 w.exprList(n.Rlist)
1040
1041 case ORETURN:
1042 w.op(ORETURN)
1043 w.pos(n.Pos)
1044 w.exprList(n.List)
1045
1046
1047
1048
1049 case OGO, ODEFER:
1050 w.op(op)
1051 w.pos(n.Pos)
1052 w.expr(n.Left)
1053
1054 case OIF:
1055 w.op(OIF)
1056 w.pos(n.Pos)
1057 w.stmtList(n.Ninit)
1058 w.expr(n.Left)
1059 w.stmtList(n.Nbody)
1060 w.stmtList(n.Rlist)
1061
1062 case OFOR:
1063 w.op(OFOR)
1064 w.pos(n.Pos)
1065 w.stmtList(n.Ninit)
1066 w.exprsOrNil(n.Left, n.Right)
1067 w.stmtList(n.Nbody)
1068
1069 case ORANGE:
1070 w.op(ORANGE)
1071 w.pos(n.Pos)
1072 w.stmtList(n.List)
1073 w.expr(n.Right)
1074 w.stmtList(n.Nbody)
1075
1076 case OSELECT, OSWITCH:
1077 w.op(op)
1078 w.pos(n.Pos)
1079 w.stmtList(n.Ninit)
1080 w.exprsOrNil(n.Left, nil)
1081 w.stmtList(n.List)
1082
1083 case OCASE, OXCASE:
1084 w.op(OXCASE)
1085 w.pos(n.Pos)
1086 w.stmtList(n.List)
1087 w.stmtList(n.Nbody)
1088
1089 case OFALL:
1090 w.op(OFALL)
1091 w.pos(n.Pos)
1092
1093 case OBREAK, OCONTINUE:
1094 w.op(op)
1095 w.pos(n.Pos)
1096 w.exprsOrNil(n.Left, nil)
1097
1098 case OEMPTY:
1099
1100
1101 case OGOTO, OLABEL:
1102 w.op(op)
1103 w.pos(n.Pos)
1104 w.string(n.Sym.Name)
1105
1106 default:
1107 Fatalf("exporter: CANNOT EXPORT: %v\nPlease notify gri@\n", n.Op)
1108 }
1109 }
1110
1111 func (w *exportWriter) exprList(list Nodes) {
1112 for _, n := range list.Slice() {
1113 w.expr(n)
1114 }
1115 w.op(OEND)
1116 }
1117
1118 func (w *exportWriter) expr(n *Node) {
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129 for n.Op == OPAREN || n.Implicit() && (n.Op == ODEREF || n.Op == OADDR || n.Op == ODOT || n.Op == ODOTPTR) {
1130 n = n.Left
1131 }
1132
1133 switch op := n.Op; op {
1134
1135
1136 case OLITERAL:
1137 if n.Val().Ctype() == CTNIL && n.Orig != nil && n.Orig != n {
1138 w.expr(n.Orig)
1139 break
1140 }
1141 w.op(OLITERAL)
1142 w.pos(n.Pos)
1143 w.value(n.Type, n.Val())
1144
1145 case ONAME:
1146
1147
1148
1149 if n.isMethodExpression() {
1150 w.op(OXDOT)
1151 w.pos(n.Pos)
1152 w.expr(n.Left)
1153 w.selector(n.Right.Sym)
1154 break
1155 }
1156
1157
1158 if (n.Class() == PEXTERN || n.Class() == PFUNC) && !n.isBlank() {
1159 w.op(ONONAME)
1160 w.qualifiedIdent(n)
1161 break
1162 }
1163
1164
1165 w.op(ONAME)
1166 w.localName(n)
1167
1168
1169
1170
1171 case OTYPE:
1172 w.op(OTYPE)
1173 w.typ(n.Type)
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184 case OPTRLIT:
1185 w.op(OPTRLIT)
1186 w.pos(n.Pos)
1187 w.expr(n.Left)
1188 w.bool(n.Implicit())
1189
1190 case OSTRUCTLIT:
1191 w.op(OSTRUCTLIT)
1192 w.pos(n.Pos)
1193 w.typ(n.Type)
1194 w.elemList(n.List)
1195
1196 case OARRAYLIT, OSLICELIT, OMAPLIT:
1197 w.op(OCOMPLIT)
1198 w.pos(n.Pos)
1199 w.typ(n.Type)
1200 w.exprList(n.List)
1201
1202 case OKEY:
1203 w.op(OKEY)
1204 w.pos(n.Pos)
1205 w.exprsOrNil(n.Left, n.Right)
1206
1207
1208
1209
1210
1211
1212
1213 case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
1214 w.op(OXDOT)
1215 w.pos(n.Pos)
1216 w.expr(n.Left)
1217 w.selector(n.Sym)
1218
1219 case ODOTTYPE, ODOTTYPE2:
1220 w.op(ODOTTYPE)
1221 w.pos(n.Pos)
1222 w.expr(n.Left)
1223 w.typ(n.Type)
1224
1225 case OINDEX, OINDEXMAP:
1226 w.op(OINDEX)
1227 w.pos(n.Pos)
1228 w.expr(n.Left)
1229 w.expr(n.Right)
1230
1231 case OSLICE, OSLICESTR, OSLICEARR:
1232 w.op(OSLICE)
1233 w.pos(n.Pos)
1234 w.expr(n.Left)
1235 low, high, _ := n.SliceBounds()
1236 w.exprsOrNil(low, high)
1237
1238 case OSLICE3, OSLICE3ARR:
1239 w.op(OSLICE3)
1240 w.pos(n.Pos)
1241 w.expr(n.Left)
1242 low, high, max := n.SliceBounds()
1243 w.exprsOrNil(low, high)
1244 w.expr(max)
1245
1246 case OCOPY, OCOMPLEX:
1247
1248 w.op(op)
1249 w.pos(n.Pos)
1250 w.expr(n.Left)
1251 w.expr(n.Right)
1252 w.op(OEND)
1253
1254 case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, ORUNES2STR, OSTR2BYTES, OSTR2RUNES, ORUNESTR:
1255 w.op(OCONV)
1256 w.pos(n.Pos)
1257 w.expr(n.Left)
1258 w.typ(n.Type)
1259
1260 case OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN:
1261 w.op(op)
1262 w.pos(n.Pos)
1263 if n.Left != nil {
1264 w.expr(n.Left)
1265 w.op(OEND)
1266 } else {
1267 w.exprList(n.List)
1268 }
1269
1270 if op == OAPPEND {
1271 w.bool(n.IsDDD())
1272 } else if n.IsDDD() {
1273 Fatalf("exporter: unexpected '...' with %v call", op)
1274 }
1275
1276 case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG:
1277 w.op(OCALL)
1278 w.pos(n.Pos)
1279 w.stmtList(n.Ninit)
1280 w.expr(n.Left)
1281 w.exprList(n.List)
1282 w.bool(n.IsDDD())
1283
1284 case OMAKEMAP, OMAKECHAN, OMAKESLICE:
1285 w.op(op)
1286 w.pos(n.Pos)
1287 w.typ(n.Type)
1288 switch {
1289 default:
1290
1291 w.op(OEND)
1292 case n.List.Len() != 0:
1293 w.exprList(n.List)
1294 case n.Right != nil:
1295 w.expr(n.Left)
1296 w.expr(n.Right)
1297 w.op(OEND)
1298 case n.Left != nil && (n.Op == OMAKESLICE || !n.Left.Type.IsUntyped()):
1299 w.expr(n.Left)
1300 w.op(OEND)
1301 }
1302
1303
1304 case OPLUS, ONEG, OADDR, OBITNOT, ODEREF, ONOT, ORECV:
1305 w.op(op)
1306 w.pos(n.Pos)
1307 w.expr(n.Left)
1308
1309
1310 case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, OLT,
1311 OLSH, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSEND, OSUB, OXOR:
1312 w.op(op)
1313 w.pos(n.Pos)
1314 w.expr(n.Left)
1315 w.expr(n.Right)
1316
1317 case OADDSTR:
1318 w.op(OADDSTR)
1319 w.pos(n.Pos)
1320 w.exprList(n.List)
1321
1322 case ODCLCONST:
1323
1324
1325
1326 default:
1327 Fatalf("cannot export %v (%d) node\n"+
1328 "\t==> please file an issue and assign to gri@", n.Op, int(n.Op))
1329 }
1330 }
1331
1332 func (w *exportWriter) op(op Op) {
1333 w.uint64(uint64(op))
1334 }
1335
1336 func (w *exportWriter) exprsOrNil(a, b *Node) {
1337 ab := 0
1338 if a != nil {
1339 ab |= 1
1340 }
1341 if b != nil {
1342 ab |= 2
1343 }
1344 w.uint64(uint64(ab))
1345 if ab&1 != 0 {
1346 w.expr(a)
1347 }
1348 if ab&2 != 0 {
1349 w.node(b)
1350 }
1351 }
1352
1353 func (w *exportWriter) elemList(list Nodes) {
1354 w.uint64(uint64(list.Len()))
1355 for _, n := range list.Slice() {
1356 w.selector(n.Sym)
1357 w.expr(n.Left)
1358 }
1359 }
1360
1361 func (w *exportWriter) localName(n *Node) {
1362
1363
1364
1365
1366
1367
1368
1369 var v int32
1370 if n.Class() == PAUTO || (n.Class() == PAUTOHEAP && n.Name.Param.Stackcopy == nil) {
1371 v = n.Name.Vargen
1372 }
1373
1374 w.localIdent(n.Sym, v)
1375 }
1376
1377 func (w *exportWriter) localIdent(s *types.Sym, v int32) {
1378
1379 if s == nil {
1380 w.string("")
1381 return
1382 }
1383
1384 name := s.Name
1385 if name == "_" {
1386 w.string("_")
1387 return
1388 }
1389
1390
1391 if i := strings.LastIndex(name, "."); i >= 0 && !strings.HasPrefix(name, ".autotmp_") {
1392 Fatalf("unexpected dot in identifier: %v", name)
1393 }
1394
1395 if v > 0 {
1396 if strings.Contains(name, "·") {
1397 Fatalf("exporter: unexpected · in symbol name")
1398 }
1399 name = fmt.Sprintf("%s·%d", name, v)
1400 }
1401
1402 if !types.IsExported(name) && s.Pkg != w.currPkg {
1403 Fatalf("weird package in name: %v => %v, not %q", s, name, w.currPkg.Path)
1404 }
1405
1406 w.string(name)
1407 }
1408
1409 type intWriter struct {
1410 bytes.Buffer
1411 }
1412
1413 func (w *intWriter) int64(x int64) {
1414 var buf [binary.MaxVarintLen64]byte
1415 n := binary.PutVarint(buf[:], x)
1416 w.Write(buf[:n])
1417 }
1418
1419 func (w *intWriter) uint64(x uint64) {
1420 var buf [binary.MaxVarintLen64]byte
1421 n := binary.PutUvarint(buf[:], x)
1422 w.Write(buf[:n])
1423 }
1424
View as plain text