github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/cmd/compile/internal/gc/iexport.go (about)

     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/obj"
   206  	"cmd/internal/src"
   207  	"encoding/binary"
   208  	"fmt"
   209  	"go/ast"
   210  	"io"
   211  	"math/big"
   212  	"strings"
   213  )
   214  
   215  // Current indexed export format version. Increase with each format change.
   216  // 0: Go1.11 encoding
   217  const iexportVersion = 0
   218  
   219  // predeclReserved is the number of type offsets reserved for types
   220  // implicitly declared in the universe block.
   221  const predeclReserved = 32
   222  
   223  // An itag distinguishes the kind of type that was written into the
   224  // indexed export format.
   225  type itag uint64
   226  
   227  const (
   228  	// Types
   229  	definedType itag = iota
   230  	pointerType
   231  	sliceType
   232  	arrayType
   233  	chanType
   234  	mapType
   235  	signatureType
   236  	structType
   237  	interfaceType
   238  )
   239  
   240  func iexport(out *bufio.Writer) {
   241  	// Mark inline bodies that are reachable through exported types.
   242  	// (Phase 0 of bexport.go.)
   243  	{
   244  		// TODO(mdempsky): Separate from bexport logic.
   245  		p := &exporter{marked: make(map[*types.Type]bool)}
   246  		for _, n := range exportlist {
   247  			sym := n.Sym
   248  			p.markType(asNode(sym.Def).Type)
   249  		}
   250  	}
   251  
   252  	p := iexporter{
   253  		allPkgs:     map[*types.Pkg]bool{},
   254  		stringIndex: map[string]uint64{},
   255  		declIndex:   map[*Node]uint64{},
   256  		inlineIndex: map[*Node]uint64{},
   257  		typIndex:    map[*types.Type]uint64{},
   258  	}
   259  
   260  	for i, pt := range predeclared() {
   261  		p.typIndex[pt] = uint64(i)
   262  	}
   263  	if len(p.typIndex) > predeclReserved {
   264  		Fatalf("too many predeclared types: %d > %d", len(p.typIndex), predeclReserved)
   265  	}
   266  
   267  	// Initialize work queue with exported declarations.
   268  	for _, n := range exportlist {
   269  		p.pushDecl(n)
   270  	}
   271  
   272  	// Loop until no more work. We use a queue because while
   273  	// writing out inline bodies, we may discover additional
   274  	// declarations that are needed.
   275  	for !p.declTodo.empty() {
   276  		p.doDecl(p.declTodo.popLeft())
   277  	}
   278  
   279  	// Append indices to data0 section.
   280  	dataLen := uint64(p.data0.Len())
   281  	w := p.newWriter()
   282  	w.writeIndex(p.declIndex, true)
   283  	w.writeIndex(p.inlineIndex, false)
   284  	w.flush()
   285  
   286  	// Assemble header.
   287  	var hdr intWriter
   288  	hdr.WriteByte('i')
   289  	hdr.uint64(iexportVersion)
   290  	hdr.uint64(uint64(p.strings.Len()))
   291  	hdr.uint64(dataLen)
   292  
   293  	// Flush output.
   294  	io.Copy(out, &hdr)
   295  	io.Copy(out, &p.strings)
   296  	io.Copy(out, &p.data0)
   297  }
   298  
   299  // writeIndex writes out an object index. mainIndex indicates whether
   300  // we're writing out the main index, which is also read by
   301  // non-compiler tools and includes a complete package description
   302  // (i.e., name and height).
   303  func (w *exportWriter) writeIndex(index map[*Node]uint64, mainIndex bool) {
   304  	// Build a map from packages to objects from that package.
   305  	pkgObjs := map[*types.Pkg][]*Node{}
   306  
   307  	// For the main index, make sure to include every package that
   308  	// we reference, even if we're not exporting (or reexporting)
   309  	// any symbols from it.
   310  	if mainIndex {
   311  		pkgObjs[localpkg] = nil
   312  		for pkg := range w.p.allPkgs {
   313  			pkgObjs[pkg] = nil
   314  		}
   315  	}
   316  
   317  	for n := range index {
   318  		pkgObjs[n.Sym.Pkg] = append(pkgObjs[n.Sym.Pkg], n)
   319  	}
   320  
   321  	var pkgs []*types.Pkg
   322  	for pkg, objs := range pkgObjs {
   323  		pkgs = append(pkgs, pkg)
   324  
   325  		obj.SortSlice(objs, func(i, j int) bool {
   326  			return objs[i].Sym.Name < objs[j].Sym.Name
   327  		})
   328  	}
   329  
   330  	obj.SortSlice(pkgs, func(i, j int) bool {
   331  		return pkgs[i].Path < pkgs[j].Path
   332  	})
   333  
   334  	w.uint64(uint64(len(pkgs)))
   335  	for _, pkg := range pkgs {
   336  		w.string(pkg.Path)
   337  		if mainIndex {
   338  			w.string(pkg.Name)
   339  			w.uint64(uint64(pkg.Height))
   340  		}
   341  
   342  		objs := pkgObjs[pkg]
   343  		w.uint64(uint64(len(objs)))
   344  		for _, n := range objs {
   345  			w.string(n.Sym.Name)
   346  			w.uint64(index[n])
   347  		}
   348  	}
   349  }
   350  
   351  type iexporter struct {
   352  	// allPkgs tracks all packages that have been referenced by
   353  	// the export data, so we can ensure to include them in the
   354  	// main index.
   355  	allPkgs map[*types.Pkg]bool
   356  
   357  	declTodo nodeQueue
   358  
   359  	strings     intWriter
   360  	stringIndex map[string]uint64
   361  
   362  	data0       intWriter
   363  	declIndex   map[*Node]uint64
   364  	inlineIndex map[*Node]uint64
   365  	typIndex    map[*types.Type]uint64
   366  }
   367  
   368  // stringOff returns the offset of s within the string section.
   369  // If not already present, it's added to the end.
   370  func (p *iexporter) stringOff(s string) uint64 {
   371  	off, ok := p.stringIndex[s]
   372  	if !ok {
   373  		off = uint64(p.strings.Len())
   374  		p.stringIndex[s] = off
   375  
   376  		p.strings.uint64(uint64(len(s)))
   377  		p.strings.WriteString(s)
   378  	}
   379  	return off
   380  }
   381  
   382  // pushDecl adds n to the declaration work queue, if not already present.
   383  func (p *iexporter) pushDecl(n *Node) {
   384  	if n.Sym == nil || asNode(n.Sym.Def) != n && n.Op != OTYPE {
   385  		Fatalf("weird Sym: %v, %v", n, n.Sym)
   386  	}
   387  
   388  	// Don't export predeclared declarations.
   389  	if n.Sym.Pkg == builtinpkg || n.Sym.Pkg == unsafepkg {
   390  		return
   391  	}
   392  
   393  	if _, ok := p.declIndex[n]; ok {
   394  		return
   395  	}
   396  
   397  	p.declIndex[n] = ^uint64(0) // mark n present in work queue
   398  	p.declTodo.pushRight(n)
   399  }
   400  
   401  // exportWriter handles writing out individual data section chunks.
   402  type exportWriter struct {
   403  	p *iexporter
   404  
   405  	data     intWriter
   406  	currPkg  *types.Pkg
   407  	prevFile string
   408  	prevLine int64
   409  }
   410  
   411  func (p *iexporter) doDecl(n *Node) {
   412  	w := p.newWriter()
   413  	w.setPkg(n.Sym.Pkg, false)
   414  
   415  	switch n.Op {
   416  	case ONAME:
   417  		switch n.Class() {
   418  		case PEXTERN:
   419  			// Variable.
   420  			w.tag('V')
   421  			w.pos(n.Pos)
   422  			w.typ(n.Type)
   423  			w.varExt(n)
   424  
   425  		case PFUNC:
   426  			if n.IsMethod() {
   427  				Fatalf("unexpected method: %v", n)
   428  			}
   429  
   430  			// Function.
   431  			w.tag('F')
   432  			w.pos(n.Pos)
   433  			w.signature(n.Type)
   434  			w.funcExt(n)
   435  
   436  		default:
   437  			Fatalf("unexpected class: %v, %v", n, n.Class())
   438  		}
   439  
   440  	case OLITERAL:
   441  		// Constant.
   442  		n = typecheck(n, ctxExpr)
   443  		w.tag('C')
   444  		w.pos(n.Pos)
   445  		w.value(n.Type, n.Val())
   446  
   447  	case OTYPE:
   448  		if IsAlias(n.Sym) {
   449  			// Alias.
   450  			w.tag('A')
   451  			w.pos(n.Pos)
   452  			w.typ(n.Type)
   453  			break
   454  		}
   455  
   456  		// Defined type.
   457  		w.tag('T')
   458  		w.pos(n.Pos)
   459  
   460  		underlying := n.Type.Orig
   461  		if underlying == types.Errortype.Orig {
   462  			// For "type T error", use error as the
   463  			// underlying type instead of error's own
   464  			// underlying anonymous interface. This
   465  			// ensures consistency with how importers may
   466  			// declare error (e.g., go/types uses nil Pkg
   467  			// for predeclared objects).
   468  			underlying = types.Errortype
   469  		}
   470  		w.typ(underlying)
   471  
   472  		t := n.Type
   473  		if t.IsInterface() {
   474  			break
   475  		}
   476  
   477  		ms := t.Methods()
   478  		w.uint64(uint64(ms.Len()))
   479  		for _, m := range ms.Slice() {
   480  			w.pos(m.Pos)
   481  			w.selector(m.Sym)
   482  			w.param(m.Type.Recv())
   483  			w.signature(m.Type)
   484  		}
   485  
   486  		for _, m := range ms.Slice() {
   487  			w.methExt(m)
   488  		}
   489  
   490  	default:
   491  		Fatalf("unexpected node: %v", n)
   492  	}
   493  
   494  	p.declIndex[n] = w.flush()
   495  }
   496  
   497  func (w *exportWriter) tag(tag byte) {
   498  	w.data.WriteByte(tag)
   499  }
   500  
   501  func (p *iexporter) doInline(f *Node) {
   502  	w := p.newWriter()
   503  	w.setPkg(fnpkg(f), false)
   504  
   505  	w.stmtList(asNodes(f.Func.Inl.Body))
   506  
   507  	p.inlineIndex[f] = w.flush()
   508  }
   509  
   510  func (w *exportWriter) pos(pos src.XPos) {
   511  	p := Ctxt.PosTable.Pos(pos)
   512  	file := p.Base().AbsFilename()
   513  	line := int64(p.RelLine())
   514  
   515  	// When file is the same as the last position (common case),
   516  	// we can save a few bytes by delta encoding just the line
   517  	// number.
   518  	//
   519  	// Note: Because data objects may be read out of order (or not
   520  	// at all), we can only apply delta encoding within a single
   521  	// object. This is handled implicitly by tracking prevFile and
   522  	// prevLine as fields of exportWriter.
   523  
   524  	if file == w.prevFile {
   525  		delta := line - w.prevLine
   526  		w.int64(delta)
   527  		if delta == deltaNewFile {
   528  			w.int64(-1)
   529  		}
   530  	} else {
   531  		w.int64(deltaNewFile)
   532  		w.int64(line) // line >= 0
   533  		w.string(file)
   534  		w.prevFile = file
   535  	}
   536  	w.prevLine = line
   537  }
   538  
   539  func (w *exportWriter) pkg(pkg *types.Pkg) {
   540  	// Ensure any referenced packages are declared in the main index.
   541  	w.p.allPkgs[pkg] = true
   542  
   543  	w.string(pkg.Path)
   544  }
   545  
   546  func (w *exportWriter) qualifiedIdent(n *Node) {
   547  	// Ensure any referenced declarations are written out too.
   548  	w.p.pushDecl(n)
   549  
   550  	s := n.Sym
   551  	w.string(s.Name)
   552  	w.pkg(s.Pkg)
   553  }
   554  
   555  func (w *exportWriter) selector(s *types.Sym) {
   556  	if w.currPkg == nil {
   557  		Fatalf("missing currPkg")
   558  	}
   559  
   560  	// Method selectors are rewritten into method symbols (of the
   561  	// form T.M) during typechecking, but we want to write out
   562  	// just the bare method name.
   563  	name := s.Name
   564  	if i := strings.LastIndex(name, "."); i >= 0 {
   565  		name = name[i+1:]
   566  	} else {
   567  		pkg := w.currPkg
   568  		if types.IsExported(name) {
   569  			pkg = localpkg
   570  		}
   571  		if s.Pkg != pkg {
   572  			Fatalf("package mismatch in selector: %v in package %q, but want %q", s, s.Pkg.Path, pkg.Path)
   573  		}
   574  	}
   575  
   576  	w.string(name)
   577  }
   578  
   579  func (w *exportWriter) typ(t *types.Type) {
   580  	w.data.uint64(w.p.typOff(t))
   581  }
   582  
   583  func (p *iexporter) newWriter() *exportWriter {
   584  	return &exportWriter{p: p}
   585  }
   586  
   587  func (w *exportWriter) flush() uint64 {
   588  	off := uint64(w.p.data0.Len())
   589  	io.Copy(&w.p.data0, &w.data)
   590  	return off
   591  }
   592  
   593  func (p *iexporter) typOff(t *types.Type) uint64 {
   594  	off, ok := p.typIndex[t]
   595  	if !ok {
   596  		w := p.newWriter()
   597  		w.doTyp(t)
   598  		off = predeclReserved + w.flush()
   599  		p.typIndex[t] = off
   600  	}
   601  	return off
   602  }
   603  
   604  func (w *exportWriter) startType(k itag) {
   605  	w.data.uint64(uint64(k))
   606  }
   607  
   608  func (w *exportWriter) doTyp(t *types.Type) {
   609  	if t.Sym != nil {
   610  		if t.Sym.Pkg == builtinpkg || t.Sym.Pkg == unsafepkg {
   611  			Fatalf("builtin type missing from typIndex: %v", t)
   612  		}
   613  
   614  		w.startType(definedType)
   615  		w.qualifiedIdent(typenod(t))
   616  		return
   617  	}
   618  
   619  	switch t.Etype {
   620  	case TPTR:
   621  		w.startType(pointerType)
   622  		w.typ(t.Elem())
   623  
   624  	case TSLICE:
   625  		w.startType(sliceType)
   626  		w.typ(t.Elem())
   627  
   628  	case TARRAY:
   629  		w.startType(arrayType)
   630  		w.uint64(uint64(t.NumElem()))
   631  		w.typ(t.Elem())
   632  
   633  	case TCHAN:
   634  		w.startType(chanType)
   635  		w.uint64(uint64(t.ChanDir()))
   636  		w.typ(t.Elem())
   637  
   638  	case TMAP:
   639  		w.startType(mapType)
   640  		w.typ(t.Key())
   641  		w.typ(t.Elem())
   642  
   643  	case TFUNC:
   644  		w.startType(signatureType)
   645  		w.setPkg(t.Pkg(), true)
   646  		w.signature(t)
   647  
   648  	case TSTRUCT:
   649  		w.startType(structType)
   650  		w.setPkg(t.Pkg(), true)
   651  
   652  		w.uint64(uint64(t.NumFields()))
   653  		for _, f := range t.FieldSlice() {
   654  			w.pos(f.Pos)
   655  			w.selector(f.Sym)
   656  			w.typ(f.Type)
   657  			w.bool(f.Embedded != 0)
   658  			w.string(f.Note)
   659  		}
   660  
   661  	case TINTER:
   662  		var embeddeds, methods []*types.Field
   663  		for _, m := range t.Methods().Slice() {
   664  			if m.Sym != nil {
   665  				methods = append(methods, m)
   666  			} else {
   667  				embeddeds = append(embeddeds, m)
   668  			}
   669  		}
   670  
   671  		w.startType(interfaceType)
   672  		w.setPkg(t.Pkg(), true)
   673  
   674  		w.uint64(uint64(len(embeddeds)))
   675  		for _, f := range embeddeds {
   676  			w.pos(f.Pos)
   677  			w.typ(f.Type)
   678  		}
   679  
   680  		w.uint64(uint64(len(methods)))
   681  		for _, f := range methods {
   682  			w.pos(f.Pos)
   683  			w.selector(f.Sym)
   684  			w.signature(f.Type)
   685  		}
   686  
   687  	default:
   688  		Fatalf("unexpected type: %v", t)
   689  	}
   690  }
   691  
   692  func (w *exportWriter) setPkg(pkg *types.Pkg, write bool) {
   693  	if pkg == nil {
   694  		// TODO(mdempsky): Proactively set Pkg for types and
   695  		// remove this fallback logic.
   696  		pkg = localpkg
   697  	}
   698  
   699  	if write {
   700  		w.pkg(pkg)
   701  	}
   702  
   703  	w.currPkg = pkg
   704  }
   705  
   706  func (w *exportWriter) signature(t *types.Type) {
   707  	w.paramList(t.Params().FieldSlice())
   708  	w.paramList(t.Results().FieldSlice())
   709  	if n := t.Params().NumFields(); n > 0 {
   710  		w.bool(t.Params().Field(n - 1).IsDDD())
   711  	}
   712  }
   713  
   714  func (w *exportWriter) paramList(fs []*types.Field) {
   715  	w.uint64(uint64(len(fs)))
   716  	for _, f := range fs {
   717  		w.param(f)
   718  	}
   719  }
   720  
   721  func (w *exportWriter) param(f *types.Field) {
   722  	w.pos(f.Pos)
   723  	w.localIdent(origSym(f.Sym), 0)
   724  	w.typ(f.Type)
   725  }
   726  
   727  func constTypeOf(typ *types.Type) Ctype {
   728  	switch typ {
   729  	case types.Idealint, types.Idealrune:
   730  		return CTINT
   731  	case types.Idealfloat:
   732  		return CTFLT
   733  	case types.Idealcomplex:
   734  		return CTCPLX
   735  	}
   736  
   737  	switch typ.Etype {
   738  	case TCHAN, TFUNC, TMAP, TNIL, TINTER, TSLICE:
   739  		return CTNIL
   740  	case TBOOL:
   741  		return CTBOOL
   742  	case TSTRING:
   743  		return CTSTR
   744  	case TINT, TINT8, TINT16, TINT32, TINT64,
   745  		TUINT, TUINT8, TUINT16, TUINT32, TUINT64, TUINTPTR,
   746  		TPTR, TUNSAFEPTR:
   747  		return CTINT
   748  	case TFLOAT32, TFLOAT64:
   749  		return CTFLT
   750  	case TCOMPLEX64, TCOMPLEX128:
   751  		return CTCPLX
   752  	}
   753  
   754  	Fatalf("unexpected constant type: %v", typ)
   755  	return 0
   756  }
   757  
   758  func (w *exportWriter) value(typ *types.Type, v Val) {
   759  	if typ.IsUntyped() {
   760  		typ = untype(v.Ctype())
   761  	}
   762  	w.typ(typ)
   763  
   764  	// Each type has only one admissible constant representation,
   765  	// so we could type switch directly on v.U here. However,
   766  	// switching on the type increases symmetry with import logic
   767  	// and provides a useful consistency check.
   768  
   769  	switch constTypeOf(typ) {
   770  	case CTNIL:
   771  		// Only one value; nothing to encode.
   772  		_ = v.U.(*NilVal)
   773  	case CTBOOL:
   774  		w.bool(v.U.(bool))
   775  	case CTSTR:
   776  		w.string(v.U.(string))
   777  	case CTINT:
   778  		w.mpint(&v.U.(*Mpint).Val, typ)
   779  	case CTFLT:
   780  		w.mpfloat(&v.U.(*Mpflt).Val, typ)
   781  	case CTCPLX:
   782  		x := v.U.(*Mpcplx)
   783  		w.mpfloat(&x.Real.Val, typ)
   784  		w.mpfloat(&x.Imag.Val, typ)
   785  	}
   786  }
   787  
   788  func intSize(typ *types.Type) (signed bool, maxBytes uint) {
   789  	if typ.IsUntyped() {
   790  		return true, Mpprec / 8
   791  	}
   792  
   793  	switch typ.Etype {
   794  	case TFLOAT32, TCOMPLEX64:
   795  		return true, 3
   796  	case TFLOAT64, TCOMPLEX128:
   797  		return true, 7
   798  	}
   799  
   800  	signed = typ.IsSigned()
   801  	maxBytes = uint(typ.Size())
   802  
   803  	// The go/types API doesn't expose sizes to importers, so they
   804  	// don't know how big these types are.
   805  	switch typ.Etype {
   806  	case TINT, TUINT, TUINTPTR:
   807  		maxBytes = 8
   808  	}
   809  
   810  	return
   811  }
   812  
   813  // mpint exports a multi-precision integer.
   814  //
   815  // For unsigned types, small values are written out as a single
   816  // byte. Larger values are written out as a length-prefixed big-endian
   817  // byte string, where the length prefix is encoded as its complement.
   818  // For example, bytes 0, 1, and 2 directly represent the integer
   819  // values 0, 1, and 2; while bytes 255, 254, and 253 indicate a 1-,
   820  // 2-, and 3-byte big-endian string follow.
   821  //
   822  // Encoding for signed types use the same general approach as for
   823  // unsigned types, except small values use zig-zag encoding and the
   824  // bottom bit of length prefix byte for large values is reserved as a
   825  // sign bit.
   826  //
   827  // The exact boundary between small and large encodings varies
   828  // according to the maximum number of bytes needed to encode a value
   829  // of type typ. As a special case, 8-bit types are always encoded as a
   830  // single byte.
   831  //
   832  // TODO(mdempsky): Is this level of complexity really worthwhile?
   833  func (w *exportWriter) mpint(x *big.Int, typ *types.Type) {
   834  	signed, maxBytes := intSize(typ)
   835  
   836  	negative := x.Sign() < 0
   837  	if !signed && negative {
   838  		Fatalf("negative unsigned integer; type %v, value %v", typ, x)
   839  	}
   840  
   841  	b := x.Bytes()
   842  	if len(b) > 0 && b[0] == 0 {
   843  		Fatalf("leading zeros")
   844  	}
   845  	if uint(len(b)) > maxBytes {
   846  		Fatalf("bad mpint length: %d > %d (type %v, value %v)", len(b), maxBytes, typ, x)
   847  	}
   848  
   849  	maxSmall := 256 - maxBytes
   850  	if signed {
   851  		maxSmall = 256 - 2*maxBytes
   852  	}
   853  	if maxBytes == 1 {
   854  		maxSmall = 256
   855  	}
   856  
   857  	// Check if x can use small value encoding.
   858  	if len(b) <= 1 {
   859  		var ux uint
   860  		if len(b) == 1 {
   861  			ux = uint(b[0])
   862  		}
   863  		if signed {
   864  			ux <<= 1
   865  			if negative {
   866  				ux--
   867  			}
   868  		}
   869  		if ux < maxSmall {
   870  			w.data.WriteByte(byte(ux))
   871  			return
   872  		}
   873  	}
   874  
   875  	n := 256 - uint(len(b))
   876  	if signed {
   877  		n = 256 - 2*uint(len(b))
   878  		if negative {
   879  			n |= 1
   880  		}
   881  	}
   882  	if n < maxSmall || n >= 256 {
   883  		Fatalf("encoding mistake: %d, %v, %v => %d", len(b), signed, negative, n)
   884  	}
   885  
   886  	w.data.WriteByte(byte(n))
   887  	w.data.Write(b)
   888  }
   889  
   890  // mpfloat exports a multi-precision floating point number.
   891  //
   892  // The number's value is decomposed into mantissa × 2**exponent, where
   893  // mantissa is an integer. The value is written out as mantissa (as a
   894  // multi-precision integer) and then the exponent, except exponent is
   895  // omitted if mantissa is zero.
   896  func (w *exportWriter) mpfloat(f *big.Float, typ *types.Type) {
   897  	if f.IsInf() {
   898  		Fatalf("infinite constant")
   899  	}
   900  
   901  	// Break into f = mant × 2**exp, with 0.5 <= mant < 1.
   902  	var mant big.Float
   903  	exp := int64(f.MantExp(&mant))
   904  
   905  	// Scale so that mant is an integer.
   906  	prec := mant.MinPrec()
   907  	mant.SetMantExp(&mant, int(prec))
   908  	exp -= int64(prec)
   909  
   910  	manti, acc := mant.Int(nil)
   911  	if acc != big.Exact {
   912  		Fatalf("mantissa scaling failed for %f (%s)", f, acc)
   913  	}
   914  	w.mpint(manti, typ)
   915  	if manti.Sign() != 0 {
   916  		w.int64(exp)
   917  	}
   918  }
   919  
   920  func (w *exportWriter) bool(b bool) bool {
   921  	var x uint64
   922  	if b {
   923  		x = 1
   924  	}
   925  	w.uint64(x)
   926  	return b
   927  }
   928  
   929  func (w *exportWriter) int64(x int64)   { w.data.int64(x) }
   930  func (w *exportWriter) uint64(x uint64) { w.data.uint64(x) }
   931  func (w *exportWriter) string(s string) { w.uint64(w.p.stringOff(s)) }
   932  
   933  // Compiler-specific extensions.
   934  
   935  func (w *exportWriter) varExt(n *Node) {
   936  	w.linkname(n.Sym)
   937  }
   938  
   939  func (w *exportWriter) funcExt(n *Node) {
   940  	w.linkname(n.Sym)
   941  
   942  	// Escape analysis.
   943  	for _, fs := range types.RecvsParams {
   944  		for _, f := range fs(n.Type).FieldSlice() {
   945  			w.string(f.Note)
   946  		}
   947  	}
   948  
   949  	// Inline body.
   950  	if n.Func.Inl != nil {
   951  		w.uint64(1 + uint64(n.Func.Inl.Cost))
   952  		if n.Func.ExportInline() {
   953  			w.p.doInline(n)
   954  		}
   955  
   956  		// Endlineno for inlined function.
   957  		if n.Name.Defn != nil {
   958  			w.pos(n.Name.Defn.Func.Endlineno)
   959  		} else {
   960  			// When the exported node was defined externally,
   961  			// e.g. io exports atomic.(*Value).Load or bytes exports errors.New.
   962  			// Keep it as we don't distinguish this case in iimport.go.
   963  			w.pos(n.Func.Endlineno)
   964  		}
   965  	} else {
   966  		w.uint64(0)
   967  	}
   968  }
   969  
   970  func (w *exportWriter) methExt(m *types.Field) {
   971  	w.bool(m.Nointerface())
   972  	w.funcExt(asNode(m.Type.Nname()))
   973  }
   974  
   975  func (w *exportWriter) linkname(s *types.Sym) {
   976  	w.string(s.Linkname)
   977  }
   978  
   979  // Inline bodies.
   980  
   981  func (w *exportWriter) stmtList(list Nodes) {
   982  	for _, n := range list.Slice() {
   983  		w.node(n)
   984  	}
   985  	w.op(OEND)
   986  }
   987  
   988  func (w *exportWriter) node(n *Node) {
   989  	if opprec[n.Op] < 0 {
   990  		w.stmt(n)
   991  	} else {
   992  		w.expr(n)
   993  	}
   994  }
   995  
   996  // Caution: stmt will emit more than one node for statement nodes n that have a non-empty
   997  // n.Ninit and where n cannot have a natural init section (such as in "if", "for", etc.).
   998  func (w *exportWriter) stmt(n *Node) {
   999  	if n.Ninit.Len() > 0 && !stmtwithinit(n.Op) {
  1000  		// can't use stmtList here since we don't want the final OEND
  1001  		for _, n := range n.Ninit.Slice() {
  1002  			w.stmt(n)
  1003  		}
  1004  	}
  1005  
  1006  	switch op := n.Op; op {
  1007  	case ODCL:
  1008  		w.op(ODCL)
  1009  		w.pos(n.Left.Pos)
  1010  		w.localName(n.Left)
  1011  		w.typ(n.Left.Type)
  1012  
  1013  	// case ODCLFIELD:
  1014  	//	unimplemented - handled by default case
  1015  
  1016  	case OAS:
  1017  		// Don't export "v = <N>" initializing statements, hope they're always
  1018  		// preceded by the DCL which will be re-parsed and typecheck to reproduce
  1019  		// the "v = <N>" again.
  1020  		if n.Right != nil {
  1021  			w.op(OAS)
  1022  			w.pos(n.Pos)
  1023  			w.expr(n.Left)
  1024  			w.expr(n.Right)
  1025  		}
  1026  
  1027  	case OASOP:
  1028  		w.op(OASOP)
  1029  		w.pos(n.Pos)
  1030  		w.op(n.SubOp())
  1031  		w.expr(n.Left)
  1032  		if w.bool(!n.Implicit()) {
  1033  			w.expr(n.Right)
  1034  		}
  1035  
  1036  	case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
  1037  		w.op(OAS2)
  1038  		w.pos(n.Pos)
  1039  		w.exprList(n.List)
  1040  		w.exprList(n.Rlist)
  1041  
  1042  	case ORETURN:
  1043  		w.op(ORETURN)
  1044  		w.pos(n.Pos)
  1045  		w.exprList(n.List)
  1046  
  1047  	// case ORETJMP:
  1048  	// 	unreachable - generated by compiler for trampolin routines
  1049  
  1050  	case OGO, ODEFER:
  1051  		w.op(op)
  1052  		w.pos(n.Pos)
  1053  		w.expr(n.Left)
  1054  
  1055  	case OIF:
  1056  		w.op(OIF)
  1057  		w.pos(n.Pos)
  1058  		w.stmtList(n.Ninit)
  1059  		w.expr(n.Left)
  1060  		w.stmtList(n.Nbody)
  1061  		w.stmtList(n.Rlist)
  1062  
  1063  	case OFOR:
  1064  		w.op(OFOR)
  1065  		w.pos(n.Pos)
  1066  		w.stmtList(n.Ninit)
  1067  		w.exprsOrNil(n.Left, n.Right)
  1068  		w.stmtList(n.Nbody)
  1069  
  1070  	case ORANGE:
  1071  		w.op(ORANGE)
  1072  		w.pos(n.Pos)
  1073  		w.stmtList(n.List)
  1074  		w.expr(n.Right)
  1075  		w.stmtList(n.Nbody)
  1076  
  1077  	case OSELECT, OSWITCH:
  1078  		w.op(op)
  1079  		w.pos(n.Pos)
  1080  		w.stmtList(n.Ninit)
  1081  		w.exprsOrNil(n.Left, nil)
  1082  		w.stmtList(n.List)
  1083  
  1084  	case OCASE, OXCASE:
  1085  		w.op(OXCASE)
  1086  		w.pos(n.Pos)
  1087  		w.stmtList(n.List)
  1088  		w.stmtList(n.Nbody)
  1089  
  1090  	case OFALL:
  1091  		w.op(OFALL)
  1092  		w.pos(n.Pos)
  1093  
  1094  	case OBREAK, OCONTINUE:
  1095  		w.op(op)
  1096  		w.pos(n.Pos)
  1097  		w.exprsOrNil(n.Left, nil)
  1098  
  1099  	case OEMPTY:
  1100  		// nothing to emit
  1101  
  1102  	case OGOTO, OLABEL:
  1103  		w.op(op)
  1104  		w.pos(n.Pos)
  1105  		w.string(n.Sym.Name)
  1106  
  1107  	default:
  1108  		Fatalf("exporter: CANNOT EXPORT: %v\nPlease notify gri@\n", n.Op)
  1109  	}
  1110  }
  1111  
  1112  func (w *exportWriter) exprList(list Nodes) {
  1113  	for _, n := range list.Slice() {
  1114  		w.expr(n)
  1115  	}
  1116  	w.op(OEND)
  1117  }
  1118  
  1119  func (w *exportWriter) expr(n *Node) {
  1120  	// from nodefmt (fmt.go)
  1121  	//
  1122  	// nodefmt reverts nodes back to their original - we don't need to do
  1123  	// it because we are not bound to produce valid Go syntax when exporting
  1124  	//
  1125  	// if (fmtmode != FExp || n.Op != OLITERAL) && n.Orig != nil {
  1126  	// 	n = n.Orig
  1127  	// }
  1128  
  1129  	// from exprfmt (fmt.go)
  1130  	for n.Op == OPAREN || n.Implicit() && (n.Op == ODEREF || n.Op == OADDR || n.Op == ODOT || n.Op == ODOTPTR) {
  1131  		n = n.Left
  1132  	}
  1133  
  1134  	switch op := n.Op; op {
  1135  	// expressions
  1136  	// (somewhat closely following the structure of exprfmt in fmt.go)
  1137  	case OLITERAL:
  1138  		if n.Val().Ctype() == CTNIL && n.Orig != nil && n.Orig != n {
  1139  			w.expr(n.Orig)
  1140  			break
  1141  		}
  1142  		w.op(OLITERAL)
  1143  		w.pos(n.Pos)
  1144  		w.value(n.Type, n.Val())
  1145  
  1146  	case ONAME:
  1147  		// Special case: explicit name of func (*T) method(...) is turned into pkg.(*T).method,
  1148  		// but for export, this should be rendered as (*pkg.T).meth.
  1149  		// These nodes have the special property that they are names with a left OTYPE and a right ONAME.
  1150  		if n.isMethodExpression() {
  1151  			w.op(OXDOT)
  1152  			w.pos(n.Pos)
  1153  			w.expr(n.Left) // n.Left.Op == OTYPE
  1154  			w.selector(n.Right.Sym)
  1155  			break
  1156  		}
  1157  
  1158  		// Package scope name.
  1159  		if (n.Class() == PEXTERN || n.Class() == PFUNC) && !n.isBlank() {
  1160  			w.op(ONONAME)
  1161  			w.qualifiedIdent(n)
  1162  			break
  1163  		}
  1164  
  1165  		// Function scope name.
  1166  		w.op(ONAME)
  1167  		w.localName(n)
  1168  
  1169  	// case OPACK, ONONAME:
  1170  	// 	should have been resolved by typechecking - handled by default case
  1171  
  1172  	case OTYPE:
  1173  		w.op(OTYPE)
  1174  		w.typ(n.Type)
  1175  
  1176  	// case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
  1177  	// 	should have been resolved by typechecking - handled by default case
  1178  
  1179  	// case OCLOSURE:
  1180  	//	unimplemented - handled by default case
  1181  
  1182  	// case OCOMPLIT:
  1183  	// 	should have been resolved by typechecking - handled by default case
  1184  
  1185  	case OPTRLIT:
  1186  		w.op(OPTRLIT)
  1187  		w.pos(n.Pos)
  1188  		w.expr(n.Left)
  1189  		w.bool(n.Implicit())
  1190  
  1191  	case OSTRUCTLIT:
  1192  		w.op(OSTRUCTLIT)
  1193  		w.pos(n.Pos)
  1194  		w.typ(n.Type)
  1195  		w.elemList(n.List) // special handling of field names
  1196  
  1197  	case OARRAYLIT, OSLICELIT, OMAPLIT:
  1198  		w.op(OCOMPLIT)
  1199  		w.pos(n.Pos)
  1200  		w.typ(n.Type)
  1201  		w.exprList(n.List)
  1202  
  1203  	case OKEY:
  1204  		w.op(OKEY)
  1205  		w.pos(n.Pos)
  1206  		w.exprsOrNil(n.Left, n.Right)
  1207  
  1208  	// case OSTRUCTKEY:
  1209  	//	unreachable - handled in case OSTRUCTLIT by elemList
  1210  
  1211  	// case OCALLPART:
  1212  	//	unimplemented - handled by default case
  1213  
  1214  	case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
  1215  		w.op(OXDOT)
  1216  		w.pos(n.Pos)
  1217  		w.expr(n.Left)
  1218  		w.selector(n.Sym)
  1219  
  1220  	case ODOTTYPE, ODOTTYPE2:
  1221  		w.op(ODOTTYPE)
  1222  		w.pos(n.Pos)
  1223  		w.expr(n.Left)
  1224  		w.typ(n.Type)
  1225  
  1226  	case OINDEX, OINDEXMAP:
  1227  		w.op(OINDEX)
  1228  		w.pos(n.Pos)
  1229  		w.expr(n.Left)
  1230  		w.expr(n.Right)
  1231  
  1232  	case OSLICE, OSLICESTR, OSLICEARR:
  1233  		w.op(OSLICE)
  1234  		w.pos(n.Pos)
  1235  		w.expr(n.Left)
  1236  		low, high, _ := n.SliceBounds()
  1237  		w.exprsOrNil(low, high)
  1238  
  1239  	case OSLICE3, OSLICE3ARR:
  1240  		w.op(OSLICE3)
  1241  		w.pos(n.Pos)
  1242  		w.expr(n.Left)
  1243  		low, high, max := n.SliceBounds()
  1244  		w.exprsOrNil(low, high)
  1245  		w.expr(max)
  1246  
  1247  	case OCOPY, OCOMPLEX:
  1248  		// treated like other builtin calls (see e.g., OREAL)
  1249  		w.op(op)
  1250  		w.pos(n.Pos)
  1251  		w.expr(n.Left)
  1252  		w.expr(n.Right)
  1253  		w.op(OEND)
  1254  
  1255  	case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, ORUNES2STR, OSTR2BYTES, OSTR2RUNES, ORUNESTR:
  1256  		w.op(OCONV)
  1257  		w.pos(n.Pos)
  1258  		w.expr(n.Left)
  1259  		w.typ(n.Type)
  1260  
  1261  	case OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN:
  1262  		w.op(op)
  1263  		w.pos(n.Pos)
  1264  		if n.Left != nil {
  1265  			w.expr(n.Left)
  1266  			w.op(OEND)
  1267  		} else {
  1268  			w.exprList(n.List) // emits terminating OEND
  1269  		}
  1270  		// only append() calls may contain '...' arguments
  1271  		if op == OAPPEND {
  1272  			w.bool(n.IsDDD())
  1273  		} else if n.IsDDD() {
  1274  			Fatalf("exporter: unexpected '...' with %v call", op)
  1275  		}
  1276  
  1277  	case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG:
  1278  		w.op(OCALL)
  1279  		w.pos(n.Pos)
  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  	if i := strings.LastIndex(name, "."); i >= 0 {
  1391  		Fatalf("unexpected dot in identifier: %v", name)
  1392  	}
  1393  
  1394  	if v > 0 {
  1395  		if strings.Contains(name, "·") {
  1396  			Fatalf("exporter: unexpected · in symbol name")
  1397  		}
  1398  		name = fmt.Sprintf("%s·%d", name, v)
  1399  	}
  1400  
  1401  	if !ast.IsExported(name) && s.Pkg != w.currPkg {
  1402  		Fatalf("weird package in name: %v => %v, not %q", s, name, w.currPkg.Path)
  1403  	}
  1404  
  1405  	w.string(name)
  1406  }
  1407  
  1408  type intWriter struct {
  1409  	bytes.Buffer
  1410  }
  1411  
  1412  func (w *intWriter) int64(x int64) {
  1413  	var buf [binary.MaxVarintLen64]byte
  1414  	n := binary.PutVarint(buf[:], x)
  1415  	w.Write(buf[:n])
  1416  }
  1417  
  1418  func (w *intWriter) uint64(x uint64) {
  1419  	var buf [binary.MaxVarintLen64]byte
  1420  	n := binary.PutUvarint(buf[:], x)
  1421  	w.Write(buf[:n])
  1422  }