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