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