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