]> Cypherpunks repositories - gostls13.git/blob
5184753
[gostls13.git] /
1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Binary package import.
6 // Based loosely on x/tools/go/importer.
7
8 package gc
9
10 import (
11         "bufio"
12         "cmd/compile/internal/big"
13         "encoding/binary"
14         "fmt"
15 )
16
17 // The overall structure of Import is symmetric to Export: For each
18 // export method in bexport.go there is a matching and symmetric method
19 // in bimport.go. Changing the export format requires making symmetric
20 // changes to bimport.go and bexport.go.
21
22 type importer struct {
23         in  *bufio.Reader
24         buf []byte // reused for reading strings
25
26         // object lists, in order of deserialization
27         strList       []string
28         pkgList       []*Pkg
29         typList       []*Type
30         funcList      []*Node // nil entry means already declared
31         trackAllTypes bool
32
33         // for delayed type verification
34         cmpList []struct{ pt, t *Type }
35
36         // position encoding
37         posInfoFormat bool
38         prevFile      string
39         prevLine      int
40
41         // debugging support
42         debugFormat bool
43         read        int // bytes read
44 }
45
46 // Import populates importpkg from the serialized package data.
47 func Import(in *bufio.Reader) {
48         p := importer{
49                 in:      in,
50                 strList: []string{""}, // empty string is mapped to 0
51         }
52
53         // read low-level encoding format
54         switch format := p.rawByte(); format {
55         case 'c':
56                 // compact format - nothing to do
57         case 'd':
58                 p.debugFormat = true
59         default:
60                 Fatalf("importer: invalid encoding format in export data: got %q; want 'c' or 'd'", format)
61         }
62
63         p.trackAllTypes = p.rawByte() == 'a'
64
65         p.posInfoFormat = p.bool()
66
67         // --- generic export data ---
68
69         if v := p.string(); v != exportVersion {
70                 Fatalf("importer: unknown export data version: %s", v)
71         }
72
73         // populate typList with predeclared "known" types
74         p.typList = append(p.typList, predeclared()...)
75
76         // read package data
77         p.pkg()
78
79         // defer some type-checking until all types are read in completely
80         // (parser.go:import_package)
81         tcok := typecheckok
82         typecheckok = true
83         defercheckwidth()
84
85         // read objects
86
87         // phase 1
88         objcount := 0
89         for {
90                 tag := p.tagOrIndex()
91                 if tag == endTag {
92                         break
93                 }
94                 p.obj(tag)
95                 objcount++
96         }
97
98         // self-verification
99         if count := p.int(); count != objcount {
100                 Fatalf("importer: got %d objects; want %d", objcount, count)
101         }
102
103         // --- compiler-specific export data ---
104
105         // read compiler-specific flags
106         importpkg.Safe = p.bool()
107
108         // phase 2
109         objcount = 0
110         for {
111                 tag := p.tagOrIndex()
112                 if tag == endTag {
113                         break
114                 }
115                 p.obj(tag)
116                 objcount++
117         }
118
119         // self-verification
120         if count := p.int(); count != objcount {
121                 Fatalf("importer: got %d objects; want %d", objcount, count)
122         }
123
124         // read inlineable functions bodies
125         if dclcontext != PEXTERN {
126                 Fatalf("importer: unexpected context %d", dclcontext)
127         }
128
129         objcount = 0
130         for i0 := -1; ; {
131                 i := p.int() // index of function with inlineable body
132                 if i < 0 {
133                         break
134                 }
135
136                 // don't process the same function twice
137                 if i <= i0 {
138                         Fatalf("importer: index not increasing: %d <= %d", i, i0)
139                 }
140                 i0 = i
141
142                 if Funcdepth != 0 {
143                         Fatalf("importer: unexpected Funcdepth %d", Funcdepth)
144                 }
145
146                 // Note: In the original code, funchdr and funcbody are called for
147                 // all functions (that were not yet imported). Now, we are calling
148                 // them only for functions with inlineable bodies. funchdr does
149                 // parameter renaming which doesn't matter if we don't have a body.
150
151                 if f := p.funcList[i]; f != nil {
152                         // function not yet imported - read body and set it
153                         funchdr(f)
154                         body := p.stmtList()
155                         if body == nil {
156                                 // Make sure empty body is not interpreted as
157                                 // no inlineable body (see also parser.fnbody)
158                                 // (not doing so can cause significant performance
159                                 // degradation due to unnecessary calls to empty
160                                 // functions).
161                                 body = []*Node{Nod(OEMPTY, nil, nil)}
162                         }
163                         f.Func.Inl.Set(body)
164                         funcbody(f)
165                 } else {
166                         // function already imported - read body but discard declarations
167                         dclcontext = PDISCARD // throw away any declarations
168                         p.stmtList()
169                         dclcontext = PEXTERN
170                 }
171
172                 objcount++
173         }
174
175         // self-verification
176         if count := p.int(); count != objcount {
177                 Fatalf("importer: got %d functions; want %d", objcount, count)
178         }
179
180         if dclcontext != PEXTERN {
181                 Fatalf("importer: unexpected context %d", dclcontext)
182         }
183
184         p.verifyTypes()
185
186         // --- end of export data ---
187
188         typecheckok = tcok
189         resumecheckwidth()
190
191         testdclstack() // debugging only
192 }
193
194 func (p *importer) verifyTypes() {
195         for _, pair := range p.cmpList {
196                 pt := pair.pt
197                 t := pair.t
198                 if !Eqtype(pt.Orig, t) {
199                         // TODO(gri) Is this a possible regular error (stale files)
200                         // or can this only happen if export/import is flawed?
201                         // (if the latter, change to Fatalf here)
202                         Yyerror("inconsistent definition for type %v during import\n\t%v (in %q)\n\t%v (in %q)", pt.Sym, Tconv(pt, FmtLong), pt.Sym.Importdef.Path, Tconv(t, FmtLong), importpkg.Path)
203                 }
204         }
205 }
206
207 func (p *importer) pkg() *Pkg {
208         // if the package was seen before, i is its index (>= 0)
209         i := p.tagOrIndex()
210         if i >= 0 {
211                 return p.pkgList[i]
212         }
213
214         // otherwise, i is the package tag (< 0)
215         if i != packageTag {
216                 Fatalf("importer: expected package tag, found tag = %d", i)
217         }
218
219         // read package data
220         name := p.string()
221         path := p.string()
222
223         // we should never see an empty package name
224         if name == "" {
225                 Fatalf("importer: empty package name for path %q", path)
226         }
227
228         // we should never see a bad import path
229         if isbadimport(path) {
230                 Fatalf("importer: bad package path %q for package %s", path, name)
231         }
232
233         // an empty path denotes the package we are currently importing;
234         // it must be the first package we see
235         if (path == "") != (len(p.pkgList) == 0) {
236                 Fatalf("importer: package path %q for pkg index %d", path, len(p.pkgList))
237         }
238
239         pkg := importpkg
240         if path != "" {
241                 pkg = mkpkg(path)
242         }
243         if pkg.Name == "" {
244                 pkg.Name = name
245         } else if pkg.Name != name {
246                 Fatalf("importer: conflicting package names %s and %s for path %q", pkg.Name, name, path)
247         }
248         p.pkgList = append(p.pkgList, pkg)
249
250         return pkg
251 }
252
253 func idealType(typ *Type) *Type {
254         if typ.IsUntyped() {
255                 // canonicalize ideal types
256                 typ = Types[TIDEAL]
257         }
258         return typ
259 }
260
261 func (p *importer) obj(tag int) {
262         switch tag {
263         case constTag:
264                 p.pos()
265                 sym := p.qualifiedName()
266                 typ := p.typ()
267                 val := p.value(typ)
268                 importconst(sym, idealType(typ), nodlit(val))
269
270         case typeTag:
271                 p.typ()
272
273         case varTag:
274                 p.pos()
275                 sym := p.qualifiedName()
276                 typ := p.typ()
277                 importvar(sym, typ)
278
279         case funcTag:
280                 p.pos()
281                 sym := p.qualifiedName()
282                 params := p.paramList()
283                 result := p.paramList()
284
285                 sig := functype(nil, params, result)
286                 importsym(sym, ONAME)
287                 if sym.Def != nil && sym.Def.Op == ONAME {
288                         // function was imported before (via another import)
289                         if !Eqtype(sig, sym.Def.Type) {
290                                 Fatalf("importer: inconsistent definition for func %v during import\n\t%v\n\t%v", sym, sym.Def.Type, sig)
291                         }
292                         p.funcList = append(p.funcList, nil)
293                         break
294                 }
295
296                 n := newfuncname(sym)
297                 n.Type = sig
298                 declare(n, PFUNC)
299                 p.funcList = append(p.funcList, n)
300                 importlist = append(importlist, n)
301
302                 if Debug['E'] > 0 {
303                         fmt.Printf("import [%q] func %v \n", importpkg.Path, n)
304                         if Debug['m'] > 2 && n.Func.Inl.Len() != 0 {
305                                 fmt.Printf("inl body: %v\n", n.Func.Inl)
306                         }
307                 }
308
309         default:
310                 Fatalf("importer: unexpected object (tag = %d)", tag)
311         }
312 }
313
314 func (p *importer) pos() {
315         if !p.posInfoFormat {
316                 return
317         }
318
319         file := p.prevFile
320         line := p.prevLine
321         if delta := p.int(); delta != 0 {
322                 // line changed
323                 line += delta
324         } else if n := p.int(); n >= 0 {
325                 // file changed
326                 file = p.prevFile[:n] + p.string()
327                 p.prevFile = file
328                 line = p.int()
329         }
330         p.prevLine = line
331
332         // TODO(gri) register new position
333 }
334
335 func (p *importer) newtyp(etype EType) *Type {
336         t := typ(etype)
337         if p.trackAllTypes {
338                 p.typList = append(p.typList, t)
339         }
340         return t
341 }
342
343 // This is like the function importtype but it delays the
344 // type identity check for types that have been seen already.
345 // importer.importtype and importtype and (export.go) need to
346 // remain in sync.
347 func (p *importer) importtype(pt, t *Type) {
348         // override declaration in unsafe.go for Pointer.
349         // there is no way in Go code to define unsafe.Pointer
350         // so we have to supply it.
351         if incannedimport != 0 && importpkg.Name == "unsafe" && pt.Nod.Sym.Name == "Pointer" {
352                 t = Types[TUNSAFEPTR]
353         }
354
355         if pt.Etype == TFORW {
356                 n := pt.Nod
357                 copytype(pt.Nod, t)
358                 pt.Nod = n // unzero nod
359                 pt.Sym.Importdef = importpkg
360                 pt.Sym.Lastlineno = lineno
361                 declare(n, PEXTERN)
362                 checkwidth(pt)
363         } else {
364                 // pt.Orig and t must be identical. Since t may not be
365                 // fully set up yet, collect the types and verify identity
366                 // later.
367                 p.cmpList = append(p.cmpList, struct{ pt, t *Type }{pt, t})
368         }
369
370         if Debug['E'] != 0 {
371                 fmt.Printf("import type %v %v\n", pt, Tconv(t, FmtLong))
372         }
373 }
374
375 func (p *importer) typ() *Type {
376         // if the type was seen before, i is its index (>= 0)
377         i := p.tagOrIndex()
378         if i >= 0 {
379                 return p.typList[i]
380         }
381
382         // otherwise, i is the type tag (< 0)
383         var t *Type
384         switch i {
385         case namedTag:
386                 // parser.go:hidden_importsym
387                 p.pos()
388                 tsym := p.qualifiedName()
389
390                 // parser.go:hidden_pkgtype
391                 t = pkgtype(tsym)
392                 p.typList = append(p.typList, t)
393
394                 // read underlying type
395                 // parser.go:hidden_type
396                 t0 := p.typ()
397                 if p.trackAllTypes {
398                         // If we track all types, we cannot check equality of previously
399                         // imported types until later. Use customized version of importtype.
400                         p.importtype(t, t0)
401                 } else {
402                         importtype(t, t0)
403                 }
404
405                 // interfaces don't have associated methods
406                 if t0.IsInterface() {
407                         break
408                 }
409
410                 // set correct import context (since p.typ() may be called
411                 // while importing the body of an inlined function)
412                 savedContext := dclcontext
413                 dclcontext = PEXTERN
414
415                 // read associated methods
416                 for i := p.int(); i > 0; i-- {
417                         // parser.go:hidden_fndcl
418
419                         p.pos()
420                         sym := p.fieldSym()
421
422                         recv := p.paramList() // TODO(gri) do we need a full param list for the receiver?
423                         params := p.paramList()
424                         result := p.paramList()
425
426                         n := methodname1(newname(sym), recv[0].Right)
427                         n.Type = functype(recv[0], params, result)
428                         checkwidth(n.Type)
429                         addmethod(sym, n.Type, tsym.Pkg, false, false)
430                         p.funcList = append(p.funcList, n)
431                         importlist = append(importlist, n)
432
433                         // (comment from parser.go)
434                         // inl.C's inlnode in on a dotmeth node expects to find the inlineable body as
435                         // (dotmeth's type).Nname.Inl, and dotmeth's type has been pulled
436                         // out by typecheck's lookdot as this $$.ttype. So by providing
437                         // this back link here we avoid special casing there.
438                         n.Type.SetNname(n)
439
440                         if Debug['E'] > 0 {
441                                 fmt.Printf("import [%q] meth %v \n", importpkg.Path, n)
442                                 if Debug['m'] > 2 && n.Func.Inl.Len() != 0 {
443                                         fmt.Printf("inl body: %v\n", n.Func.Inl)
444                                 }
445                         }
446                 }
447
448                 dclcontext = savedContext
449
450         case arrayTag:
451                 t = p.newtyp(TARRAY)
452                 bound := p.int64()
453                 elem := p.typ()
454                 t.Extra = &ArrayType{Elem: elem, Bound: bound}
455
456         case sliceTag:
457                 t = p.newtyp(TSLICE)
458                 elem := p.typ()
459                 t.Extra = SliceType{Elem: elem}
460
461         case dddTag:
462                 t = p.newtyp(TDDDFIELD)
463                 t.Extra = DDDFieldType{T: p.typ()}
464
465         case structTag:
466                 t = p.newtyp(TSTRUCT)
467                 tostruct0(t, p.fieldList())
468
469         case pointerTag:
470                 t = p.newtyp(Tptr)
471                 t.Extra = PtrType{Elem: p.typ()}
472
473         case signatureTag:
474                 t = p.newtyp(TFUNC)
475                 params := p.paramList()
476                 result := p.paramList()
477                 functype0(t, nil, params, result)
478
479         case interfaceTag:
480                 t = p.newtyp(TINTER)
481                 if p.int() != 0 {
482                         Fatalf("importer: unexpected embedded interface")
483                 }
484                 tointerface0(t, p.methodList())
485
486         case mapTag:
487                 t = p.newtyp(TMAP)
488                 mt := t.MapType()
489                 mt.Key = p.typ()
490                 mt.Val = p.typ()
491
492         case chanTag:
493                 t = p.newtyp(TCHAN)
494                 ct := t.ChanType()
495                 ct.Dir = ChanDir(p.int())
496                 ct.Elem = p.typ()
497
498         default:
499                 Fatalf("importer: unexpected type (tag = %d)", i)
500         }
501
502         if t == nil {
503                 Fatalf("importer: nil type (type tag = %d)", i)
504         }
505
506         return t
507 }
508
509 func (p *importer) qualifiedName() *Sym {
510         name := p.string()
511         pkg := p.pkg()
512         return pkg.Lookup(name)
513 }
514
515 // parser.go:hidden_structdcl_list
516 func (p *importer) fieldList() (fields []*Node) {
517         if n := p.int(); n > 0 {
518                 fields = make([]*Node, n)
519                 for i := range fields {
520                         fields[i] = p.field()
521                 }
522         }
523         return
524 }
525
526 // parser.go:hidden_structdcl
527 func (p *importer) field() *Node {
528         p.pos()
529         sym := p.fieldName()
530         typ := p.typ()
531         note := p.string()
532
533         var n *Node
534         if sym.Name != "" {
535                 n = Nod(ODCLFIELD, newname(sym), typenod(typ))
536         } else {
537                 // anonymous field - typ must be T or *T and T must be a type name
538                 s := typ.Sym
539                 if s == nil && typ.IsPtr() {
540                         s = typ.Elem().Sym // deref
541                 }
542                 pkg := importpkg
543                 if sym != nil {
544                         pkg = sym.Pkg
545                 }
546                 n = embedded(s, pkg)
547                 n.Right = typenod(typ)
548         }
549         n.SetVal(Val{U: note})
550
551         return n
552 }
553
554 // parser.go:hidden_interfacedcl_list
555 func (p *importer) methodList() (methods []*Node) {
556         if n := p.int(); n > 0 {
557                 methods = make([]*Node, n)
558                 for i := range methods {
559                         methods[i] = p.method()
560                 }
561         }
562         return
563 }
564
565 // parser.go:hidden_interfacedcl
566 func (p *importer) method() *Node {
567         p.pos()
568         sym := p.fieldName()
569         params := p.paramList()
570         result := p.paramList()
571         return Nod(ODCLFIELD, newname(sym), typenod(functype(fakethis(), params, result)))
572 }
573
574 // parser.go:sym,hidden_importsym
575 func (p *importer) fieldName() *Sym {
576         name := p.string()
577         pkg := localpkg
578         if name == "_" {
579                 // During imports, unqualified non-exported identifiers are from builtinpkg
580                 // (see parser.go:sym). The binary exporter only exports blank as a non-exported
581                 // identifier without qualification.
582                 pkg = builtinpkg
583         } else if name == "?" || name != "" && !exportname(name) {
584                 if name == "?" {
585                         name = ""
586                 }
587                 pkg = p.pkg()
588         }
589         return pkg.Lookup(name)
590 }
591
592 // parser.go:ohidden_funarg_list
593 func (p *importer) paramList() []*Node {
594         i := p.int()
595         if i == 0 {
596                 return nil
597         }
598         // negative length indicates unnamed parameters
599         named := true
600         if i < 0 {
601                 i = -i
602                 named = false
603         }
604         // i > 0
605         n := make([]*Node, i)
606         for i := range n {
607                 n[i] = p.param(named)
608         }
609         return n
610 }
611
612 // parser.go:hidden_funarg
613 func (p *importer) param(named bool) *Node {
614         typ := p.typ()
615
616         isddd := false
617         if typ.Etype == TDDDFIELD {
618                 // TDDDFIELD indicates wrapped ... slice type
619                 typ = typSlice(typ.DDDField())
620                 isddd = true
621         }
622
623         n := Nod(ODCLFIELD, nil, typenod(typ))
624         n.Isddd = isddd
625
626         if named {
627                 name := p.string()
628                 if name == "" {
629                         Fatalf("importer: expected named parameter")
630                 }
631                 // TODO(gri) Supply function/method package rather than
632                 // encoding the package for each parameter repeatedly.
633                 pkg := localpkg
634                 if name != "_" {
635                         pkg = p.pkg()
636                 }
637                 n.Left = newname(pkg.Lookup(name))
638         }
639
640         // TODO(gri) This is compiler-specific (escape info).
641         // Move into compiler-specific section eventually?
642         n.SetVal(Val{U: p.string()})
643
644         return n
645 }
646
647 func (p *importer) value(typ *Type) (x Val) {
648         switch tag := p.tagOrIndex(); tag {
649         case falseTag:
650                 x.U = false
651
652         case trueTag:
653                 x.U = true
654
655         case int64Tag:
656                 u := new(Mpint)
657                 u.SetInt64(p.int64())
658                 u.Rune = typ == idealrune
659                 x.U = u
660
661         case floatTag:
662                 f := newMpflt()
663                 p.float(f)
664                 if typ == idealint || typ.IsInteger() {
665                         // uncommon case: large int encoded as float
666                         u := new(Mpint)
667                         u.SetFloat(f)
668                         x.U = u
669                         break
670                 }
671                 x.U = f
672
673         case complexTag:
674                 u := new(Mpcplx)
675                 p.float(&u.Real)
676                 p.float(&u.Imag)
677                 x.U = u
678
679         case stringTag:
680                 x.U = p.string()
681
682         case unknownTag:
683                 Fatalf("importer: unknown constant (importing package with errors)")
684
685         case nilTag:
686                 x.U = new(NilVal)
687
688         default:
689                 Fatalf("importer: unexpected value tag %d", tag)
690         }
691
692         // verify ideal type
693         if typ.IsUntyped() && untype(x.Ctype()) != typ {
694                 Fatalf("importer: value %v and type %v don't match", x, typ)
695         }
696
697         return
698 }
699
700 func (p *importer) float(x *Mpflt) {
701         sign := p.int()
702         if sign == 0 {
703                 x.SetFloat64(0)
704                 return
705         }
706
707         exp := p.int()
708         mant := new(big.Int).SetBytes([]byte(p.string()))
709
710         m := x.Val.SetInt(mant)
711         m.SetMantExp(m, exp-mant.BitLen())
712         if sign < 0 {
713                 m.Neg(m)
714         }
715 }
716
717 // ----------------------------------------------------------------------------
718 // Inlined function bodies
719
720 // Approach: Read nodes and use them to create/declare the same data structures
721 // as done originally by the (hidden) parser by closely following the parser's
722 // original code. In other words, "parsing" the import data (which happens to
723 // be encoded in binary rather textual form) is the best way at the moment to
724 // re-establish the syntax tree's invariants. At some future point we might be
725 // able to avoid this round-about way and create the rewritten nodes directly,
726 // possibly avoiding a lot of duplicate work (name resolution, type checking).
727 //
728 // Refined nodes (e.g., ODOTPTR as a refinement of OXDOT) are exported as their
729 // unrefined nodes (since this is what the importer uses). The respective case
730 // entries are unreachable in the importer.
731
732 func (p *importer) stmtList() []*Node {
733         var list []*Node
734         for {
735                 n := p.node()
736                 if n == nil {
737                         break
738                 }
739                 // OBLOCK nodes may be created when importing ODCL nodes - unpack them
740                 if n.Op == OBLOCK {
741                         list = append(list, n.List.Slice()...)
742                 } else {
743                         list = append(list, n)
744                 }
745         }
746         return list
747 }
748
749 func (p *importer) exprList() []*Node {
750         var list []*Node
751         for {
752                 n := p.expr()
753                 if n == nil {
754                         break
755                 }
756                 list = append(list, n)
757         }
758         return list
759 }
760
761 func (p *importer) elemList() []*Node {
762         c := p.int()
763         list := make([]*Node, c)
764         for i := range list {
765                 list[i] = Nod(OKEY, mkname(p.fieldSym()), p.expr())
766         }
767         return list
768 }
769
770 func (p *importer) expr() *Node {
771         n := p.node()
772         if n != nil && n.Op == OBLOCK {
773                 Fatalf("unexpected block node: %v", n)
774         }
775         return n
776 }
777
778 // TODO(gri) split into expr and stmt
779 func (p *importer) node() *Node {
780         switch op := p.op(); op {
781         // expressions
782         // case OPAREN:
783         //      unreachable - unpacked by exporter
784
785         // case ODDDARG:
786         //      unimplemented
787
788         // case OREGISTER:
789         //      unimplemented
790
791         case OLITERAL:
792                 typ := p.typ()
793                 n := nodlit(p.value(typ))
794                 if !typ.IsUntyped() {
795                         conv := Nod(OCALL, typenod(typ), nil)
796                         conv.List.Set1(n)
797                         n = conv
798                 }
799                 return n
800
801         case ONAME:
802                 return mkname(p.sym())
803
804         // case OPACK, ONONAME:
805         //      unreachable - should have been resolved by typechecking
806
807         case OTYPE:
808                 if p.bool() {
809                         return mkname(p.sym())
810                 }
811                 return typenod(p.typ())
812
813         // case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
814         //      unreachable - should have been resolved by typechecking
815
816         // case OCLOSURE:
817         //      unimplemented
818
819         case OPTRLIT:
820                 n := p.expr()
821                 if !p.bool() /* !implicit, i.e. '&' operator */ {
822                         if n.Op == OCOMPLIT {
823                                 // Special case for &T{...}: turn into (*T){...}.
824                                 n.Right = Nod(OIND, n.Right, nil)
825                                 n.Right.Implicit = true
826                         } else {
827                                 n = Nod(OADDR, n, nil)
828                         }
829                 }
830                 return n
831
832         case OSTRUCTLIT:
833                 n := Nod(OCOMPLIT, nil, typenod(p.typ()))
834                 n.List.Set(p.elemList()) // special handling of field names
835                 return n
836
837         // case OARRAYLIT, OMAPLIT:
838         //      unreachable - mapped to case OCOMPLIT below by exporter
839
840         case OCOMPLIT:
841                 n := Nod(OCOMPLIT, nil, typenod(p.typ()))
842                 n.List.Set(p.exprList())
843                 return n
844
845         case OKEY:
846                 left, right := p.exprsOrNil()
847                 return Nod(OKEY, left, right)
848
849         // case OCALLPART:
850         //      unimplemented
851
852         // case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
853         //      unreachable - mapped to case OXDOT below by exporter
854
855         case OXDOT:
856                 // see parser.new_dotname
857                 return NodSym(OXDOT, p.expr(), p.fieldSym())
858
859         // case ODOTTYPE, ODOTTYPE2:
860         //      unreachable - mapped to case ODOTTYPE below by exporter
861
862         case ODOTTYPE:
863                 n := Nod(ODOTTYPE, p.expr(), nil)
864                 if p.bool() {
865                         n.Right = p.expr()
866                 } else {
867                         n.Right = typenod(p.typ())
868                 }
869                 return n
870
871         // case OINDEX, OINDEXMAP, OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR:
872         //      unreachable - mapped to cases below by exporter
873
874         case OINDEX:
875                 return Nod(op, p.expr(), p.expr())
876
877         case OSLICE, OSLICE3:
878                 n := Nod(op, p.expr(), nil)
879                 low, high := p.exprsOrNil()
880                 var max *Node
881                 if n.Op.IsSlice3() {
882                         max = p.expr()
883                 }
884                 n.SetSliceBounds(low, high, max)
885                 return n
886
887         // case OCONV, OCONVIFACE, OCONVNOP, OARRAYBYTESTR, OARRAYRUNESTR, OSTRARRAYBYTE, OSTRARRAYRUNE, ORUNESTR:
888         //      unreachable - mapped to OCONV case below by exporter
889
890         case OCONV:
891                 n := Nod(OCALL, typenod(p.typ()), nil)
892                 n.List.Set(p.exprList())
893                 return n
894
895         case OCOPY, OCOMPLEX, OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN:
896                 n := builtinCall(op)
897                 n.List.Set(p.exprList())
898                 if op == OAPPEND {
899                         n.Isddd = p.bool()
900                 }
901                 return n
902
903         // case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG:
904         //      unreachable - mapped to OCALL case below by exporter
905
906         case OCALL:
907                 n := Nod(OCALL, p.expr(), nil)
908                 n.List.Set(p.exprList())
909                 n.Isddd = p.bool()
910                 return n
911
912         case OMAKEMAP, OMAKECHAN, OMAKESLICE:
913                 n := builtinCall(OMAKE)
914                 n.List.Append(typenod(p.typ()))
915                 n.List.Append(p.exprList()...)
916                 return n
917
918         // unary expressions
919         case OPLUS, OMINUS, OADDR, OCOM, OIND, ONOT, ORECV:
920                 return Nod(op, p.expr(), nil)
921
922         // binary expressions
923         case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, OLT,
924                 OLSH, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSEND, OSUB, OXOR:
925                 return Nod(op, p.expr(), p.expr())
926
927         case OADDSTR:
928                 list := p.exprList()
929                 x := list[0]
930                 for _, y := range list[1:] {
931                         x = Nod(OADD, x, y)
932                 }
933                 return x
934
935         // case OCMPSTR, OCMPIFACE:
936         //      unreachable - mapped to std comparison operators by exporter
937
938         case ODCLCONST:
939                 // TODO(gri) these should not be exported in the first place
940                 return Nod(OEMPTY, nil, nil)
941
942         // --------------------------------------------------------------------
943         // statements
944         case ODCL:
945                 var lhs *Node
946                 if p.bool() {
947                         lhs = p.expr()
948                 } else {
949                         lhs = dclname(p.sym())
950                 }
951                 // TODO(gri) avoid list created here!
952                 return liststmt(variter([]*Node{lhs}, typenod(p.typ()), nil))
953
954         // case ODCLFIELD:
955         //      unimplemented
956
957         // case OAS, OASWB:
958         //      unreachable - mapped to OAS case below by exporter
959
960         case OAS:
961                 return Nod(OAS, p.expr(), p.expr())
962
963         case OASOP:
964                 n := Nod(OASOP, nil, nil)
965                 n.Etype = EType(p.int())
966                 n.Left = p.expr()
967                 if !p.bool() {
968                         n.Right = Nodintconst(1)
969                         n.Implicit = true
970                 } else {
971                         n.Right = p.expr()
972                 }
973                 return n
974
975         // case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
976         //      unreachable - mapped to OAS2 case below by exporter
977
978         case OAS2:
979                 n := Nod(OAS2, nil, nil)
980                 n.List.Set(p.exprList())
981                 n.Rlist.Set(p.exprList())
982                 return n
983
984         case ORETURN:
985                 n := Nod(ORETURN, nil, nil)
986                 n.List.Set(p.exprList())
987                 return n
988
989         // case ORETJMP:
990         //      unreachable - generated by compiler for trampolin routines (not exported)
991
992         case OPROC, ODEFER:
993                 return Nod(op, p.expr(), nil)
994
995         case OIF:
996                 markdcl()
997                 n := Nod(OIF, nil, nil)
998                 n.Ninit.Set(p.stmtList())
999                 n.Left = p.expr()
1000                 n.Nbody.Set(p.stmtList())
1001                 n.Rlist.Set(p.stmtList())
1002                 popdcl()
1003                 return n
1004
1005         case OFOR:
1006                 markdcl()
1007                 n := Nod(OFOR, nil, nil)
1008                 n.Ninit.Set(p.stmtList())
1009                 n.Left, n.Right = p.exprsOrNil()
1010                 n.Nbody.Set(p.stmtList())
1011                 popdcl()
1012                 return n
1013
1014         case ORANGE:
1015                 markdcl()
1016                 n := Nod(ORANGE, nil, nil)
1017                 n.List.Set(p.stmtList())
1018                 n.Right = p.expr()
1019                 n.Nbody.Set(p.stmtList())
1020                 popdcl()
1021                 return n
1022
1023         case OSELECT, OSWITCH:
1024                 markdcl()
1025                 n := Nod(op, nil, nil)
1026                 n.Ninit.Set(p.stmtList())
1027                 n.Left, _ = p.exprsOrNil()
1028                 n.List.Set(p.stmtList())
1029                 popdcl()
1030                 return n
1031
1032         // case OCASE, OXCASE:
1033         //      unreachable - mapped to OXCASE case below by exporter
1034
1035         case OXCASE:
1036                 markdcl()
1037                 n := Nod(OXCASE, nil, nil)
1038                 n.List.Set(p.exprList())
1039                 // TODO(gri) eventually we must declare variables for type switch
1040                 // statements (type switch statements are not yet exported)
1041                 n.Nbody.Set(p.stmtList())
1042                 popdcl()
1043                 return n
1044
1045         // case OFALL:
1046         //      unreachable - mapped to OXFALL case below by exporter
1047
1048         case OBREAK, OCONTINUE, OGOTO, OXFALL:
1049                 left, _ := p.exprsOrNil()
1050                 return Nod(op, left, nil)
1051
1052         // case OEMPTY:
1053         //      unreachable - not emitted by exporter
1054
1055         case OLABEL:
1056                 n := Nod(OLABEL, p.expr(), nil)
1057                 n.Left.Sym = dclstack // context, for goto restrictions
1058                 return n
1059
1060         case OEND:
1061                 return nil
1062
1063         default:
1064                 Fatalf("cannot import %s (%d) node\n"+
1065                         "==> please file an issue and assign to gri@\n", op, op)
1066                 panic("unreachable") // satisfy compiler
1067         }
1068 }
1069
1070 func builtinCall(op Op) *Node {
1071         return Nod(OCALL, mkname(builtinpkg.Lookup(goopnames[op])), nil)
1072 }
1073
1074 func (p *importer) exprsOrNil() (a, b *Node) {
1075         ab := p.int()
1076         if ab&1 != 0 {
1077                 a = p.expr()
1078         }
1079         if ab&2 != 0 {
1080                 b = p.expr()
1081         }
1082         return
1083 }
1084
1085 func (p *importer) fieldSym() *Sym {
1086         name := p.string()
1087         pkg := localpkg
1088         if !exportname(name) {
1089                 pkg = p.pkg()
1090         }
1091         return pkg.Lookup(name)
1092 }
1093
1094 func (p *importer) sym() *Sym {
1095         name := p.string()
1096         pkg := localpkg
1097         if name != "_" {
1098                 pkg = p.pkg()
1099         }
1100         return pkg.Lookup(name)
1101 }
1102
1103 func (p *importer) bool() bool {
1104         return p.int() != 0
1105 }
1106
1107 func (p *importer) op() Op {
1108         return Op(p.int())
1109 }
1110
1111 // ----------------------------------------------------------------------------
1112 // Low-level decoders
1113
1114 func (p *importer) tagOrIndex() int {
1115         if p.debugFormat {
1116                 p.marker('t')
1117         }
1118
1119         return int(p.rawInt64())
1120 }
1121
1122 func (p *importer) int() int {
1123         x := p.int64()
1124         if int64(int(x)) != x {
1125                 Fatalf("importer: exported integer too large")
1126         }
1127         return int(x)
1128 }
1129
1130 func (p *importer) int64() int64 {
1131         if p.debugFormat {
1132                 p.marker('i')
1133         }
1134
1135         return p.rawInt64()
1136 }
1137
1138 func (p *importer) string() string {
1139         if p.debugFormat {
1140                 p.marker('s')
1141         }
1142         // if the string was seen before, i is its index (>= 0)
1143         // (the empty string is at index 0)
1144         i := p.rawInt64()
1145         if i >= 0 {
1146                 return p.strList[i]
1147         }
1148         // otherwise, i is the negative string length (< 0)
1149         if n := int(-i); n <= cap(p.buf) {
1150                 p.buf = p.buf[:n]
1151         } else {
1152                 p.buf = make([]byte, n)
1153         }
1154         for i := range p.buf {
1155                 p.buf[i] = p.rawByte()
1156         }
1157         s := string(p.buf)
1158         p.strList = append(p.strList, s)
1159         return s
1160 }
1161
1162 func (p *importer) marker(want byte) {
1163         if got := p.rawByte(); got != want {
1164                 Fatalf("importer: incorrect marker: got %c; want %c (pos = %d)", got, want, p.read)
1165         }
1166
1167         pos := p.read
1168         if n := int(p.rawInt64()); n != pos {
1169                 Fatalf("importer: incorrect position: got %d; want %d", n, pos)
1170         }
1171 }
1172
1173 // rawInt64 should only be used by low-level decoders
1174 func (p *importer) rawInt64() int64 {
1175         i, err := binary.ReadVarint(p)
1176         if err != nil {
1177                 Fatalf("importer: read error: %v", err)
1178         }
1179         return i
1180 }
1181
1182 // needed for binary.ReadVarint in rawInt64
1183 func (p *importer) ReadByte() (byte, error) {
1184         return p.rawByte(), nil
1185 }
1186
1187 // rawByte is the bottleneck interface for reading from p.in.
1188 // It unescapes '|' 'S' to '$' and '|' '|' to '|'.
1189 // rawByte should only be used by low-level decoders.
1190 func (p *importer) rawByte() byte {
1191         c, err := p.in.ReadByte()
1192         p.read++
1193         if err != nil {
1194                 Fatalf("importer: read error: %v", err)
1195         }
1196         if c == '|' {
1197                 c, err = p.in.ReadByte()
1198                 p.read++
1199                 if err != nil {
1200                         Fatalf("importer: read error: %v", err)
1201                 }
1202                 switch c {
1203                 case 'S':
1204                         c = '$'
1205                 case '|':
1206                         // nothing to do
1207                 default:
1208                         Fatalf("importer: unexpected escape sequence in export data")
1209                 }
1210         }
1211         return c
1212 }