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