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