github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/src/cmd/compile/internal/gc/bexport.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Binary package export. 6 // (see fmt.go, parser.go as "documentation" for how to use/setup data structures) 7 8 /* 9 1) Export data encoding principles: 10 11 The export data is a serialized description of the graph of exported 12 "objects": constants, types, variables, and functions. Aliases may be 13 directly reexported, and unaliased types may be indirectly reexported 14 (as part of the type of a directly exported object). More generally, 15 objects referred to from inlined function bodies can be reexported. 16 We need to know which package declares these reexported objects, and 17 therefore packages are also part of the export graph. 18 19 The roots of the graph are two lists of objects. The 1st list (phase 1, 20 see Export) contains all objects that are exported at the package level. 21 These objects are the full representation of the package's API, and they 22 are the only information a platform-independent tool (e.g., go/types) 23 needs to know to type-check against a package. 24 25 The 2nd list of objects contains all objects referred to from exported 26 inlined function bodies. These objects are needed by the compiler to 27 make sense of the function bodies; the exact list contents are compiler- 28 specific. 29 30 Finally, the export data contains a list of representations for inlined 31 function bodies. The format of this representation is compiler specific. 32 33 The graph is serialized in in-order fashion, starting with the roots. 34 Each object in the graph is serialized by writing its fields sequentially. 35 If the field is a pointer to another object, that object is serialized in 36 place, recursively. Otherwise the field is written in place. Non-pointer 37 fields are all encoded as integer or string values. 38 39 Some objects (packages, types) may be referred to more than once. When 40 reaching an object that was not serialized before, an integer _index_ 41 is assigned to it, starting at 0. In this case, the encoding starts 42 with an integer _tag_ < 0. The tag value indicates the kind of object 43 that follows and that this is the first time that we see this object. 44 If the object was already serialized, the encoding is simply the object 45 index >= 0. An importer can trivially determine if an object needs to 46 be read in for the first time (tag < 0) and entered into the respective 47 object table, or if the object was seen already (index >= 0), in which 48 case the index is used to look up the object in the respective table. 49 50 Before exporting or importing, the type tables are populated with the 51 predeclared types (int, string, error, unsafe.Pointer, etc.). This way 52 they are automatically encoded with a known and fixed type index. 53 54 2) Encoding format: 55 56 The export data starts with two newline-terminated strings: a version 57 string and either an empty string, or "debug", when emitting the debug 58 format. These strings are followed by version-specific encoding options. 59 60 (The Go1.7 version starts with a couple of bytes specifying the format. 61 That format encoding is no longer used but is supported to avoid spurious 62 errors when importing old installed package files.) 63 64 This header is followed by the package object for the exported package, 65 two lists of objects, and the list of inlined function bodies. 66 67 The encoding of objects is straight-forward: Constants, variables, and 68 functions start with their name, type, and possibly a value. Named types 69 record their name and package so that they can be canonicalized: If the 70 same type was imported before via another import, the importer must use 71 the previously imported type pointer so that we have exactly one version 72 (i.e., one pointer) for each named type (and read but discard the current 73 type encoding). Unnamed types simply encode their respective fields. 74 Aliases are encoded starting with their name followed by the original 75 (aliased) object. 76 77 In the encoding, some lists start with the list length. Some lists are 78 terminated with an end marker (usually for lists where we may not know 79 the length a priori). 80 81 Integers use variable-length encoding for compact representation. 82 83 Strings are canonicalized similar to objects that may occur multiple times: 84 If the string was exported already, it is represented by its index only. 85 Otherwise, the export data starts with the negative string length (negative, 86 so we can distinguish from string index), followed by the string bytes. 87 The empty string is mapped to index 0. (The initial format string is an 88 exception; it is encoded as the string bytes followed by a newline). 89 90 The exporter and importer are completely symmetric in implementation: For 91 each encoding routine there is a matching and symmetric decoding routine. 92 This symmetry makes it very easy to change or extend the format: If a new 93 field needs to be encoded, a symmetric change can be made to exporter and 94 importer. 95 96 3) Making changes to the encoding format: 97 98 Any change to the encoding format requires a respective change in the 99 exporter below and a corresponding symmetric change to the importer in 100 bimport.go. 101 102 Furthermore, it requires a corresponding change to go/internal/gcimporter 103 and golang.org/x/tools/go/gcimporter15. Changes to the latter must preserve 104 compatibility with both the last release of the compiler, and with the 105 corresponding compiler at tip. That change is necessarily more involved, 106 as it must switch based on the version number in the export data file. 107 108 It is recommended to turn on debugFormat temporarily when working on format 109 changes as it will help finding encoding/decoding inconsistencies quickly. 110 */ 111 112 package gc 113 114 import ( 115 "bufio" 116 "bytes" 117 "encoding/binary" 118 "fmt" 119 "math/big" 120 "sort" 121 "strings" 122 ) 123 124 // If debugFormat is set, each integer and string value is preceded by a marker 125 // and position information in the encoding. This mechanism permits an importer 126 // to recognize immediately when it is out of sync. The importer recognizes this 127 // mode automatically (i.e., it can import export data produced with debugging 128 // support even if debugFormat is not set at the time of import). This mode will 129 // lead to massively larger export data (by a factor of 2 to 3) and should only 130 // be enabled during development and debugging. 131 // 132 // NOTE: This flag is the first flag to enable if importing dies because of 133 // (suspected) format errors, and whenever a change is made to the format. 134 const debugFormat = false // default: false 135 136 // forceObjFileStability enforces additional constraints in export data 137 // and other parts of the compiler to eliminate object file differences 138 // only due to the choice of export format. 139 // TODO(gri) disable and remove once there is only one export format again 140 const forceObjFileStability = true 141 142 // Current export format version. Increase with each format change. 143 // 3: added aliasTag and export of aliases 144 // 2: removed unused bool in ODCL export 145 // 1: header format change (more regular), export package for _ struct fields 146 // 0: Go1.7 encoding 147 const exportVersion = 3 148 149 // exportInlined enables the export of inlined function bodies and related 150 // dependencies. The compiler should work w/o any loss of functionality with 151 // the flag disabled, but the generated code will lose access to inlined 152 // function bodies across packages, leading to performance bugs. 153 // Leave for debugging. 154 const exportInlined = true // default: true 155 156 // trackAllTypes enables cycle tracking for all types, not just named 157 // types. The existing compiler invariants assume that unnamed types 158 // that are not completely set up are not used, or else there are spurious 159 // errors. 160 // If disabled, only named types are tracked, possibly leading to slightly 161 // less efficient encoding in rare cases. It also prevents the export of 162 // some corner-case type declarations (but those were not handled correctly 163 // with the former textual export format either). 164 // TODO(gri) enable and remove once issues caused by it are fixed 165 const trackAllTypes = false 166 167 type exporter struct { 168 out *bufio.Writer 169 170 // object -> index maps, indexed in order of serialization 171 strIndex map[string]int 172 pkgIndex map[*Pkg]int 173 typIndex map[*Type]int 174 funcList []*Func 175 176 // position encoding 177 posInfoFormat bool 178 prevFile string 179 prevLine int 180 181 // debugging support 182 written int // bytes written 183 indent int // for p.trace 184 trace bool 185 186 // work-around for issue #16369 only 187 nesting int // amount of "nesting" of interface types 188 } 189 190 // export writes the exportlist for localpkg to out and returns the number of bytes written. 191 func export(out *bufio.Writer, trace bool) int { 192 p := exporter{ 193 out: out, 194 strIndex: map[string]int{"": 0}, // empty string is mapped to 0 195 pkgIndex: make(map[*Pkg]int), 196 typIndex: make(map[*Type]int), 197 posInfoFormat: true, 198 trace: trace, 199 } 200 201 // write version info 202 // The version string must start with "version %d" where %d is the version 203 // number. Additional debugging information may follow after a blank; that 204 // text is ignored by the importer. 205 p.rawStringln(fmt.Sprintf("version %d", exportVersion)) 206 var debug string 207 if debugFormat { 208 debug = "debug" 209 } 210 p.rawStringln(debug) // cannot use p.bool since it's affected by debugFormat; also want to see this clearly 211 p.bool(trackAllTypes) 212 p.bool(p.posInfoFormat) 213 214 // --- generic export data --- 215 216 // populate type map with predeclared "known" types 217 predecl := predeclared() 218 for index, typ := range predecl { 219 p.typIndex[typ] = index 220 } 221 if len(p.typIndex) != len(predecl) { 222 Fatalf("exporter: duplicate entries in type map?") 223 } 224 225 // write package data 226 if localpkg.Path != "" { 227 Fatalf("exporter: local package path not empty: %q", localpkg.Path) 228 } 229 p.pkg(localpkg) 230 if p.trace { 231 p.tracef("\n") 232 } 233 234 // export objects 235 // 236 // First, export all exported (package-level) objects; i.e., all objects 237 // in the current exportlist. These objects represent all information 238 // required to import this package and type-check against it; i.e., this 239 // is the platform-independent export data. The format is generic in the 240 // sense that different compilers can use the same representation. 241 // 242 // During this first phase, more objects may be added to the exportlist 243 // (due to inlined function bodies and their dependencies). Export those 244 // objects in a second phase. That data is platform-specific as it depends 245 // on the inlining decisions of the compiler and the representation of the 246 // inlined function bodies. 247 248 // remember initial exportlist length 249 var numglobals = len(exportlist) 250 251 // Phase 1: Export objects in _current_ exportlist; exported objects at 252 // package level. 253 // Use range since we want to ignore objects added to exportlist during 254 // this phase. 255 objcount := 0 256 for _, n := range exportlist { 257 sym := n.Sym 258 259 if sym.Flags&SymExported != 0 { 260 continue 261 } 262 sym.Flags |= SymExported 263 264 // TODO(gri) Closures have dots in their names; 265 // e.g., TestFloatZeroValue.func1 in math/big tests. 266 if strings.Contains(sym.Name, ".") { 267 Fatalf("exporter: unexpected symbol: %v", sym) 268 } 269 270 // TODO(gri) Should we do this check? 271 // if sym.Flags&SymExport == 0 { 272 // continue 273 // } 274 275 if sym.Def == nil { 276 Fatalf("exporter: unknown export symbol: %v", sym) 277 } 278 279 // TODO(gri) Optimization: Probably worthwhile collecting 280 // long runs of constants and export them "in bulk" (saving 281 // tags and types, and making import faster). 282 283 if p.trace { 284 p.tracef("\n") 285 } 286 p.obj(sym) 287 objcount++ 288 } 289 290 // indicate end of list 291 if p.trace { 292 p.tracef("\n") 293 } 294 p.tag(endTag) 295 296 // for self-verification only (redundant) 297 p.int(objcount) 298 299 // --- compiler-specific export data --- 300 301 if p.trace { 302 p.tracef("\n--- compiler-specific export data ---\n[ ") 303 if p.indent != 0 { 304 Fatalf("exporter: incorrect indentation") 305 } 306 } 307 308 // write compiler-specific flags 309 if p.trace { 310 p.tracef("\n") 311 } 312 313 // Phase 2: Export objects added to exportlist during phase 1. 314 // Don't use range since exportlist may grow during this phase 315 // and we want to export all remaining objects. 316 objcount = 0 317 for i := numglobals; exportInlined && i < len(exportlist); i++ { 318 n := exportlist[i] 319 sym := n.Sym 320 321 // TODO(gri) The rest of this loop body is identical with 322 // the loop body above. Leave alone for now since there 323 // are different optimization opportunities, but factor 324 // eventually. 325 326 if sym.Flags&SymExported != 0 { 327 continue 328 } 329 sym.Flags |= SymExported 330 331 // TODO(gri) Closures have dots in their names; 332 // e.g., TestFloatZeroValue.func1 in math/big tests. 333 if strings.Contains(sym.Name, ".") { 334 Fatalf("exporter: unexpected symbol: %v", sym) 335 } 336 337 // TODO(gri) Should we do this check? 338 // if sym.Flags&SymExport == 0 { 339 // continue 340 // } 341 342 if sym.Def == nil { 343 Fatalf("exporter: unknown export symbol: %v", sym) 344 } 345 346 // TODO(gri) Optimization: Probably worthwhile collecting 347 // long runs of constants and export them "in bulk" (saving 348 // tags and types, and making import faster). 349 350 if p.trace { 351 p.tracef("\n") 352 } 353 354 if sym.Flags&SymAlias != 0 { 355 Fatalf("exporter: unexpected alias %v in inlined function body", sym) 356 } 357 358 p.obj(sym) 359 objcount++ 360 } 361 362 // indicate end of list 363 if p.trace { 364 p.tracef("\n") 365 } 366 p.tag(endTag) 367 368 // for self-verification only (redundant) 369 p.int(objcount) 370 371 // --- inlined function bodies --- 372 373 if p.trace { 374 p.tracef("\n--- inlined function bodies ---\n") 375 if p.indent != 0 { 376 Fatalf("exporter: incorrect indentation") 377 } 378 } 379 380 // write inlineable function bodies 381 objcount = 0 382 for i, f := range p.funcList { 383 if f != nil { 384 // function has inlineable body: 385 // write index and body 386 if p.trace { 387 p.tracef("\n----\nfunc { %#v }\n", f.Inl) 388 } 389 p.int(i) 390 p.stmtList(f.Inl) 391 if p.trace { 392 p.tracef("\n") 393 } 394 objcount++ 395 } 396 } 397 398 // indicate end of list 399 if p.trace { 400 p.tracef("\n") 401 } 402 p.int(-1) // invalid index terminates list 403 404 // for self-verification only (redundant) 405 p.int(objcount) 406 407 if p.trace { 408 p.tracef("\n--- end ---\n") 409 } 410 411 // --- end of export data --- 412 413 return p.written 414 } 415 416 func (p *exporter) pkg(pkg *Pkg) { 417 if pkg == nil { 418 Fatalf("exporter: unexpected nil pkg") 419 } 420 421 // if we saw the package before, write its index (>= 0) 422 if i, ok := p.pkgIndex[pkg]; ok { 423 p.index('P', i) 424 return 425 } 426 427 // otherwise, remember the package, write the package tag (< 0) and package data 428 if p.trace { 429 p.tracef("P%d = { ", len(p.pkgIndex)) 430 defer p.tracef("} ") 431 } 432 p.pkgIndex[pkg] = len(p.pkgIndex) 433 434 p.tag(packageTag) 435 p.string(pkg.Name) 436 p.string(pkg.Path) 437 } 438 439 func unidealType(typ *Type, val Val) *Type { 440 // Untyped (ideal) constants get their own type. This decouples 441 // the constant type from the encoding of the constant value. 442 if typ == nil || typ.IsUntyped() { 443 typ = untype(val.Ctype()) 444 } 445 return typ 446 } 447 448 func (p *exporter) obj(sym *Sym) { 449 if sym.Flags&SymAlias != 0 { 450 p.tag(aliasTag) 451 p.pos(nil) // TODO(gri) fix position information 452 // Aliases can only be exported from the package that 453 // declares them (aliases to aliases are resolved to the 454 // original object, and so are uses of aliases in inlined 455 // exported function bodies). Thus, we only need the alias 456 // name without package qualification. 457 if sym.Pkg != localpkg { 458 Fatalf("exporter: export of non-local alias: %v", sym) 459 } 460 p.string(sym.Name) 461 sym = sym.Def.Sym // original object 462 // fall through to export original 463 // Multiple aliases to the same original will cause that 464 // original to be exported multiple times (issue #17636). 465 // TODO(gri) fix this 466 } 467 468 if sym != sym.Def.Sym { 469 Fatalf("exporter: exported object %v is not original %v", sym, sym.Def.Sym) 470 } 471 472 if sym.Flags&SymAlias != 0 { 473 Fatalf("exporter: original object %v marked as alias", sym) 474 } 475 476 // Exported objects may be from different packages because they 477 // may be re-exported via an exported alias or as dependencies in 478 // exported inlined function bodies. Thus, exported object names 479 // must be fully qualified. 480 // 481 // (This can only happen for aliased objects or during phase 2 482 // (exportInlined enabled) of object export. Unaliased Objects 483 // exported in phase 1 (compiler-indendepent objects) are by 484 // definition only the objects from the current package and not 485 // pulled in via inlined function bodies. In that case the package 486 // qualifier is not needed. Possible space optimization.) 487 488 n := sym.Def 489 switch n.Op { 490 case OLITERAL: 491 // constant 492 // TODO(gri) determine if we need the typecheck call here 493 n = typecheck(n, Erv) 494 if n == nil || n.Op != OLITERAL { 495 Fatalf("exporter: dumpexportconst: oconst nil: %v", sym) 496 } 497 498 p.tag(constTag) 499 p.pos(n) 500 // TODO(gri) In inlined functions, constants are used directly 501 // so they should never occur as re-exported objects. We may 502 // not need the qualified name here. See also comment above. 503 // Possible space optimization. 504 p.qualifiedName(sym) 505 p.typ(unidealType(n.Type, n.Val())) 506 p.value(n.Val()) 507 508 case OTYPE: 509 // named type 510 t := n.Type 511 if t.Etype == TFORW { 512 Fatalf("exporter: export of incomplete type %v", sym) 513 } 514 515 p.tag(typeTag) 516 p.typ(t) 517 518 case ONAME: 519 // variable or function 520 n = typecheck(n, Erv|Ecall) 521 if n == nil || n.Type == nil { 522 Fatalf("exporter: variable/function exported but not defined: %v", sym) 523 } 524 525 if n.Type.Etype == TFUNC && n.Class == PFUNC { 526 // function 527 p.tag(funcTag) 528 p.pos(n) 529 p.qualifiedName(sym) 530 531 sig := sym.Def.Type 532 inlineable := isInlineable(sym.Def) 533 534 p.paramList(sig.Params(), inlineable) 535 p.paramList(sig.Results(), inlineable) 536 537 var f *Func 538 if inlineable { 539 f = sym.Def.Func 540 // TODO(gri) re-examine reexportdeplist: 541 // Because we can trivially export types 542 // in-place, we don't need to collect types 543 // inside function bodies in the exportlist. 544 // With an adjusted reexportdeplist used only 545 // by the binary exporter, we can also avoid 546 // the global exportlist. 547 reexportdeplist(f.Inl) 548 } 549 p.funcList = append(p.funcList, f) 550 } else { 551 // variable 552 p.tag(varTag) 553 p.pos(n) 554 p.qualifiedName(sym) 555 p.typ(sym.Def.Type) 556 } 557 558 default: 559 Fatalf("exporter: unexpected export symbol: %v %v", n.Op, sym) 560 } 561 } 562 563 func (p *exporter) pos(n *Node) { 564 if !p.posInfoFormat { 565 return 566 } 567 568 file, line := fileLine(n) 569 if file == p.prevFile { 570 // common case: write line delta 571 // delta == 0 means different file or no line change 572 delta := line - p.prevLine 573 p.int(delta) 574 if delta == 0 { 575 p.int(-1) // -1 means no file change 576 } 577 } else { 578 // different file 579 p.int(0) 580 // Encode filename as length of common prefix with previous 581 // filename, followed by (possibly empty) suffix. Filenames 582 // frequently share path prefixes, so this can save a lot 583 // of space and make export data size less dependent on file 584 // path length. The suffix is unlikely to be empty because 585 // file names tend to end in ".go". 586 n := commonPrefixLen(p.prevFile, file) 587 p.int(n) // n >= 0 588 p.string(file[n:]) // write suffix only 589 p.prevFile = file 590 p.int(line) 591 } 592 p.prevLine = line 593 } 594 595 func fileLine(n *Node) (file string, line int) { 596 if n != nil { 597 file, line = Ctxt.LineHist.AbsFileLine(int(n.Lineno)) 598 } 599 return 600 } 601 602 func commonPrefixLen(a, b string) int { 603 if len(a) > len(b) { 604 a, b = b, a 605 } 606 // len(a) <= len(b) 607 i := 0 608 for i < len(a) && a[i] == b[i] { 609 i++ 610 } 611 return i 612 } 613 614 func isInlineable(n *Node) bool { 615 if exportInlined && n != nil && n.Func != nil && n.Func.Inl.Len() != 0 { 616 // when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet. 617 // currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package 618 if Debug['l'] < 2 { 619 typecheckinl(n) 620 } 621 return true 622 } 623 return false 624 } 625 626 var errorInterface *Type // lazily initialized 627 628 func (p *exporter) typ(t *Type) { 629 if t == nil { 630 Fatalf("exporter: nil type") 631 } 632 633 // Possible optimization: Anonymous pointer types *T where 634 // T is a named type are common. We could canonicalize all 635 // such types *T to a single type PT = *T. This would lead 636 // to at most one *T entry in typIndex, and all future *T's 637 // would be encoded as the respective index directly. Would 638 // save 1 byte (pointerTag) per *T and reduce the typIndex 639 // size (at the cost of a canonicalization map). We can do 640 // this later, without encoding format change. 641 642 // if we saw the type before, write its index (>= 0) 643 if i, ok := p.typIndex[t]; ok { 644 p.index('T', i) 645 return 646 } 647 648 // otherwise, remember the type, write the type tag (< 0) and type data 649 if trackAllTypes { 650 if p.trace { 651 p.tracef("T%d = {>\n", len(p.typIndex)) 652 defer p.tracef("<\n} ") 653 } 654 p.typIndex[t] = len(p.typIndex) 655 } 656 657 // pick off named types 658 if tsym := t.Sym; tsym != nil { 659 if !trackAllTypes { 660 // if we don't track all types, track named types now 661 p.typIndex[t] = len(p.typIndex) 662 } 663 664 // Predeclared types should have been found in the type map. 665 if t.Orig == t { 666 Fatalf("exporter: predeclared type missing from type map?") 667 } 668 669 n := typenod(t) 670 if n.Type != t { 671 Fatalf("exporter: named type definition incorrectly set up") 672 } 673 674 p.tag(namedTag) 675 p.pos(n) 676 p.qualifiedName(tsym) 677 678 // write underlying type 679 orig := t.Orig 680 if orig == errortype { 681 // The error type is the only predeclared type which has 682 // a composite underlying type. When we encode that type, 683 // make sure to encode the underlying interface rather than 684 // the named type again. See also the comment in universe.go 685 // regarding the errortype and issue #15920. 686 if errorInterface == nil { 687 errorInterface = makeErrorInterface() 688 } 689 orig = errorInterface 690 } 691 p.typ(orig) 692 693 // interfaces don't have associated methods 694 if t.Orig.IsInterface() { 695 return 696 } 697 698 // sort methods for reproducible export format 699 // TODO(gri) Determine if they are already sorted 700 // in which case we can drop this step. 701 var methods []*Field 702 for _, m := range t.Methods().Slice() { 703 methods = append(methods, m) 704 } 705 sort.Sort(methodbyname(methods)) 706 p.int(len(methods)) 707 708 if p.trace && len(methods) > 0 { 709 p.tracef("associated methods {>") 710 } 711 712 for _, m := range methods { 713 if p.trace { 714 p.tracef("\n") 715 } 716 if strings.Contains(m.Sym.Name, ".") { 717 Fatalf("invalid symbol name: %s (%v)", m.Sym.Name, m.Sym) 718 } 719 720 p.pos(m.Nname) 721 p.fieldSym(m.Sym, false) 722 723 sig := m.Type 724 mfn := sig.Nname() 725 inlineable := isInlineable(mfn) 726 727 p.paramList(sig.Recvs(), inlineable) 728 p.paramList(sig.Params(), inlineable) 729 p.paramList(sig.Results(), inlineable) 730 p.bool(m.Nointerface) // record go:nointerface pragma value (see also #16243) 731 732 var f *Func 733 if inlineable { 734 f = mfn.Func 735 reexportdeplist(mfn.Func.Inl) 736 } 737 p.funcList = append(p.funcList, f) 738 } 739 740 if p.trace && len(methods) > 0 { 741 p.tracef("<\n} ") 742 } 743 744 return 745 } 746 747 // otherwise we have a type literal 748 switch t.Etype { 749 case TARRAY: 750 if t.isDDDArray() { 751 Fatalf("array bounds should be known at export time: %v", t) 752 } 753 p.tag(arrayTag) 754 p.int64(t.NumElem()) 755 p.typ(t.Elem()) 756 757 case TSLICE: 758 p.tag(sliceTag) 759 p.typ(t.Elem()) 760 761 case TDDDFIELD: 762 // see p.param use of TDDDFIELD 763 p.tag(dddTag) 764 p.typ(t.DDDField()) 765 766 case TSTRUCT: 767 p.tag(structTag) 768 p.fieldList(t) 769 770 case TPTR32, TPTR64: // could use Tptr but these are constants 771 p.tag(pointerTag) 772 p.typ(t.Elem()) 773 774 case TFUNC: 775 p.tag(signatureTag) 776 p.paramList(t.Params(), false) 777 p.paramList(t.Results(), false) 778 779 case TINTER: 780 p.tag(interfaceTag) 781 // gc doesn't separate between embedded interfaces 782 // and methods declared explicitly with an interface 783 p.int(0) // no embedded interfaces 784 785 // Because the compiler flattens interfaces containing 786 // embedded interfaces, it is possible to create interface 787 // types that recur through an unnamed type. 788 // If trackAllTypes is disabled, such recursion is not 789 // detected, leading to a stack overflow during export 790 // (issue #16369). 791 // As a crude work-around we terminate deep recursion 792 // through interface types with an empty interface and 793 // report an error. 794 // This will catch endless recursion, but is unlikely 795 // to trigger for valid, deeply nested types given the 796 // high threshold. 797 // It would be ok to continue without reporting an error 798 // since the export format is valid. But a subsequent 799 // import would import an incorrect type. The textual 800 // exporter does not report an error but importing the 801 // resulting package will lead to a syntax error during 802 // import. 803 // TODO(gri) remove this once we have a permanent fix 804 // for the issue. 805 if p.nesting > 100 { 806 p.int(0) // 0 methods to indicate empty interface 807 yyerrorl(t.Lineno, "cannot export unnamed recursive interface") 808 break 809 } 810 811 p.nesting++ 812 p.methodList(t) 813 p.nesting-- 814 815 case TMAP: 816 p.tag(mapTag) 817 p.typ(t.Key()) 818 p.typ(t.Val()) 819 820 case TCHAN: 821 p.tag(chanTag) 822 p.int(int(t.ChanDir())) 823 p.typ(t.Elem()) 824 825 default: 826 Fatalf("exporter: unexpected type: %v (Etype = %d)", t, t.Etype) 827 } 828 } 829 830 func (p *exporter) qualifiedName(sym *Sym) { 831 p.string(sym.Name) 832 p.pkg(sym.Pkg) 833 } 834 835 func (p *exporter) fieldList(t *Type) { 836 if p.trace && t.NumFields() > 0 { 837 p.tracef("fields {>") 838 defer p.tracef("<\n} ") 839 } 840 841 p.int(t.NumFields()) 842 for _, f := range t.Fields().Slice() { 843 if p.trace { 844 p.tracef("\n") 845 } 846 p.field(f) 847 } 848 } 849 850 func (p *exporter) field(f *Field) { 851 p.pos(f.Nname) 852 p.fieldName(f) 853 p.typ(f.Type) 854 p.string(f.Note) 855 } 856 857 func (p *exporter) methodList(t *Type) { 858 if p.trace && t.NumFields() > 0 { 859 p.tracef("methods {>") 860 defer p.tracef("<\n} ") 861 } 862 863 p.int(t.NumFields()) 864 for _, m := range t.Fields().Slice() { 865 if p.trace { 866 p.tracef("\n") 867 } 868 p.method(m) 869 } 870 } 871 872 func (p *exporter) method(m *Field) { 873 p.pos(m.Nname) 874 p.fieldName(m) 875 p.paramList(m.Type.Params(), false) 876 p.paramList(m.Type.Results(), false) 877 } 878 879 // fieldName is like qualifiedName but it doesn't record the package for exported names. 880 func (p *exporter) fieldName(t *Field) { 881 name := t.Sym.Name 882 if t.Embedded != 0 { 883 name = "" // anonymous field 884 if bname := basetypeName(t.Type); bname != "" && !exportname(bname) { 885 // anonymous field with unexported base type name 886 name = "?" // unexported name to force export of package 887 } 888 } 889 p.string(name) 890 if name != "" && !exportname(name) { 891 p.pkg(t.Sym.Pkg) 892 } 893 } 894 895 func basetypeName(t *Type) string { 896 s := t.Sym 897 if s == nil && t.IsPtr() { 898 s = t.Elem().Sym // deref 899 } 900 // s should exist, but be conservative 901 if s != nil { 902 return s.Name 903 } 904 return "" 905 } 906 907 func (p *exporter) paramList(params *Type, numbered bool) { 908 if !params.IsFuncArgStruct() { 909 Fatalf("exporter: parameter list expected") 910 } 911 912 // use negative length to indicate unnamed parameters 913 // (look at the first parameter only since either all 914 // names are present or all are absent) 915 // 916 // TODO(gri) If we don't have an exported function 917 // body, the parameter names are irrelevant for the 918 // compiler (though they may be of use for other tools). 919 // Possible space optimization. 920 n := params.NumFields() 921 if n > 0 && parName(params.Field(0), numbered) == "" { 922 n = -n 923 } 924 p.int(n) 925 for _, q := range params.Fields().Slice() { 926 p.param(q, n, numbered) 927 } 928 } 929 930 func (p *exporter) param(q *Field, n int, numbered bool) { 931 t := q.Type 932 if q.Isddd { 933 // create a fake type to encode ... just for the p.typ call 934 t = typDDDField(t.Elem()) 935 } 936 p.typ(t) 937 if n > 0 { 938 name := parName(q, numbered) 939 if name == "" { 940 // Sometimes we see an empty name even for n > 0. 941 // This appears to happen for interface methods 942 // with _ (blank) parameter names. Make sure we 943 // have a proper name and package so we don't crash 944 // during import (see also issue #15470). 945 // (parName uses "" instead of "?" as in fmt.go) 946 // TODO(gri) review parameter name encoding 947 name = "_" 948 } 949 p.string(name) 950 if name != "_" { 951 // Because of (re-)exported inlined functions 952 // the importpkg may not be the package to which this 953 // function (and thus its parameter) belongs. We need to 954 // supply the parameter package here. We need the package 955 // when the function is inlined so we can properly resolve 956 // the name. The _ (blank) parameter cannot be accessed, so 957 // we don't need to export a package. 958 // 959 // TODO(gri) This is compiler-specific. Try using importpkg 960 // here and then update the symbols if we find an inlined 961 // body only. Otherwise, the parameter name is ignored and 962 // the package doesn't matter. This would remove an int 963 // (likely 1 byte) for each named parameter. 964 p.pkg(q.Sym.Pkg) 965 } 966 } 967 // TODO(gri) This is compiler-specific (escape info). 968 // Move into compiler-specific section eventually? 969 // (Not having escape info causes tests to fail, e.g. runtime GCInfoTest) 970 p.string(q.Note) 971 } 972 973 func parName(f *Field, numbered bool) string { 974 s := f.Sym 975 if s == nil { 976 return "" 977 } 978 979 // Take the name from the original, lest we substituted it with ~r%d or ~b%d. 980 // ~r%d is a (formerly) unnamed result. 981 if f.Nname != nil { 982 if f.Nname.Orig != nil { 983 s = f.Nname.Orig.Sym 984 if s != nil && s.Name[0] == '~' { 985 if s.Name[1] == 'r' { // originally an unnamed result 986 return "" // s = nil 987 } else if s.Name[1] == 'b' { // originally the blank identifier _ 988 return "_" // belongs to localpkg 989 } 990 } 991 } else { 992 return "" // s = nil 993 } 994 } 995 996 if s == nil { 997 return "" 998 } 999 1000 // print symbol with Vargen number or not as desired 1001 name := s.Name 1002 if strings.Contains(name, ".") { 1003 Fatalf("invalid symbol name: %s", name) 1004 } 1005 1006 // Functions that can be inlined use numbered parameters so we can distingish them 1007 // from other names in their context after inlining (i.e., the parameter numbering 1008 // is a form of parameter rewriting). See issue 4326 for an example and test case. 1009 if forceObjFileStability || numbered { 1010 if !strings.Contains(name, "·") && f.Nname != nil && f.Nname.Name != nil && f.Nname.Name.Vargen > 0 { 1011 name = fmt.Sprintf("%s·%d", name, f.Nname.Name.Vargen) // append Vargen 1012 } 1013 } else { 1014 if i := strings.Index(name, "·"); i > 0 { 1015 name = name[:i] // cut off Vargen 1016 } 1017 } 1018 return name 1019 } 1020 1021 func (p *exporter) value(x Val) { 1022 if p.trace { 1023 p.tracef("= ") 1024 } 1025 1026 switch x := x.U.(type) { 1027 case bool: 1028 tag := falseTag 1029 if x { 1030 tag = trueTag 1031 } 1032 p.tag(tag) 1033 1034 case *Mpint: 1035 if minintval[TINT64].Cmp(x) <= 0 && x.Cmp(maxintval[TINT64]) <= 0 { 1036 // common case: x fits into an int64 - use compact encoding 1037 p.tag(int64Tag) 1038 p.int64(x.Int64()) 1039 return 1040 } 1041 // uncommon case: large x - use float encoding 1042 // (powers of 2 will be encoded efficiently with exponent) 1043 f := newMpflt() 1044 f.SetInt(x) 1045 p.tag(floatTag) 1046 p.float(f) 1047 1048 case *Mpflt: 1049 p.tag(floatTag) 1050 p.float(x) 1051 1052 case *Mpcplx: 1053 p.tag(complexTag) 1054 p.float(&x.Real) 1055 p.float(&x.Imag) 1056 1057 case string: 1058 p.tag(stringTag) 1059 p.string(x) 1060 1061 case *NilVal: 1062 // not a constant but used in exported function bodies 1063 p.tag(nilTag) 1064 1065 default: 1066 Fatalf("exporter: unexpected value %v (%T)", x, x) 1067 } 1068 } 1069 1070 func (p *exporter) float(x *Mpflt) { 1071 // extract sign (there is no -0) 1072 f := &x.Val 1073 sign := f.Sign() 1074 if sign == 0 { 1075 // x == 0 1076 p.int(0) 1077 return 1078 } 1079 // x != 0 1080 1081 // extract exponent such that 0.5 <= m < 1.0 1082 var m big.Float 1083 exp := f.MantExp(&m) 1084 1085 // extract mantissa as *big.Int 1086 // - set exponent large enough so mant satisfies mant.IsInt() 1087 // - get *big.Int from mant 1088 m.SetMantExp(&m, int(m.MinPrec())) 1089 mant, acc := m.Int(nil) 1090 if acc != big.Exact { 1091 Fatalf("exporter: internal error") 1092 } 1093 1094 p.int(sign) 1095 p.int(exp) 1096 p.string(string(mant.Bytes())) 1097 } 1098 1099 // ---------------------------------------------------------------------------- 1100 // Inlined function bodies 1101 1102 // Approach: More or less closely follow what fmt.go is doing for FExp mode 1103 // but instead of emitting the information textually, emit the node tree in 1104 // binary form. 1105 1106 // TODO(gri) Improve tracing output. The current format is difficult to read. 1107 1108 // stmtList may emit more (or fewer) than len(list) nodes. 1109 func (p *exporter) stmtList(list Nodes) { 1110 if p.trace { 1111 if list.Len() == 0 { 1112 p.tracef("{}") 1113 } else { 1114 p.tracef("{>") 1115 defer p.tracef("<\n}") 1116 } 1117 } 1118 1119 for _, n := range list.Slice() { 1120 if p.trace { 1121 p.tracef("\n") 1122 } 1123 // TODO inlining produces expressions with ninits. we can't export these yet. 1124 // (from fmt.go:1461ff) 1125 if opprec[n.Op] < 0 { 1126 p.stmt(n) 1127 } else { 1128 p.expr(n) 1129 } 1130 } 1131 1132 p.op(OEND) 1133 } 1134 1135 func (p *exporter) exprList(list Nodes) { 1136 if p.trace { 1137 if list.Len() == 0 { 1138 p.tracef("{}") 1139 } else { 1140 p.tracef("{>") 1141 defer p.tracef("<\n}") 1142 } 1143 } 1144 1145 for _, n := range list.Slice() { 1146 if p.trace { 1147 p.tracef("\n") 1148 } 1149 p.expr(n) 1150 } 1151 1152 p.op(OEND) 1153 } 1154 1155 func (p *exporter) elemList(list Nodes) { 1156 if p.trace { 1157 p.tracef("[ ") 1158 } 1159 p.int(list.Len()) 1160 if p.trace { 1161 if list.Len() == 0 { 1162 p.tracef("] {}") 1163 } else { 1164 p.tracef("] {>") 1165 defer p.tracef("<\n}") 1166 } 1167 } 1168 1169 for _, n := range list.Slice() { 1170 if p.trace { 1171 p.tracef("\n") 1172 } 1173 p.fieldSym(n.Sym, false) 1174 p.expr(n.Left) 1175 } 1176 } 1177 1178 func (p *exporter) expr(n *Node) { 1179 if p.trace { 1180 p.tracef("( ") 1181 defer p.tracef(") ") 1182 } 1183 1184 // from nodefmt (fmt.go) 1185 // 1186 // nodefmt reverts nodes back to their original - we don't need to do 1187 // it because we are not bound to produce valid Go syntax when exporting 1188 // 1189 // if (fmtmode != FExp || n.Op != OLITERAL) && n.Orig != nil { 1190 // n = n.Orig 1191 // } 1192 1193 // from exprfmt (fmt.go) 1194 for n != nil && n.Implicit && (n.Op == OIND || n.Op == OADDR) { 1195 n = n.Left 1196 } 1197 1198 switch op := n.Op; op { 1199 // expressions 1200 // (somewhat closely following the structure of exprfmt in fmt.go) 1201 case OPAREN: 1202 p.expr(n.Left) // unparen 1203 1204 // case ODDDARG: 1205 // unimplemented - handled by default case 1206 1207 case OLITERAL: 1208 if n.Val().Ctype() == CTNIL && n.Orig != nil && n.Orig != n { 1209 p.expr(n.Orig) 1210 break 1211 } 1212 p.op(OLITERAL) 1213 p.typ(unidealType(n.Type, n.Val())) 1214 p.value(n.Val()) 1215 1216 case ONAME: 1217 // Special case: name used as local variable in export. 1218 // _ becomes ~b%d internally; print as _ for export 1219 if n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' { 1220 p.op(ONAME) 1221 p.string("_") // inlined and customized version of p.sym(n) 1222 break 1223 } 1224 1225 if n.Sym != nil && !isblank(n) && n.Name.Vargen > 0 { 1226 p.op(ONAME) 1227 p.sym(n) 1228 break 1229 } 1230 1231 // Special case: explicit name of func (*T) method(...) is turned into pkg.(*T).method, 1232 // but for export, this should be rendered as (*pkg.T).meth. 1233 // These nodes have the special property that they are names with a left OTYPE and a right ONAME. 1234 if n.Left != nil && n.Left.Op == OTYPE && n.Right != nil && n.Right.Op == ONAME { 1235 p.op(OXDOT) 1236 p.expr(n.Left) // n.Left.Op == OTYPE 1237 p.fieldSym(n.Right.Sym, true) 1238 break 1239 } 1240 1241 p.op(ONAME) 1242 p.sym(n) 1243 1244 // case OPACK, ONONAME: 1245 // should have been resolved by typechecking - handled by default case 1246 1247 case OTYPE: 1248 p.op(OTYPE) 1249 if p.bool(n.Type == nil) { 1250 p.sym(n) 1251 } else { 1252 p.typ(n.Type) 1253 } 1254 1255 // case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC: 1256 // should have been resolved by typechecking - handled by default case 1257 1258 // case OCLOSURE: 1259 // unimplemented - handled by default case 1260 1261 // case OCOMPLIT: 1262 // should have been resolved by typechecking - handled by default case 1263 1264 case OPTRLIT: 1265 p.op(OPTRLIT) 1266 p.expr(n.Left) 1267 p.bool(n.Implicit) 1268 1269 case OSTRUCTLIT: 1270 p.op(OSTRUCTLIT) 1271 p.typ(n.Type) 1272 p.elemList(n.List) // special handling of field names 1273 1274 case OARRAYLIT, OSLICELIT, OMAPLIT: 1275 p.op(OCOMPLIT) 1276 p.typ(n.Type) 1277 p.exprList(n.List) 1278 1279 case OKEY: 1280 p.op(OKEY) 1281 p.exprsOrNil(n.Left, n.Right) 1282 1283 // case OSTRUCTKEY: 1284 // unreachable - handled in case OSTRUCTLIT by elemList 1285 1286 // case OCALLPART: 1287 // unimplemented - handled by default case 1288 1289 case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH: 1290 p.op(OXDOT) 1291 p.expr(n.Left) 1292 p.fieldSym(n.Sym, true) 1293 1294 case ODOTTYPE, ODOTTYPE2: 1295 p.op(ODOTTYPE) 1296 p.expr(n.Left) 1297 if p.bool(n.Right != nil) { 1298 p.expr(n.Right) 1299 } else { 1300 p.typ(n.Type) 1301 } 1302 1303 case OINDEX, OINDEXMAP: 1304 p.op(OINDEX) 1305 p.expr(n.Left) 1306 p.expr(n.Right) 1307 1308 case OSLICE, OSLICESTR, OSLICEARR: 1309 p.op(OSLICE) 1310 p.expr(n.Left) 1311 low, high, _ := n.SliceBounds() 1312 p.exprsOrNil(low, high) 1313 1314 case OSLICE3, OSLICE3ARR: 1315 p.op(OSLICE3) 1316 p.expr(n.Left) 1317 low, high, max := n.SliceBounds() 1318 p.exprsOrNil(low, high) 1319 p.expr(max) 1320 1321 case OCOPY, OCOMPLEX: 1322 // treated like other builtin calls (see e.g., OREAL) 1323 p.op(op) 1324 p.expr(n.Left) 1325 p.expr(n.Right) 1326 p.op(OEND) 1327 1328 case OCONV, OCONVIFACE, OCONVNOP, OARRAYBYTESTR, OARRAYRUNESTR, OSTRARRAYBYTE, OSTRARRAYRUNE, ORUNESTR: 1329 p.op(OCONV) 1330 p.typ(n.Type) 1331 if n.Left != nil { 1332 p.expr(n.Left) 1333 p.op(OEND) 1334 } else { 1335 p.exprList(n.List) // emits terminating OEND 1336 } 1337 1338 case OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN: 1339 p.op(op) 1340 if n.Left != nil { 1341 p.expr(n.Left) 1342 p.op(OEND) 1343 } else { 1344 p.exprList(n.List) // emits terminating OEND 1345 } 1346 // only append() calls may contain '...' arguments 1347 if op == OAPPEND { 1348 p.bool(n.Isddd) 1349 } else if n.Isddd { 1350 Fatalf("exporter: unexpected '...' with %s call", opnames[op]) 1351 } 1352 1353 case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG: 1354 p.op(OCALL) 1355 p.expr(n.Left) 1356 p.exprList(n.List) 1357 p.bool(n.Isddd) 1358 1359 case OMAKEMAP, OMAKECHAN, OMAKESLICE: 1360 p.op(op) // must keep separate from OMAKE for importer 1361 p.typ(n.Type) 1362 switch { 1363 default: 1364 // empty list 1365 p.op(OEND) 1366 case n.List.Len() != 0: // pre-typecheck 1367 p.exprList(n.List) // emits terminating OEND 1368 case n.Right != nil: 1369 p.expr(n.Left) 1370 p.expr(n.Right) 1371 p.op(OEND) 1372 case n.Left != nil && (n.Op == OMAKESLICE || !n.Left.Type.IsUntyped()): 1373 p.expr(n.Left) 1374 p.op(OEND) 1375 } 1376 1377 // unary expressions 1378 case OPLUS, OMINUS, OADDR, OCOM, OIND, ONOT, ORECV: 1379 p.op(op) 1380 p.expr(n.Left) 1381 1382 // binary expressions 1383 case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, OLT, 1384 OLSH, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSEND, OSUB, OXOR: 1385 p.op(op) 1386 p.expr(n.Left) 1387 p.expr(n.Right) 1388 1389 case OADDSTR: 1390 p.op(OADDSTR) 1391 p.exprList(n.List) 1392 1393 case OCMPSTR, OCMPIFACE: 1394 p.op(Op(n.Etype)) 1395 p.expr(n.Left) 1396 p.expr(n.Right) 1397 1398 case ODCLCONST: 1399 // if exporting, DCLCONST should just be removed as its usage 1400 // has already been replaced with literals 1401 // TODO(gri) these should not be exported in the first place 1402 // TODO(gri) why is this considered an expression in fmt.go? 1403 p.op(ODCLCONST) 1404 1405 default: 1406 Fatalf("cannot export %v (%d) node\n"+ 1407 "==> please file an issue and assign to gri@\n", n.Op, int(n.Op)) 1408 } 1409 } 1410 1411 // Caution: stmt will emit more than one node for statement nodes n that have a non-empty 1412 // n.Ninit and where n cannot have a natural init section (such as in "if", "for", etc.). 1413 func (p *exporter) stmt(n *Node) { 1414 if p.trace { 1415 p.tracef("( ") 1416 defer p.tracef(") ") 1417 } 1418 1419 if n.Ninit.Len() > 0 && !stmtwithinit(n.Op) { 1420 if p.trace { 1421 p.tracef("( /* Ninits */ ") 1422 } 1423 1424 // can't use stmtList here since we don't want the final OEND 1425 for _, n := range n.Ninit.Slice() { 1426 p.stmt(n) 1427 } 1428 1429 if p.trace { 1430 p.tracef(") ") 1431 } 1432 } 1433 1434 switch op := n.Op; op { 1435 case ODCL: 1436 p.op(ODCL) 1437 p.sym(n.Left) 1438 p.typ(n.Left.Type) 1439 1440 // case ODCLFIELD: 1441 // unimplemented - handled by default case 1442 1443 case OAS, OASWB: 1444 // Don't export "v = <N>" initializing statements, hope they're always 1445 // preceded by the DCL which will be re-parsed and typecheck to reproduce 1446 // the "v = <N>" again. 1447 if n.Right != nil { 1448 p.op(OAS) 1449 p.expr(n.Left) 1450 p.expr(n.Right) 1451 } 1452 1453 case OASOP: 1454 p.op(OASOP) 1455 p.int(int(n.Etype)) 1456 p.expr(n.Left) 1457 if p.bool(!n.Implicit) { 1458 p.expr(n.Right) 1459 } 1460 1461 case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV: 1462 p.op(OAS2) 1463 p.exprList(n.List) 1464 p.exprList(n.Rlist) 1465 1466 case ORETURN: 1467 p.op(ORETURN) 1468 p.exprList(n.List) 1469 1470 // case ORETJMP: 1471 // unreachable - generated by compiler for trampolin routines 1472 1473 case OPROC, ODEFER: 1474 p.op(op) 1475 p.expr(n.Left) 1476 1477 case OIF: 1478 p.op(OIF) 1479 p.stmtList(n.Ninit) 1480 p.expr(n.Left) 1481 p.stmtList(n.Nbody) 1482 p.stmtList(n.Rlist) 1483 1484 case OFOR: 1485 p.op(OFOR) 1486 p.stmtList(n.Ninit) 1487 p.exprsOrNil(n.Left, n.Right) 1488 p.stmtList(n.Nbody) 1489 1490 case ORANGE: 1491 p.op(ORANGE) 1492 p.stmtList(n.List) 1493 p.expr(n.Right) 1494 p.stmtList(n.Nbody) 1495 1496 case OSELECT, OSWITCH: 1497 p.op(op) 1498 p.stmtList(n.Ninit) 1499 p.exprsOrNil(n.Left, nil) 1500 p.stmtList(n.List) 1501 1502 case OCASE, OXCASE: 1503 p.op(OXCASE) 1504 p.stmtList(n.List) 1505 p.stmtList(n.Nbody) 1506 1507 case OFALL, OXFALL: 1508 p.op(OXFALL) 1509 1510 case OBREAK, OCONTINUE: 1511 p.op(op) 1512 p.exprsOrNil(n.Left, nil) 1513 1514 case OEMPTY: 1515 // nothing to emit 1516 1517 case OGOTO, OLABEL: 1518 p.op(op) 1519 p.expr(n.Left) 1520 1521 default: 1522 Fatalf("exporter: CANNOT EXPORT: %v\nPlease notify gri@\n", n.Op) 1523 } 1524 } 1525 1526 func (p *exporter) exprsOrNil(a, b *Node) { 1527 ab := 0 1528 if a != nil { 1529 ab |= 1 1530 } 1531 if b != nil { 1532 ab |= 2 1533 } 1534 p.int(ab) 1535 if ab&1 != 0 { 1536 p.expr(a) 1537 } 1538 if ab&2 != 0 { 1539 p.expr(b) 1540 } 1541 } 1542 1543 func (p *exporter) fieldSym(s *Sym, short bool) { 1544 name := s.Name 1545 1546 // remove leading "type." in method names ("(T).m" -> "m") 1547 if short { 1548 if i := strings.LastIndex(name, "."); i >= 0 { 1549 name = name[i+1:] 1550 } 1551 } 1552 1553 // we should never see a _ (blank) here - these are accessible ("read") fields 1554 // TODO(gri) can we assert this with an explicit check? 1555 p.string(name) 1556 if !exportname(name) { 1557 p.pkg(s.Pkg) 1558 } 1559 } 1560 1561 // sym must encode the _ (blank) identifier as a single string "_" since 1562 // encoding for some nodes is based on this assumption (e.g. ONAME nodes). 1563 func (p *exporter) sym(n *Node) { 1564 s := n.Sym 1565 if s.Pkg != nil { 1566 if len(s.Name) > 0 && s.Name[0] == '.' { 1567 Fatalf("exporter: exporting synthetic symbol %s", s.Name) 1568 } 1569 } 1570 1571 if p.trace { 1572 p.tracef("{ SYM ") 1573 defer p.tracef("} ") 1574 } 1575 1576 name := s.Name 1577 1578 // remove leading "type." in method names ("(T).m" -> "m") 1579 if i := strings.LastIndex(name, "."); i >= 0 { 1580 name = name[i+1:] 1581 } 1582 1583 if strings.Contains(name, "·") && n.Name.Vargen > 0 { 1584 Fatalf("exporter: unexpected · in symbol name") 1585 } 1586 1587 if i := n.Name.Vargen; i > 0 { 1588 name = fmt.Sprintf("%s·%d", name, i) 1589 } 1590 1591 p.string(name) 1592 if name != "_" { 1593 p.pkg(s.Pkg) 1594 } 1595 } 1596 1597 func (p *exporter) bool(b bool) bool { 1598 if p.trace { 1599 p.tracef("[") 1600 defer p.tracef("= %v] ", b) 1601 } 1602 1603 x := 0 1604 if b { 1605 x = 1 1606 } 1607 p.int(x) 1608 return b 1609 } 1610 1611 func (p *exporter) op(op Op) { 1612 if p.trace { 1613 p.tracef("[") 1614 defer p.tracef("= %v] ", op) 1615 } 1616 1617 p.int(int(op)) 1618 } 1619 1620 // ---------------------------------------------------------------------------- 1621 // Low-level encoders 1622 1623 func (p *exporter) index(marker byte, index int) { 1624 if index < 0 { 1625 Fatalf("exporter: invalid index < 0") 1626 } 1627 if debugFormat { 1628 p.marker('t') 1629 } 1630 if p.trace { 1631 p.tracef("%c%d ", marker, index) 1632 } 1633 p.rawInt64(int64(index)) 1634 } 1635 1636 func (p *exporter) tag(tag int) { 1637 if tag >= 0 { 1638 Fatalf("exporter: invalid tag >= 0") 1639 } 1640 if debugFormat { 1641 p.marker('t') 1642 } 1643 if p.trace { 1644 p.tracef("%s ", tagString[-tag]) 1645 } 1646 p.rawInt64(int64(tag)) 1647 } 1648 1649 func (p *exporter) int(x int) { 1650 p.int64(int64(x)) 1651 } 1652 1653 func (p *exporter) int64(x int64) { 1654 if debugFormat { 1655 p.marker('i') 1656 } 1657 if p.trace { 1658 p.tracef("%d ", x) 1659 } 1660 p.rawInt64(x) 1661 } 1662 1663 func (p *exporter) string(s string) { 1664 if debugFormat { 1665 p.marker('s') 1666 } 1667 if p.trace { 1668 p.tracef("%q ", s) 1669 } 1670 // if we saw the string before, write its index (>= 0) 1671 // (the empty string is mapped to 0) 1672 if i, ok := p.strIndex[s]; ok { 1673 p.rawInt64(int64(i)) 1674 return 1675 } 1676 // otherwise, remember string and write its negative length and bytes 1677 p.strIndex[s] = len(p.strIndex) 1678 p.rawInt64(-int64(len(s))) 1679 for i := 0; i < len(s); i++ { 1680 p.rawByte(s[i]) 1681 } 1682 } 1683 1684 // marker emits a marker byte and position information which makes 1685 // it easy for a reader to detect if it is "out of sync". Used only 1686 // if debugFormat is set. 1687 func (p *exporter) marker(m byte) { 1688 p.rawByte(m) 1689 // Uncomment this for help tracking down the location 1690 // of an incorrect marker when running in debugFormat. 1691 // if p.trace { 1692 // p.tracef("#%d ", p.written) 1693 // } 1694 p.rawInt64(int64(p.written)) 1695 } 1696 1697 // rawInt64 should only be used by low-level encoders. 1698 func (p *exporter) rawInt64(x int64) { 1699 var tmp [binary.MaxVarintLen64]byte 1700 n := binary.PutVarint(tmp[:], x) 1701 for i := 0; i < n; i++ { 1702 p.rawByte(tmp[i]) 1703 } 1704 } 1705 1706 // rawStringln should only be used to emit the initial version string. 1707 func (p *exporter) rawStringln(s string) { 1708 for i := 0; i < len(s); i++ { 1709 p.rawByte(s[i]) 1710 } 1711 p.rawByte('\n') 1712 } 1713 1714 // rawByte is the bottleneck interface to write to p.out. 1715 // rawByte escapes b as follows (any encoding does that 1716 // hides '$'): 1717 // 1718 // '$' => '|' 'S' 1719 // '|' => '|' '|' 1720 // 1721 // Necessary so other tools can find the end of the 1722 // export data by searching for "$$". 1723 // rawByte should only be used by low-level encoders. 1724 func (p *exporter) rawByte(b byte) { 1725 switch b { 1726 case '$': 1727 // write '$' as '|' 'S' 1728 b = 'S' 1729 fallthrough 1730 case '|': 1731 // write '|' as '|' '|' 1732 p.out.WriteByte('|') 1733 p.written++ 1734 } 1735 p.out.WriteByte(b) 1736 p.written++ 1737 } 1738 1739 // tracef is like fmt.Printf but it rewrites the format string 1740 // to take care of indentation. 1741 func (p *exporter) tracef(format string, args ...interface{}) { 1742 if strings.ContainsAny(format, "<>\n") { 1743 var buf bytes.Buffer 1744 for i := 0; i < len(format); i++ { 1745 // no need to deal with runes 1746 ch := format[i] 1747 switch ch { 1748 case '>': 1749 p.indent++ 1750 continue 1751 case '<': 1752 p.indent-- 1753 continue 1754 } 1755 buf.WriteByte(ch) 1756 if ch == '\n' { 1757 for j := p.indent; j > 0; j-- { 1758 buf.WriteString(". ") 1759 } 1760 } 1761 } 1762 format = buf.String() 1763 } 1764 fmt.Printf(format, args...) 1765 } 1766 1767 // ---------------------------------------------------------------------------- 1768 // Export format 1769 1770 // Tags. Must be < 0. 1771 const ( 1772 // Objects 1773 packageTag = -(iota + 1) 1774 constTag 1775 typeTag 1776 varTag 1777 funcTag 1778 endTag 1779 1780 // Types 1781 namedTag 1782 arrayTag 1783 sliceTag 1784 dddTag 1785 structTag 1786 pointerTag 1787 signatureTag 1788 interfaceTag 1789 mapTag 1790 chanTag 1791 1792 // Values 1793 falseTag 1794 trueTag 1795 int64Tag 1796 floatTag 1797 fractionTag // not used by gc 1798 complexTag 1799 stringTag 1800 nilTag 1801 unknownTag // not used by gc (only appears in packages with errors) 1802 1803 // Aliases 1804 aliasTag 1805 ) 1806 1807 // Debugging support. 1808 // (tagString is only used when tracing is enabled) 1809 var tagString = [...]string{ 1810 // Objects 1811 -packageTag: "package", 1812 -constTag: "const", 1813 -typeTag: "type", 1814 -varTag: "var", 1815 -funcTag: "func", 1816 -endTag: "end", 1817 1818 // Types 1819 -namedTag: "named type", 1820 -arrayTag: "array", 1821 -sliceTag: "slice", 1822 -dddTag: "ddd", 1823 -structTag: "struct", 1824 -pointerTag: "pointer", 1825 -signatureTag: "signature", 1826 -interfaceTag: "interface", 1827 -mapTag: "map", 1828 -chanTag: "chan", 1829 1830 // Values 1831 -falseTag: "false", 1832 -trueTag: "true", 1833 -int64Tag: "int64", 1834 -floatTag: "float", 1835 -fractionTag: "fraction", 1836 -complexTag: "complex", 1837 -stringTag: "string", 1838 -nilTag: "nil", 1839 -unknownTag: "unknown", 1840 1841 // Aliases 1842 -aliasTag: "alias", 1843 } 1844 1845 // untype returns the "pseudo" untyped type for a Ctype (import/export use only). 1846 // (we can't use an pre-initialized array because we must be sure all types are 1847 // set up) 1848 func untype(ctype Ctype) *Type { 1849 switch ctype { 1850 case CTINT: 1851 return idealint 1852 case CTRUNE: 1853 return idealrune 1854 case CTFLT: 1855 return idealfloat 1856 case CTCPLX: 1857 return idealcomplex 1858 case CTSTR: 1859 return idealstring 1860 case CTBOOL: 1861 return idealbool 1862 case CTNIL: 1863 return Types[TNIL] 1864 } 1865 Fatalf("exporter: unknown Ctype") 1866 return nil 1867 } 1868 1869 var predecl []*Type // initialized lazily 1870 1871 func predeclared() []*Type { 1872 if predecl == nil { 1873 // initialize lazily to be sure that all 1874 // elements have been initialized before 1875 predecl = []*Type{ 1876 // basic types 1877 Types[TBOOL], 1878 Types[TINT], 1879 Types[TINT8], 1880 Types[TINT16], 1881 Types[TINT32], 1882 Types[TINT64], 1883 Types[TUINT], 1884 Types[TUINT8], 1885 Types[TUINT16], 1886 Types[TUINT32], 1887 Types[TUINT64], 1888 Types[TUINTPTR], 1889 Types[TFLOAT32], 1890 Types[TFLOAT64], 1891 Types[TCOMPLEX64], 1892 Types[TCOMPLEX128], 1893 Types[TSTRING], 1894 1895 // aliases 1896 bytetype, 1897 runetype, 1898 1899 // error 1900 errortype, 1901 1902 // untyped types 1903 untype(CTBOOL), 1904 untype(CTINT), 1905 untype(CTRUNE), 1906 untype(CTFLT), 1907 untype(CTCPLX), 1908 untype(CTSTR), 1909 untype(CTNIL), 1910 1911 // package unsafe 1912 Types[TUNSAFEPTR], 1913 1914 // invalid type (package contains errors) 1915 Types[Txxx], 1916 1917 // any type, for builtin export data 1918 Types[TANY], 1919 } 1920 } 1921 return predecl 1922 }