...

Source file src/pkg/cmd/compile/internal/gc/iimport.go

     1	// Copyright 2018 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	// Indexed package import.
     6	// See iexport.go for the export data format.
     7	
     8	package gc
     9	
    10	import (
    11		"cmd/compile/internal/types"
    12		"cmd/internal/bio"
    13		"cmd/internal/src"
    14		"encoding/binary"
    15		"fmt"
    16		"math/big"
    17		"os"
    18		"strings"
    19	)
    20	
    21	// An iimporterAndOffset identifies an importer and an offset within
    22	// its data section.
    23	type iimporterAndOffset struct {
    24		p   *iimporter
    25		off uint64
    26	}
    27	
    28	var (
    29		// declImporter maps from imported identifiers to an importer
    30		// and offset where that identifier's declaration can be read.
    31		declImporter = map[*types.Sym]iimporterAndOffset{}
    32	
    33		// inlineImporter is like declImporter, but for inline bodies
    34		// for function and method symbols.
    35		inlineImporter = map[*types.Sym]iimporterAndOffset{}
    36	)
    37	
    38	func expandDecl(n *Node) {
    39		if n.Op != ONONAME {
    40			return
    41		}
    42	
    43		r := importReaderFor(n, declImporter)
    44		if r == nil {
    45			// Can happen if user tries to reference an undeclared name.
    46			return
    47		}
    48	
    49		r.doDecl(n)
    50	}
    51	
    52	func expandInline(fn *Node) {
    53		if fn.Func.Inl.Body != nil {
    54			return
    55		}
    56	
    57		r := importReaderFor(fn, inlineImporter)
    58		if r == nil {
    59			Fatalf("missing import reader for %v", fn)
    60		}
    61	
    62		r.doInline(fn)
    63	}
    64	
    65	func importReaderFor(n *Node, importers map[*types.Sym]iimporterAndOffset) *importReader {
    66		x, ok := importers[n.Sym]
    67		if !ok {
    68			return nil
    69		}
    70	
    71		return x.p.newReader(x.off, n.Sym.Pkg)
    72	}
    73	
    74	type intReader struct {
    75		*bio.Reader
    76		pkg *types.Pkg
    77	}
    78	
    79	func (r *intReader) int64() int64 {
    80		i, err := binary.ReadVarint(r.Reader)
    81		if err != nil {
    82			yyerror("import %q: read error: %v", r.pkg.Path, err)
    83			errorexit()
    84		}
    85		return i
    86	}
    87	
    88	func (r *intReader) uint64() uint64 {
    89		i, err := binary.ReadUvarint(r.Reader)
    90		if err != nil {
    91			yyerror("import %q: read error: %v", r.pkg.Path, err)
    92			errorexit()
    93		}
    94		return i
    95	}
    96	
    97	func iimport(pkg *types.Pkg, in *bio.Reader) {
    98		ir := &intReader{in, pkg}
    99	
   100		version := ir.uint64()
   101		if version != iexportVersion {
   102			yyerror("import %q: unknown export format version %d", pkg.Path, version)
   103			errorexit()
   104		}
   105	
   106		sLen := ir.uint64()
   107		dLen := ir.uint64()
   108	
   109		// Map string (and data) section into memory as a single large
   110		// string. This reduces heap fragmentation and allows
   111		// returning individual substrings very efficiently.
   112		data, err := mapFile(in.File(), in.Offset(), int64(sLen+dLen))
   113		if err != nil {
   114			yyerror("import %q: mapping input: %v", pkg.Path, err)
   115			errorexit()
   116		}
   117		stringData := data[:sLen]
   118		declData := data[sLen:]
   119	
   120		in.MustSeek(int64(sLen+dLen), os.SEEK_CUR)
   121	
   122		p := &iimporter{
   123			ipkg: pkg,
   124	
   125			pkgCache:     map[uint64]*types.Pkg{},
   126			posBaseCache: map[uint64]*src.PosBase{},
   127			typCache:     map[uint64]*types.Type{},
   128	
   129			stringData: stringData,
   130			declData:   declData,
   131		}
   132	
   133		for i, pt := range predeclared() {
   134			p.typCache[uint64(i)] = pt
   135		}
   136	
   137		// Declaration index.
   138		for nPkgs := ir.uint64(); nPkgs > 0; nPkgs-- {
   139			pkg := p.pkgAt(ir.uint64())
   140			pkgName := p.stringAt(ir.uint64())
   141			pkgHeight := int(ir.uint64())
   142			if pkg.Name == "" {
   143				pkg.Name = pkgName
   144				pkg.Height = pkgHeight
   145				numImport[pkgName]++
   146	
   147				// TODO(mdempsky): This belongs somewhere else.
   148				pkg.Lookup("_").Def = asTypesNode(nblank)
   149			} else {
   150				if pkg.Name != pkgName {
   151					Fatalf("conflicting package names %v and %v for path %q", pkg.Name, pkgName, pkg.Path)
   152				}
   153				if pkg.Height != pkgHeight {
   154					Fatalf("conflicting package heights %v and %v for path %q", pkg.Height, pkgHeight, pkg.Path)
   155				}
   156			}
   157	
   158			for nSyms := ir.uint64(); nSyms > 0; nSyms-- {
   159				s := pkg.Lookup(p.stringAt(ir.uint64()))
   160				off := ir.uint64()
   161	
   162				if _, ok := declImporter[s]; ok {
   163					continue
   164				}
   165				declImporter[s] = iimporterAndOffset{p, off}
   166	
   167				// Create stub declaration. If used, this will
   168				// be overwritten by expandDecl.
   169				if s.Def != nil {
   170					Fatalf("unexpected definition for %v: %v", s, asNode(s.Def))
   171				}
   172				s.Def = asTypesNode(npos(src.NoXPos, dclname(s)))
   173			}
   174		}
   175	
   176		// Inline body index.
   177		for nPkgs := ir.uint64(); nPkgs > 0; nPkgs-- {
   178			pkg := p.pkgAt(ir.uint64())
   179	
   180			for nSyms := ir.uint64(); nSyms > 0; nSyms-- {
   181				s := pkg.Lookup(p.stringAt(ir.uint64()))
   182				off := ir.uint64()
   183	
   184				if _, ok := inlineImporter[s]; ok {
   185					continue
   186				}
   187				inlineImporter[s] = iimporterAndOffset{p, off}
   188			}
   189		}
   190	}
   191	
   192	type iimporter struct {
   193		ipkg *types.Pkg
   194	
   195		pkgCache     map[uint64]*types.Pkg
   196		posBaseCache map[uint64]*src.PosBase
   197		typCache     map[uint64]*types.Type
   198	
   199		stringData string
   200		declData   string
   201	}
   202	
   203	func (p *iimporter) stringAt(off uint64) string {
   204		var x [binary.MaxVarintLen64]byte
   205		n := copy(x[:], p.stringData[off:])
   206	
   207		slen, n := binary.Uvarint(x[:n])
   208		if n <= 0 {
   209			Fatalf("varint failed")
   210		}
   211		spos := off + uint64(n)
   212		return p.stringData[spos : spos+slen]
   213	}
   214	
   215	func (p *iimporter) posBaseAt(off uint64) *src.PosBase {
   216		if posBase, ok := p.posBaseCache[off]; ok {
   217			return posBase
   218		}
   219	
   220		file := p.stringAt(off)
   221		posBase := src.NewFileBase(file, file)
   222		p.posBaseCache[off] = posBase
   223		return posBase
   224	}
   225	
   226	func (p *iimporter) pkgAt(off uint64) *types.Pkg {
   227		if pkg, ok := p.pkgCache[off]; ok {
   228			return pkg
   229		}
   230	
   231		pkg := p.ipkg
   232		if pkgPath := p.stringAt(off); pkgPath != "" {
   233			pkg = types.NewPkg(pkgPath, "")
   234		}
   235		p.pkgCache[off] = pkg
   236		return pkg
   237	}
   238	
   239	// An importReader keeps state for reading an individual imported
   240	// object (declaration or inline body).
   241	type importReader struct {
   242		strings.Reader
   243		p *iimporter
   244	
   245		currPkg  *types.Pkg
   246		prevBase *src.PosBase
   247		prevLine int64
   248	}
   249	
   250	func (p *iimporter) newReader(off uint64, pkg *types.Pkg) *importReader {
   251		r := &importReader{
   252			p:       p,
   253			currPkg: pkg,
   254		}
   255		// (*strings.Reader).Reset wasn't added until Go 1.7, and we
   256		// need to build with Go 1.4.
   257		r.Reader = *strings.NewReader(p.declData[off:])
   258		return r
   259	}
   260	
   261	func (r *importReader) string() string        { return r.p.stringAt(r.uint64()) }
   262	func (r *importReader) posBase() *src.PosBase { return r.p.posBaseAt(r.uint64()) }
   263	func (r *importReader) pkg() *types.Pkg       { return r.p.pkgAt(r.uint64()) }
   264	
   265	func (r *importReader) setPkg() {
   266		r.currPkg = r.pkg()
   267	}
   268	
   269	func (r *importReader) doDecl(n *Node) {
   270		if n.Op != ONONAME {
   271			Fatalf("doDecl: unexpected Op for %v: %v", n.Sym, n.Op)
   272		}
   273	
   274		tag := r.byte()
   275		pos := r.pos()
   276	
   277		switch tag {
   278		case 'A':
   279			typ := r.typ()
   280	
   281			importalias(r.p.ipkg, pos, n.Sym, typ)
   282	
   283		case 'C':
   284			typ, val := r.value()
   285	
   286			importconst(r.p.ipkg, pos, n.Sym, typ, val)
   287	
   288		case 'F':
   289			typ := r.signature(nil)
   290	
   291			importfunc(r.p.ipkg, pos, n.Sym, typ)
   292			r.funcExt(n)
   293	
   294		case 'T':
   295			// Types can be recursive. We need to setup a stub
   296			// declaration before recursing.
   297			t := importtype(r.p.ipkg, pos, n.Sym)
   298	
   299			// We also need to defer width calculations until
   300			// after the underlying type has been assigned.
   301			//
   302			// TODO(mdempsky): Add nesting support directly to
   303			// {defer,resume}checkwidth? Width calculations are
   304			// already deferred during initial typechecking, but
   305			// not when we're expanding inline function bodies, so
   306			// we currently need to handle both cases here.
   307			deferring := defercalc != 0
   308			if !deferring {
   309				defercheckwidth()
   310			}
   311			underlying := r.typ()
   312			copytype(typenod(t), underlying)
   313			if !deferring {
   314				resumecheckwidth()
   315			}
   316	
   317			if underlying.IsInterface() {
   318				break
   319			}
   320	
   321			ms := make([]*types.Field, r.uint64())
   322			for i := range ms {
   323				mpos := r.pos()
   324				msym := r.ident()
   325				recv := r.param()
   326				mtyp := r.signature(recv)
   327	
   328				f := types.NewField()
   329				f.Pos = mpos
   330				f.Sym = msym
   331				f.Type = mtyp
   332				ms[i] = f
   333	
   334				m := newfuncnamel(mpos, methodSym(recv.Type, msym))
   335				m.Type = mtyp
   336				m.SetClass(PFUNC)
   337				// methodSym already marked m.Sym as a function.
   338	
   339				// (comment from parser.go)
   340				// inl.C's inlnode in on a dotmeth node expects to find the inlineable body as
   341				// (dotmeth's type).Nname.Inl, and dotmeth's type has been pulled
   342				// out by typecheck's lookdot as this $$.ttype. So by providing
   343				// this back link here we avoid special casing there.
   344				mtyp.SetNname(asTypesNode(m))
   345			}
   346			t.Methods().Set(ms)
   347	
   348			for _, m := range ms {
   349				r.methExt(m)
   350			}
   351	
   352		case 'V':
   353			typ := r.typ()
   354	
   355			importvar(r.p.ipkg, pos, n.Sym, typ)
   356			r.varExt(n)
   357	
   358		default:
   359			Fatalf("unexpected tag: %v", tag)
   360		}
   361	}
   362	
   363	func (p *importReader) value() (typ *types.Type, v Val) {
   364		typ = p.typ()
   365	
   366		switch constTypeOf(typ) {
   367		case CTNIL:
   368			v.U = &NilVal{}
   369		case CTBOOL:
   370			v.U = p.bool()
   371		case CTSTR:
   372			v.U = p.string()
   373		case CTINT:
   374			x := new(Mpint)
   375			x.Rune = typ == types.Idealrune
   376			p.mpint(&x.Val, typ)
   377			v.U = x
   378		case CTFLT:
   379			x := newMpflt()
   380			p.float(x, typ)
   381			v.U = x
   382		case CTCPLX:
   383			x := newMpcmplx()
   384			p.float(&x.Real, typ)
   385			p.float(&x.Imag, typ)
   386			v.U = x
   387		}
   388	
   389		typ = idealType(typ)
   390		return
   391	}
   392	
   393	func (p *importReader) mpint(x *big.Int, typ *types.Type) {
   394		signed, maxBytes := intSize(typ)
   395	
   396		maxSmall := 256 - maxBytes
   397		if signed {
   398			maxSmall = 256 - 2*maxBytes
   399		}
   400		if maxBytes == 1 {
   401			maxSmall = 256
   402		}
   403	
   404		n, _ := p.ReadByte()
   405		if uint(n) < maxSmall {
   406			v := int64(n)
   407			if signed {
   408				v >>= 1
   409				if n&1 != 0 {
   410					v = ^v
   411				}
   412			}
   413			x.SetInt64(v)
   414			return
   415		}
   416	
   417		v := -n
   418		if signed {
   419			v = -(n &^ 1) >> 1
   420		}
   421		if v < 1 || uint(v) > maxBytes {
   422			Fatalf("weird decoding: %v, %v => %v", n, signed, v)
   423		}
   424		b := make([]byte, v)
   425		p.Read(b)
   426		x.SetBytes(b)
   427		if signed && n&1 != 0 {
   428			x.Neg(x)
   429		}
   430	}
   431	
   432	func (p *importReader) float(x *Mpflt, typ *types.Type) {
   433		var mant big.Int
   434		p.mpint(&mant, typ)
   435		m := x.Val.SetInt(&mant)
   436		if m.Sign() == 0 {
   437			return
   438		}
   439		m.SetMantExp(m, int(p.int64()))
   440	}
   441	
   442	func (r *importReader) ident() *types.Sym {
   443		name := r.string()
   444		if name == "" {
   445			return nil
   446		}
   447		pkg := r.currPkg
   448		if types.IsExported(name) {
   449			pkg = localpkg
   450		}
   451		return pkg.Lookup(name)
   452	}
   453	
   454	func (r *importReader) qualifiedIdent() *types.Sym {
   455		name := r.string()
   456		pkg := r.pkg()
   457		return pkg.Lookup(name)
   458	}
   459	
   460	func (r *importReader) pos() src.XPos {
   461		delta := r.int64()
   462		if delta != deltaNewFile {
   463			r.prevLine += delta
   464		} else if l := r.int64(); l == -1 {
   465			r.prevLine += deltaNewFile
   466		} else {
   467			r.prevBase = r.posBase()
   468			r.prevLine = l
   469		}
   470	
   471		if (r.prevBase == nil || r.prevBase.AbsFilename() == "") && r.prevLine == 0 {
   472			// TODO(mdempsky): Remove once we reliably write
   473			// position information for all nodes.
   474			return src.NoXPos
   475		}
   476	
   477		if r.prevBase == nil {
   478			Fatalf("missing posbase")
   479		}
   480		pos := src.MakePos(r.prevBase, uint(r.prevLine), 0)
   481		return Ctxt.PosTable.XPos(pos)
   482	}
   483	
   484	func (r *importReader) typ() *types.Type {
   485		return r.p.typAt(r.uint64())
   486	}
   487	
   488	func (p *iimporter) typAt(off uint64) *types.Type {
   489		t, ok := p.typCache[off]
   490		if !ok {
   491			if off < predeclReserved {
   492				Fatalf("predeclared type missing from cache: %d", off)
   493			}
   494			t = p.newReader(off-predeclReserved, nil).typ1()
   495			p.typCache[off] = t
   496		}
   497		return t
   498	}
   499	
   500	func (r *importReader) typ1() *types.Type {
   501		switch k := r.kind(); k {
   502		default:
   503			Fatalf("unexpected kind tag in %q: %v", r.p.ipkg.Path, k)
   504			return nil
   505	
   506		case definedType:
   507			// We might be called from within doInline, in which
   508			// case Sym.Def can point to declared parameters
   509			// instead of the top-level types. Also, we don't
   510			// support inlining functions with local defined
   511			// types. Therefore, this must be a package-scope
   512			// type.
   513			n := asNode(r.qualifiedIdent().PkgDef())
   514			if n.Op == ONONAME {
   515				expandDecl(n)
   516			}
   517			if n.Op != OTYPE {
   518				Fatalf("expected OTYPE, got %v: %v, %v", n.Op, n.Sym, n)
   519			}
   520			return n.Type
   521		case pointerType:
   522			return types.NewPtr(r.typ())
   523		case sliceType:
   524			return types.NewSlice(r.typ())
   525		case arrayType:
   526			n := r.uint64()
   527			return types.NewArray(r.typ(), int64(n))
   528		case chanType:
   529			dir := types.ChanDir(r.uint64())
   530			return types.NewChan(r.typ(), dir)
   531		case mapType:
   532			return types.NewMap(r.typ(), r.typ())
   533	
   534		case signatureType:
   535			r.setPkg()
   536			return r.signature(nil)
   537	
   538		case structType:
   539			r.setPkg()
   540	
   541			fs := make([]*types.Field, r.uint64())
   542			for i := range fs {
   543				pos := r.pos()
   544				sym := r.ident()
   545				typ := r.typ()
   546				emb := r.bool()
   547				note := r.string()
   548	
   549				f := types.NewField()
   550				f.Pos = pos
   551				f.Sym = sym
   552				f.Type = typ
   553				if emb {
   554					f.Embedded = 1
   555				}
   556				f.Note = note
   557				fs[i] = f
   558			}
   559	
   560			t := types.New(TSTRUCT)
   561			t.SetPkg(r.currPkg)
   562			t.SetFields(fs)
   563			return t
   564	
   565		case interfaceType:
   566			r.setPkg()
   567	
   568			embeddeds := make([]*types.Field, r.uint64())
   569			for i := range embeddeds {
   570				pos := r.pos()
   571				typ := r.typ()
   572	
   573				f := types.NewField()
   574				f.Pos = pos
   575				f.Type = typ
   576				embeddeds[i] = f
   577			}
   578	
   579			methods := make([]*types.Field, r.uint64())
   580			for i := range methods {
   581				pos := r.pos()
   582				sym := r.ident()
   583				typ := r.signature(fakeRecvField())
   584	
   585				f := types.NewField()
   586				f.Pos = pos
   587				f.Sym = sym
   588				f.Type = typ
   589				methods[i] = f
   590			}
   591	
   592			t := types.New(TINTER)
   593			t.SetPkg(r.currPkg)
   594			t.SetInterface(append(embeddeds, methods...))
   595	
   596			// Ensure we expand the interface in the frontend (#25055).
   597			checkwidth(t)
   598	
   599			return t
   600		}
   601	}
   602	
   603	func (r *importReader) kind() itag {
   604		return itag(r.uint64())
   605	}
   606	
   607	func (r *importReader) signature(recv *types.Field) *types.Type {
   608		params := r.paramList()
   609		results := r.paramList()
   610		if n := len(params); n > 0 {
   611			params[n-1].SetIsDDD(r.bool())
   612		}
   613		t := functypefield(recv, params, results)
   614		t.SetPkg(r.currPkg)
   615		return t
   616	}
   617	
   618	func (r *importReader) paramList() []*types.Field {
   619		fs := make([]*types.Field, r.uint64())
   620		for i := range fs {
   621			fs[i] = r.param()
   622		}
   623		return fs
   624	}
   625	
   626	func (r *importReader) param() *types.Field {
   627		f := types.NewField()
   628		f.Pos = r.pos()
   629		f.Sym = r.ident()
   630		f.Type = r.typ()
   631		return f
   632	}
   633	
   634	func (r *importReader) bool() bool {
   635		return r.uint64() != 0
   636	}
   637	
   638	func (r *importReader) int64() int64 {
   639		n, err := binary.ReadVarint(r)
   640		if err != nil {
   641			Fatalf("readVarint: %v", err)
   642		}
   643		return n
   644	}
   645	
   646	func (r *importReader) uint64() uint64 {
   647		n, err := binary.ReadUvarint(r)
   648		if err != nil {
   649			Fatalf("readVarint: %v", err)
   650		}
   651		return n
   652	}
   653	
   654	func (r *importReader) byte() byte {
   655		x, err := r.ReadByte()
   656		if err != nil {
   657			Fatalf("declReader.ReadByte: %v", err)
   658		}
   659		return x
   660	}
   661	
   662	// Compiler-specific extensions.
   663	
   664	func (r *importReader) varExt(n *Node) {
   665		r.linkname(n.Sym)
   666	}
   667	
   668	func (r *importReader) funcExt(n *Node) {
   669		r.linkname(n.Sym)
   670	
   671		// Escape analysis.
   672		for _, fs := range types.RecvsParams {
   673			for _, f := range fs(n.Type).FieldSlice() {
   674				f.Note = r.string()
   675			}
   676		}
   677	
   678		// Inline body.
   679		if u := r.uint64(); u > 0 {
   680			n.Func.Inl = &Inline{
   681				Cost: int32(u - 1),
   682			}
   683			n.Func.Endlineno = r.pos()
   684		}
   685	}
   686	
   687	func (r *importReader) methExt(m *types.Field) {
   688		if r.bool() {
   689			m.SetNointerface(true)
   690		}
   691		r.funcExt(asNode(m.Type.Nname()))
   692	}
   693	
   694	func (r *importReader) linkname(s *types.Sym) {
   695		s.Linkname = r.string()
   696	}
   697	
   698	func (r *importReader) doInline(n *Node) {
   699		if len(n.Func.Inl.Body) != 0 {
   700			Fatalf("%v already has inline body", n)
   701		}
   702	
   703		funchdr(n)
   704		body := r.stmtList()
   705		funcbody()
   706		if body == nil {
   707			//
   708			// Make sure empty body is not interpreted as
   709			// no inlineable body (see also parser.fnbody)
   710			// (not doing so can cause significant performance
   711			// degradation due to unnecessary calls to empty
   712			// functions).
   713			body = []*Node{}
   714		}
   715		n.Func.Inl.Body = body
   716	
   717		importlist = append(importlist, n)
   718	
   719		if Debug['E'] > 0 && Debug['m'] > 2 {
   720			if Debug['m'] > 3 {
   721				fmt.Printf("inl body for %v %#v: %+v\n", n, n.Type, asNodes(n.Func.Inl.Body))
   722			} else {
   723				fmt.Printf("inl body for %v %#v: %v\n", n, n.Type, asNodes(n.Func.Inl.Body))
   724			}
   725		}
   726	}
   727	
   728	// ----------------------------------------------------------------------------
   729	// Inlined function bodies
   730	
   731	// Approach: Read nodes and use them to create/declare the same data structures
   732	// as done originally by the (hidden) parser by closely following the parser's
   733	// original code. In other words, "parsing" the import data (which happens to
   734	// be encoded in binary rather textual form) is the best way at the moment to
   735	// re-establish the syntax tree's invariants. At some future point we might be
   736	// able to avoid this round-about way and create the rewritten nodes directly,
   737	// possibly avoiding a lot of duplicate work (name resolution, type checking).
   738	//
   739	// Refined nodes (e.g., ODOTPTR as a refinement of OXDOT) are exported as their
   740	// unrefined nodes (since this is what the importer uses). The respective case
   741	// entries are unreachable in the importer.
   742	
   743	func (r *importReader) stmtList() []*Node {
   744		var list []*Node
   745		for {
   746			n := r.node()
   747			if n == nil {
   748				break
   749			}
   750			// OBLOCK nodes may be created when importing ODCL nodes - unpack them
   751			if n.Op == OBLOCK {
   752				list = append(list, n.List.Slice()...)
   753			} else {
   754				list = append(list, n)
   755			}
   756	
   757		}
   758		return list
   759	}
   760	
   761	func (r *importReader) exprList() []*Node {
   762		var list []*Node
   763		for {
   764			n := r.expr()
   765			if n == nil {
   766				break
   767			}
   768			list = append(list, n)
   769		}
   770		return list
   771	}
   772	
   773	func (r *importReader) expr() *Node {
   774		n := r.node()
   775		if n != nil && n.Op == OBLOCK {
   776			Fatalf("unexpected block node: %v", n)
   777		}
   778		return n
   779	}
   780	
   781	// TODO(gri) split into expr and stmt
   782	func (r *importReader) node() *Node {
   783		switch op := r.op(); op {
   784		// expressions
   785		// case OPAREN:
   786		// 	unreachable - unpacked by exporter
   787	
   788		// case ODDDARG:
   789		//	unimplemented
   790	
   791		case OLITERAL:
   792			pos := r.pos()
   793			typ, val := r.value()
   794	
   795			n := npos(pos, nodlit(val))
   796			n.Type = typ
   797			return n
   798	
   799		case ONONAME:
   800			return mkname(r.qualifiedIdent())
   801	
   802		case ONAME:
   803			return mkname(r.ident())
   804	
   805		// case OPACK, ONONAME:
   806		// 	unreachable - should have been resolved by typechecking
   807	
   808		case OTYPE:
   809			return typenod(r.typ())
   810	
   811		// case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
   812		//      unreachable - should have been resolved by typechecking
   813	
   814		// case OCLOSURE:
   815		//	unimplemented
   816	
   817		case OPTRLIT:
   818			pos := r.pos()
   819			n := npos(pos, r.expr())
   820			if !r.bool() /* !implicit, i.e. '&' operator */ {
   821				if n.Op == OCOMPLIT {
   822					// Special case for &T{...}: turn into (*T){...}.
   823					n.Right = nodl(pos, ODEREF, n.Right, nil)
   824					n.Right.SetImplicit(true)
   825				} else {
   826					n = nodl(pos, OADDR, n, nil)
   827				}
   828			}
   829			return n
   830	
   831		case OSTRUCTLIT:
   832			// TODO(mdempsky): Export position information for OSTRUCTKEY nodes.
   833			savedlineno := lineno
   834			lineno = r.pos()
   835			n := nodl(lineno, OCOMPLIT, nil, typenod(r.typ()))
   836			n.List.Set(r.elemList()) // special handling of field names
   837			lineno = savedlineno
   838			return n
   839	
   840		// case OARRAYLIT, OSLICELIT, OMAPLIT:
   841		// 	unreachable - mapped to case OCOMPLIT below by exporter
   842	
   843		case OCOMPLIT:
   844			n := nodl(r.pos(), OCOMPLIT, nil, typenod(r.typ()))
   845			n.List.Set(r.exprList())
   846			return n
   847	
   848		case OKEY:
   849			pos := r.pos()
   850			left, right := r.exprsOrNil()
   851			return nodl(pos, OKEY, left, right)
   852	
   853		// case OSTRUCTKEY:
   854		//	unreachable - handled in case OSTRUCTLIT by elemList
   855	
   856		// case OCALLPART:
   857		//	unimplemented
   858	
   859		// case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
   860		// 	unreachable - mapped to case OXDOT below by exporter
   861	
   862		case OXDOT:
   863			// see parser.new_dotname
   864			return npos(r.pos(), nodSym(OXDOT, r.expr(), r.ident()))
   865	
   866		// case ODOTTYPE, ODOTTYPE2:
   867		// 	unreachable - mapped to case ODOTTYPE below by exporter
   868	
   869		case ODOTTYPE:
   870			n := nodl(r.pos(), ODOTTYPE, r.expr(), nil)
   871			n.Type = r.typ()
   872			return n
   873	
   874		// case OINDEX, OINDEXMAP, OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR:
   875		// 	unreachable - mapped to cases below by exporter
   876	
   877		case OINDEX:
   878			return nodl(r.pos(), op, r.expr(), r.expr())
   879	
   880		case OSLICE, OSLICE3:
   881			n := nodl(r.pos(), op, r.expr(), nil)
   882			low, high := r.exprsOrNil()
   883			var max *Node
   884			if n.Op.IsSlice3() {
   885				max = r.expr()
   886			}
   887			n.SetSliceBounds(low, high, max)
   888			return n
   889	
   890		// case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, ORUNES2STR, OSTR2BYTES, OSTR2RUNES, ORUNESTR:
   891		// 	unreachable - mapped to OCONV case below by exporter
   892	
   893		case OCONV:
   894			n := nodl(r.pos(), OCONV, r.expr(), nil)
   895			n.Type = r.typ()
   896			return n
   897	
   898		case OCOPY, OCOMPLEX, OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN:
   899			n := npos(r.pos(), builtinCall(op))
   900			n.List.Set(r.exprList())
   901			if op == OAPPEND {
   902				n.SetIsDDD(r.bool())
   903			}
   904			return n
   905	
   906		// case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG:
   907		// 	unreachable - mapped to OCALL case below by exporter
   908	
   909		case OCALL:
   910			n := nodl(r.pos(), OCALL, nil, nil)
   911			n.Ninit.Set(r.stmtList())
   912			n.Left = r.expr()
   913			n.List.Set(r.exprList())
   914			n.SetIsDDD(r.bool())
   915			return n
   916	
   917		case OMAKEMAP, OMAKECHAN, OMAKESLICE:
   918			n := npos(r.pos(), builtinCall(OMAKE))
   919			n.List.Append(typenod(r.typ()))
   920			n.List.Append(r.exprList()...)
   921			return n
   922	
   923		// unary expressions
   924		case OPLUS, ONEG, OADDR, OBITNOT, ODEREF, ONOT, ORECV:
   925			return nodl(r.pos(), op, r.expr(), nil)
   926	
   927		// binary expressions
   928		case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, OLT,
   929			OLSH, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSEND, OSUB, OXOR:
   930			return nodl(r.pos(), op, r.expr(), r.expr())
   931	
   932		case OADDSTR:
   933			pos := r.pos()
   934			list := r.exprList()
   935			x := npos(pos, list[0])
   936			for _, y := range list[1:] {
   937				x = nodl(pos, OADD, x, y)
   938			}
   939			return x
   940	
   941		// --------------------------------------------------------------------
   942		// statements
   943		case ODCL:
   944			pos := r.pos()
   945			lhs := npos(pos, dclname(r.ident()))
   946			typ := typenod(r.typ())
   947			return npos(pos, liststmt(variter([]*Node{lhs}, typ, nil))) // TODO(gri) avoid list creation
   948	
   949		// case ODCLFIELD:
   950		//	unimplemented
   951	
   952		// case OAS, OASWB:
   953		// 	unreachable - mapped to OAS case below by exporter
   954	
   955		case OAS:
   956			return nodl(r.pos(), OAS, r.expr(), r.expr())
   957	
   958		case OASOP:
   959			n := nodl(r.pos(), OASOP, nil, nil)
   960			n.SetSubOp(r.op())
   961			n.Left = r.expr()
   962			if !r.bool() {
   963				n.Right = nodintconst(1)
   964				n.SetImplicit(true)
   965			} else {
   966				n.Right = r.expr()
   967			}
   968			return n
   969	
   970		// case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
   971		// 	unreachable - mapped to OAS2 case below by exporter
   972	
   973		case OAS2:
   974			n := nodl(r.pos(), OAS2, nil, nil)
   975			n.List.Set(r.exprList())
   976			n.Rlist.Set(r.exprList())
   977			return n
   978	
   979		case ORETURN:
   980			n := nodl(r.pos(), ORETURN, nil, nil)
   981			n.List.Set(r.exprList())
   982			return n
   983	
   984		// case ORETJMP:
   985		// 	unreachable - generated by compiler for trampolin routines (not exported)
   986	
   987		case OGO, ODEFER:
   988			return nodl(r.pos(), op, r.expr(), nil)
   989	
   990		case OIF:
   991			n := nodl(r.pos(), OIF, nil, nil)
   992			n.Ninit.Set(r.stmtList())
   993			n.Left = r.expr()
   994			n.Nbody.Set(r.stmtList())
   995			n.Rlist.Set(r.stmtList())
   996			return n
   997	
   998		case OFOR:
   999			n := nodl(r.pos(), OFOR, nil, nil)
  1000			n.Ninit.Set(r.stmtList())
  1001			n.Left, n.Right = r.exprsOrNil()
  1002			n.Nbody.Set(r.stmtList())
  1003			return n
  1004	
  1005		case ORANGE:
  1006			n := nodl(r.pos(), ORANGE, nil, nil)
  1007			n.List.Set(r.stmtList())
  1008			n.Right = r.expr()
  1009			n.Nbody.Set(r.stmtList())
  1010			return n
  1011	
  1012		case OSELECT, OSWITCH:
  1013			n := nodl(r.pos(), op, nil, nil)
  1014			n.Ninit.Set(r.stmtList())
  1015			n.Left, _ = r.exprsOrNil()
  1016			n.List.Set(r.stmtList())
  1017			return n
  1018	
  1019		// case OCASE, OXCASE:
  1020		// 	unreachable - mapped to OXCASE case below by exporter
  1021	
  1022		case OXCASE:
  1023			n := nodl(r.pos(), OXCASE, nil, nil)
  1024			n.List.Set(r.exprList())
  1025			// TODO(gri) eventually we must declare variables for type switch
  1026			// statements (type switch statements are not yet exported)
  1027			n.Nbody.Set(r.stmtList())
  1028			return n
  1029	
  1030		// case OFALL:
  1031		// 	unreachable - mapped to OXFALL case below by exporter
  1032	
  1033		case OFALL:
  1034			n := nodl(r.pos(), OFALL, nil, nil)
  1035			return n
  1036	
  1037		case OBREAK, OCONTINUE:
  1038			pos := r.pos()
  1039			left, _ := r.exprsOrNil()
  1040			if left != nil {
  1041				left = newname(left.Sym)
  1042			}
  1043			return nodl(pos, op, left, nil)
  1044	
  1045		// case OEMPTY:
  1046		// 	unreachable - not emitted by exporter
  1047	
  1048		case OGOTO, OLABEL:
  1049			n := nodl(r.pos(), op, nil, nil)
  1050			n.Sym = lookup(r.string())
  1051			return n
  1052	
  1053		case OEND:
  1054			return nil
  1055	
  1056		default:
  1057			Fatalf("cannot import %v (%d) node\n"+
  1058				"\t==> please file an issue and assign to gri@", op, int(op))
  1059			panic("unreachable") // satisfy compiler
  1060		}
  1061	}
  1062	
  1063	func (r *importReader) op() Op {
  1064		return Op(r.uint64())
  1065	}
  1066	
  1067	func (r *importReader) elemList() []*Node {
  1068		c := r.uint64()
  1069		list := make([]*Node, c)
  1070		for i := range list {
  1071			s := r.ident()
  1072			list[i] = nodSym(OSTRUCTKEY, r.expr(), s)
  1073		}
  1074		return list
  1075	}
  1076	
  1077	func (r *importReader) exprsOrNil() (a, b *Node) {
  1078		ab := r.uint64()
  1079		if ab&1 != 0 {
  1080			a = r.expr()
  1081		}
  1082		if ab&2 != 0 {
  1083			b = r.node()
  1084		}
  1085		return
  1086	}
  1087	

View as plain text