...

Source file src/pkg/cmd/compile/internal/gc/iexport.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 export.
     6	//
     7	// The indexed export data format is an evolution of the previous
     8	// binary export data format. Its chief contribution is introducing an
     9	// index table, which allows efficient random access of individual
    10	// declarations and inline function bodies. In turn, this allows
    11	// avoiding unnecessary work for compilation units that import large
    12	// packages.
    13	//
    14	//
    15	// The top-level data format is structured as:
    16	//
    17	//     Header struct {
    18	//         Tag        byte   // 'i'
    19	//         Version    uvarint
    20	//         StringSize uvarint
    21	//         DataSize   uvarint
    22	//     }
    23	//
    24	//     Strings [StringSize]byte
    25	//     Data    [DataSize]byte
    26	//
    27	//     MainIndex []struct{
    28	//         PkgPath   stringOff
    29	//         PkgName   stringOff
    30	//         PkgHeight uvarint
    31	//
    32	//         Decls []struct{
    33	//             Name   stringOff
    34	//             Offset declOff
    35	//         }
    36	//     }
    37	//
    38	// uvarint means a uint64 written out using uvarint encoding.
    39	//
    40	// []T means a uvarint followed by that many T objects. In other
    41	// words:
    42	//
    43	//     Len   uvarint
    44	//     Elems [Len]T
    45	//
    46	// stringOff means a uvarint that indicates an offset within the
    47	// Strings section. At that offset is another uvarint, followed by
    48	// that many bytes, which form the string value.
    49	//
    50	// declOff means a uvarint that indicates an offset within the Data
    51	// section where the associated declaration can be found.
    52	//
    53	//
    54	// There are five kinds of declarations, distinguished by their first
    55	// byte:
    56	//
    57	//     type Var struct {
    58	//         Tag  byte // 'V'
    59	//         Pos  Pos
    60	//         Type typeOff
    61	//     }
    62	//
    63	//     type Func struct {
    64	//         Tag       byte // 'F'
    65	//         Pos       Pos
    66	//         Signature Signature
    67	//     }
    68	//
    69	//     type Const struct {
    70	//         Tag   byte // 'C'
    71	//         Pos   Pos
    72	//         Value Value
    73	//     }
    74	//
    75	//     type Type struct {
    76	//         Tag        byte // 'T'
    77	//         Pos        Pos
    78	//         Underlying typeOff
    79	//
    80	//         Methods []struct{  // omitted if Underlying is an interface type
    81	//             Pos       Pos
    82	//             Name      stringOff
    83	//             Recv      Param
    84	//             Signature Signature
    85	//         }
    86	//     }
    87	//
    88	//     type Alias struct {
    89	//         Tag  byte // 'A'
    90	//         Pos  Pos
    91	//         Type typeOff
    92	//     }
    93	//
    94	//
    95	// typeOff means a uvarint that either indicates a predeclared type,
    96	// or an offset into the Data section. If the uvarint is less than
    97	// predeclReserved, then it indicates the index into the predeclared
    98	// types list (see predeclared in bexport.go for order). Otherwise,
    99	// subtracting predeclReserved yields the offset of a type descriptor.
   100	//
   101	// Value means a type and type-specific value. See
   102	// (*exportWriter).value for details.
   103	//
   104	//
   105	// There are nine kinds of type descriptors, distinguished by an itag:
   106	//
   107	//     type DefinedType struct {
   108	//         Tag     itag // definedType
   109	//         Name    stringOff
   110	//         PkgPath stringOff
   111	//     }
   112	//
   113	//     type PointerType struct {
   114	//         Tag  itag // pointerType
   115	//         Elem typeOff
   116	//     }
   117	//
   118	//     type SliceType struct {
   119	//         Tag  itag // sliceType
   120	//         Elem typeOff
   121	//     }
   122	//
   123	//     type ArrayType struct {
   124	//         Tag  itag // arrayType
   125	//         Len  uint64
   126	//         Elem typeOff
   127	//     }
   128	//
   129	//     type ChanType struct {
   130	//         Tag  itag   // chanType
   131	//         Dir  uint64 // 1 RecvOnly; 2 SendOnly; 3 SendRecv
   132	//         Elem typeOff
   133	//     }
   134	//
   135	//     type MapType struct {
   136	//         Tag  itag // mapType
   137	//         Key  typeOff
   138	//         Elem typeOff
   139	//     }
   140	//
   141	//     type FuncType struct {
   142	//         Tag       itag // signatureType
   143	//         PkgPath   stringOff
   144	//         Signature Signature
   145	//     }
   146	//
   147	//     type StructType struct {
   148	//         Tag     itag // structType
   149	//         PkgPath stringOff
   150	//         Fields []struct {
   151	//             Pos      Pos
   152	//             Name     stringOff
   153	//             Type     typeOff
   154	//             Embedded bool
   155	//             Note     stringOff
   156	//         }
   157	//     }
   158	//
   159	//     type InterfaceType struct {
   160	//         Tag     itag // interfaceType
   161	//         PkgPath stringOff
   162	//         Embeddeds []struct {
   163	//             Pos  Pos
   164	//             Type typeOff
   165	//         }
   166	//         Methods []struct {
   167	//             Pos       Pos
   168	//             Name      stringOff
   169	//             Signature Signature
   170	//         }
   171	//     }
   172	//
   173	//
   174	//     type Signature struct {
   175	//         Params   []Param
   176	//         Results  []Param
   177	//         Variadic bool  // omitted if Results is empty
   178	//     }
   179	//
   180	//     type Param struct {
   181	//         Pos  Pos
   182	//         Name stringOff
   183	//         Type typOff
   184	//     }
   185	//
   186	//
   187	// Pos encodes a file:line pair, incorporating a simple delta encoding
   188	// scheme within a data object. See exportWriter.pos for details.
   189	//
   190	//
   191	// Compiler-specific details.
   192	//
   193	// cmd/compile writes out a second index for inline bodies and also
   194	// appends additional compiler-specific details after declarations.
   195	// Third-party tools are not expected to depend on these details and
   196	// they're expected to change much more rapidly, so they're omitted
   197	// here. See exportWriter's varExt/funcExt/etc methods for details.
   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	// Current indexed export format version. Increase with each format change.
   215	// 0: Go1.11 encoding
   216	const iexportVersion = 0
   217	
   218	// predeclReserved is the number of type offsets reserved for types
   219	// implicitly declared in the universe block.
   220	const predeclReserved = 32
   221	
   222	// An itag distinguishes the kind of type that was written into the
   223	// indexed export format.
   224	type itag uint64
   225	
   226	const (
   227		// Types
   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		// Mark inline bodies that are reachable through exported types.
   241		// (Phase 0 of bexport.go.)
   242		{
   243			// TODO(mdempsky): Separate from bexport logic.
   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		// Initialize work queue with exported declarations.
   267		for _, n := range exportlist {
   268			p.pushDecl(n)
   269		}
   270	
   271		// Loop until no more work. We use a queue because while
   272		// writing out inline bodies, we may discover additional
   273		// declarations that are needed.
   274		for !p.declTodo.empty() {
   275			p.doDecl(p.declTodo.popLeft())
   276		}
   277	
   278		// Append indices to data0 section.
   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		// Assemble header.
   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		// Flush output.
   293		io.Copy(out, &hdr)
   294		io.Copy(out, &p.strings)
   295		io.Copy(out, &p.data0)
   296	}
   297	
   298	// writeIndex writes out an object index. mainIndex indicates whether
   299	// we're writing out the main index, which is also read by
   300	// non-compiler tools and includes a complete package description
   301	// (i.e., name and height).
   302	func (w *exportWriter) writeIndex(index map[*Node]uint64, mainIndex bool) {
   303		// Build a map from packages to objects from that package.
   304		pkgObjs := map[*types.Pkg][]*Node{}
   305	
   306		// For the main index, make sure to include every package that
   307		// we reference, even if we're not exporting (or reexporting)
   308		// any symbols from it.
   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		// allPkgs tracks all packages that have been referenced by
   352		// the export data, so we can ensure to include them in the
   353		// main index.
   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	// stringOff returns the offset of s within the string section.
   368	// If not already present, it's added to the end.
   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	// pushDecl adds n to the declaration work queue, if not already present.
   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		// Don't export predeclared declarations.
   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) // mark n present in work queue
   397		p.declTodo.pushRight(n)
   398	}
   399	
   400	// exportWriter handles writing out individual data section chunks.
   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				// Variable.
   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				// Function.
   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			// Constant.
   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				// Alias.
   449				w.tag('A')
   450				w.pos(n.Pos)
   451				w.typ(n.Type)
   452				break
   453			}
   454	
   455			// Defined type.
   456			w.tag('T')
   457			w.pos(n.Pos)
   458	
   459			underlying := n.Type.Orig
   460			if underlying == types.Errortype.Orig {
   461				// For "type T error", use error as the
   462				// underlying type instead of error's own
   463				// underlying anonymous interface. This
   464				// ensures consistency with how importers may
   465				// declare error (e.g., go/types uses nil Pkg
   466				// for predeclared objects).
   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		// When file is the same as the last position (common case),
   515		// we can save a few bytes by delta encoding just the line
   516		// number.
   517		//
   518		// Note: Because data objects may be read out of order (or not
   519		// at all), we can only apply delta encoding within a single
   520		// object. This is handled implicitly by tracking prevFile and
   521		// prevLine as fields of exportWriter.
   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) // line >= 0
   532			w.string(file)
   533			w.prevFile = file
   534		}
   535		w.prevLine = line
   536	}
   537	
   538	func (w *exportWriter) pkg(pkg *types.Pkg) {
   539		// Ensure any referenced packages are declared in the main index.
   540		w.p.allPkgs[pkg] = true
   541	
   542		w.string(pkg.Path)
   543	}
   544	
   545	func (w *exportWriter) qualifiedIdent(n *Node) {
   546		// Ensure any referenced declarations are written out too.
   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		// Method selectors are rewritten into method symbols (of the
   560		// form T.M) during typechecking, but we want to write out
   561		// just the bare method name.
   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			// TODO(mdempsky): Proactively set Pkg for types and
   694			// remove this fallback logic.
   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		// Each type has only one admissible constant representation,
   764		// so we could type switch directly on v.U here. However,
   765		// switching on the type increases symmetry with import logic
   766		// and provides a useful consistency check.
   767	
   768		switch constTypeOf(typ) {
   769		case CTNIL:
   770			// Only one value; nothing to encode.
   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		// The go/types API doesn't expose sizes to importers, so they
   803		// don't know how big these types are.
   804		switch typ.Etype {
   805		case TINT, TUINT, TUINTPTR:
   806			maxBytes = 8
   807		}
   808	
   809		return
   810	}
   811	
   812	// mpint exports a multi-precision integer.
   813	//
   814	// For unsigned types, small values are written out as a single
   815	// byte. Larger values are written out as a length-prefixed big-endian
   816	// byte string, where the length prefix is encoded as its complement.
   817	// For example, bytes 0, 1, and 2 directly represent the integer
   818	// values 0, 1, and 2; while bytes 255, 254, and 253 indicate a 1-,
   819	// 2-, and 3-byte big-endian string follow.
   820	//
   821	// Encoding for signed types use the same general approach as for
   822	// unsigned types, except small values use zig-zag encoding and the
   823	// bottom bit of length prefix byte for large values is reserved as a
   824	// sign bit.
   825	//
   826	// The exact boundary between small and large encodings varies
   827	// according to the maximum number of bytes needed to encode a value
   828	// of type typ. As a special case, 8-bit types are always encoded as a
   829	// single byte.
   830	//
   831	// TODO(mdempsky): Is this level of complexity really worthwhile?
   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		// Check if x can use small value encoding.
   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	// mpfloat exports a multi-precision floating point number.
   890	//
   891	// The number's value is decomposed into mantissa × 2**exponent, where
   892	// mantissa is an integer. The value is written out as mantissa (as a
   893	// multi-precision integer) and then the exponent, except exponent is
   894	// omitted if mantissa is zero.
   895	func (w *exportWriter) mpfloat(f *big.Float, typ *types.Type) {
   896		if f.IsInf() {
   897			Fatalf("infinite constant")
   898		}
   899	
   900		// Break into f = mant × 2**exp, with 0.5 <= mant < 1.
   901		var mant big.Float
   902		exp := int64(f.MantExp(&mant))
   903	
   904		// Scale so that mant is an integer.
   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	// Compiler-specific extensions.
   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		// Escape analysis.
   942		for _, fs := range types.RecvsParams {
   943			for _, f := range fs(n.Type).FieldSlice() {
   944				w.string(f.Note)
   945			}
   946		}
   947	
   948		// Inline body.
   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			// Endlineno for inlined function.
   956			if n.Name.Defn != nil {
   957				w.pos(n.Name.Defn.Func.Endlineno)
   958			} else {
   959				// When the exported node was defined externally,
   960				// e.g. io exports atomic.(*Value).Load or bytes exports errors.New.
   961				// Keep it as we don't distinguish this case in iimport.go.
   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	// Inline bodies.
   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	// Caution: stmt will emit more than one node for statement nodes n that have a non-empty
   996	// n.Ninit and where n cannot have a natural init section (such as in "if", "for", etc.).
   997	func (w *exportWriter) stmt(n *Node) {
   998		if n.Ninit.Len() > 0 && !stmtwithinit(n.Op) {
   999			// can't use stmtList here since we don't want the final OEND
  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		// case ODCLFIELD:
  1013		//	unimplemented - handled by default case
  1014	
  1015		case OAS:
  1016			// Don't export "v = <N>" initializing statements, hope they're always
  1017			// preceded by the DCL which will be re-parsed and typecheck to reproduce
  1018			// the "v = <N>" again.
  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		// case ORETJMP:
  1047		// 	unreachable - generated by compiler for trampolin routines
  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			// nothing to emit
  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		// from nodefmt (fmt.go)
  1120		//
  1121		// nodefmt reverts nodes back to their original - we don't need to do
  1122		// it because we are not bound to produce valid Go syntax when exporting
  1123		//
  1124		// if (fmtmode != FExp || n.Op != OLITERAL) && n.Orig != nil {
  1125		// 	n = n.Orig
  1126		// }
  1127	
  1128		// from exprfmt (fmt.go)
  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		// expressions
  1135		// (somewhat closely following the structure of exprfmt in fmt.go)
  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			// Special case: explicit name of func (*T) method(...) is turned into pkg.(*T).method,
  1147			// but for export, this should be rendered as (*pkg.T).meth.
  1148			// These nodes have the special property that they are names with a left OTYPE and a right ONAME.
  1149			if n.isMethodExpression() {
  1150				w.op(OXDOT)
  1151				w.pos(n.Pos)
  1152				w.expr(n.Left) // n.Left.Op == OTYPE
  1153				w.selector(n.Right.Sym)
  1154				break
  1155			}
  1156	
  1157			// Package scope name.
  1158			if (n.Class() == PEXTERN || n.Class() == PFUNC) && !n.isBlank() {
  1159				w.op(ONONAME)
  1160				w.qualifiedIdent(n)
  1161				break
  1162			}
  1163	
  1164			// Function scope name.
  1165			w.op(ONAME)
  1166			w.localName(n)
  1167	
  1168		// case OPACK, ONONAME:
  1169		// 	should have been resolved by typechecking - handled by default case
  1170	
  1171		case OTYPE:
  1172			w.op(OTYPE)
  1173			w.typ(n.Type)
  1174	
  1175		// case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
  1176		// 	should have been resolved by typechecking - handled by default case
  1177	
  1178		// case OCLOSURE:
  1179		//	unimplemented - handled by default case
  1180	
  1181		// case OCOMPLIT:
  1182		// 	should have been resolved by typechecking - handled by default case
  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) // special handling of field names
  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		// case OSTRUCTKEY:
  1208		//	unreachable - handled in case OSTRUCTLIT by elemList
  1209	
  1210		// case OCALLPART:
  1211		//	unimplemented - handled by default case
  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			// treated like other builtin calls (see e.g., OREAL)
  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) // emits terminating OEND
  1268			}
  1269			// only append() calls may contain '...' arguments
  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) // must keep separate from OMAKE for importer
  1286			w.pos(n.Pos)
  1287			w.typ(n.Type)
  1288			switch {
  1289			default:
  1290				// empty list
  1291				w.op(OEND)
  1292			case n.List.Len() != 0: // pre-typecheck
  1293				w.exprList(n.List) // emits terminating OEND
  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		// unary expressions
  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		// binary expressions
  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			// if exporting, DCLCONST should just be removed as its usage
  1324			// has already been replaced with literals
  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		// Escape analysis happens after inline bodies are saved, but
  1363		// we're using the same ONAME nodes, so we might still see
  1364		// PAUTOHEAP here.
  1365		//
  1366		// Check for Stackcopy to identify PAUTOHEAP that came from
  1367		// PPARAM/PPARAMOUT, because we only want to include vargen in
  1368		// non-param names.
  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		// Anonymous parameters.
  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		// TODO(mdempsky): Fix autotmp hack.
  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