github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/src/cmd/compile/internal/gc/bimport.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 import. 6 // See bexport.go for the export data format and how 7 // to make a format change. 8 9 package gc 10 11 import ( 12 "bufio" 13 "encoding/binary" 14 "fmt" 15 "math/big" 16 "strconv" 17 "strings" 18 ) 19 20 // The overall structure of Import is symmetric to Export: For each 21 // export method in bexport.go there is a matching and symmetric method 22 // in bimport.go. Changing the export format requires making symmetric 23 // changes to bimport.go and bexport.go. 24 25 type importer struct { 26 in *bufio.Reader 27 buf []byte // reused for reading strings 28 version int // export format version 29 30 // object lists, in order of deserialization 31 strList []string 32 pkgList []*Pkg 33 typList []*Type 34 funcList []*Node // nil entry means already declared 35 trackAllTypes bool 36 37 // for delayed type verification 38 cmpList []struct{ pt, t *Type } 39 40 // position encoding 41 posInfoFormat bool 42 prevFile string 43 prevLine int 44 45 // debugging support 46 debugFormat bool 47 read int // bytes read 48 } 49 50 // Import populates importpkg from the serialized package data. 51 func Import(in *bufio.Reader) { 52 p := importer{ 53 in: in, 54 version: -1, // unknown version 55 strList: []string{""}, // empty string is mapped to 0 56 } 57 58 // read version info 59 var versionstr string 60 if b := p.rawByte(); b == 'c' || b == 'd' { 61 // Go1.7 encoding; first byte encodes low-level 62 // encoding format (compact vs debug). 63 // For backward-compatibility only (avoid problems with 64 // old installed packages). Newly compiled packages use 65 // the extensible format string. 66 // TODO(gri) Remove this support eventually; after Go1.8. 67 if b == 'd' { 68 p.debugFormat = true 69 } 70 p.trackAllTypes = p.rawByte() == 'a' 71 p.posInfoFormat = p.bool() 72 versionstr = p.string() 73 if versionstr == "v1" { 74 p.version = 0 75 } 76 } else { 77 // Go1.8 extensible encoding 78 // read version string and extract version number (ignore anything after the version number) 79 versionstr = p.rawStringln(b) 80 if s := strings.SplitN(versionstr, " ", 3); len(s) >= 2 && s[0] == "version" { 81 if v, err := strconv.Atoi(s[1]); err == nil && v > 0 { 82 p.version = v 83 } 84 } 85 } 86 87 // read version specific flags - extend as necessary 88 switch p.version { 89 // case 5: 90 // ... 91 // fallthrough 92 case 4, 3, 2, 1: 93 p.debugFormat = p.rawStringln(p.rawByte()) == "debug" 94 p.trackAllTypes = p.bool() 95 p.posInfoFormat = p.bool() 96 case 0: 97 // Go1.7 encoding format - nothing to do here 98 default: 99 formatErrorf("unknown export format version %d (%q)", p.version, versionstr) 100 } 101 102 // --- generic export data --- 103 104 // populate typList with predeclared "known" types 105 p.typList = append(p.typList, predeclared()...) 106 107 // read package data 108 p.pkg() 109 110 // defer some type-checking until all types are read in completely 111 tcok := typecheckok 112 typecheckok = true 113 defercheckwidth() 114 115 // read objects 116 117 // phase 1 118 objcount := 0 119 for { 120 tag := p.tagOrIndex() 121 if tag == endTag { 122 break 123 } 124 p.obj(tag) 125 objcount++ 126 } 127 128 // self-verification 129 if count := p.int(); count != objcount { 130 formatErrorf("got %d objects; want %d", objcount, count) 131 } 132 133 // --- compiler-specific export data --- 134 135 // read compiler-specific flags 136 137 // phase 2 138 objcount = 0 139 for { 140 tag := p.tagOrIndex() 141 if tag == endTag { 142 break 143 } 144 p.obj(tag) 145 objcount++ 146 } 147 148 // self-verification 149 if count := p.int(); count != objcount { 150 formatErrorf("got %d objects; want %d", objcount, count) 151 } 152 153 // read inlineable functions bodies 154 if dclcontext != PEXTERN { 155 formatErrorf("unexpected context %d", dclcontext) 156 } 157 158 objcount = 0 159 for i0 := -1; ; { 160 i := p.int() // index of function with inlineable body 161 if i < 0 { 162 break 163 } 164 165 // don't process the same function twice 166 if i <= i0 { 167 formatErrorf("index not increasing: %d <= %d", i, i0) 168 } 169 i0 = i 170 171 if funcdepth != 0 { 172 formatErrorf("unexpected Funcdepth %d", funcdepth) 173 } 174 175 // Note: In the original code, funchdr and funcbody are called for 176 // all functions (that were not yet imported). Now, we are calling 177 // them only for functions with inlineable bodies. funchdr does 178 // parameter renaming which doesn't matter if we don't have a body. 179 180 if f := p.funcList[i]; f != nil { 181 // function not yet imported - read body and set it 182 funchdr(f) 183 body := p.stmtList() 184 if body == nil { 185 // Make sure empty body is not interpreted as 186 // no inlineable body (see also parser.fnbody) 187 // (not doing so can cause significant performance 188 // degradation due to unnecessary calls to empty 189 // functions). 190 body = []*Node{nod(OEMPTY, nil, nil)} 191 } 192 f.Func.Inl.Set(body) 193 funcbody(f) 194 } else { 195 // function already imported - read body but discard declarations 196 dclcontext = PDISCARD // throw away any declarations 197 p.stmtList() 198 dclcontext = PEXTERN 199 } 200 201 objcount++ 202 } 203 204 // self-verification 205 if count := p.int(); count != objcount { 206 formatErrorf("got %d functions; want %d", objcount, count) 207 } 208 209 if dclcontext != PEXTERN { 210 formatErrorf("unexpected context %d", dclcontext) 211 } 212 213 p.verifyTypes() 214 215 // --- end of export data --- 216 217 typecheckok = tcok 218 resumecheckwidth() 219 220 if debug_dclstack != 0 { 221 testdclstack() 222 } 223 } 224 225 func formatErrorf(format string, args ...interface{}) { 226 if debugFormat { 227 Fatalf(format, args...) 228 } 229 230 yyerror("cannot import %q due to version skew - reinstall package (%s)", 231 importpkg.Path, fmt.Sprintf(format, args...)) 232 errorexit() 233 } 234 235 func (p *importer) verifyTypes() { 236 for _, pair := range p.cmpList { 237 pt := pair.pt 238 t := pair.t 239 if !eqtype(pt.Orig, t) { 240 formatErrorf("inconsistent definition for type %v during import\n\t%L (in %q)\n\t%L (in %q)", pt.Sym, pt, pt.Sym.Importdef.Path, t, importpkg.Path) 241 } 242 } 243 } 244 245 // numImport tracks how often a package with a given name is imported. 246 // It is used to provide a better error message (by using the package 247 // path to disambiguate) if a package that appears multiple times with 248 // the same name appears in an error message. 249 var numImport = make(map[string]int) 250 251 func (p *importer) pkg() *Pkg { 252 // if the package was seen before, i is its index (>= 0) 253 i := p.tagOrIndex() 254 if i >= 0 { 255 return p.pkgList[i] 256 } 257 258 // otherwise, i is the package tag (< 0) 259 if i != packageTag { 260 formatErrorf("expected package tag, found tag = %d", i) 261 } 262 263 // read package data 264 name := p.string() 265 path := p.string() 266 267 // we should never see an empty package name 268 if name == "" { 269 formatErrorf("empty package name for path %q", path) 270 } 271 272 // we should never see a bad import path 273 if isbadimport(path) { 274 formatErrorf("bad package path %q for package %s", path, name) 275 } 276 277 // an empty path denotes the package we are currently importing; 278 // it must be the first package we see 279 if (path == "") != (len(p.pkgList) == 0) { 280 formatErrorf("package path %q for pkg index %d", path, len(p.pkgList)) 281 } 282 283 // add package to pkgList 284 pkg := importpkg 285 if path != "" { 286 pkg = mkpkg(path) 287 } 288 if pkg.Name == "" { 289 pkg.Name = name 290 numImport[name]++ 291 } else if pkg.Name != name { 292 yyerror("conflicting package names %s and %s for path %q", pkg.Name, name, path) 293 } 294 if myimportpath != "" && path == myimportpath { 295 yyerror("import %q: package depends on %q (import cycle)", importpkg.Path, path) 296 errorexit() 297 } 298 p.pkgList = append(p.pkgList, pkg) 299 300 return pkg 301 } 302 303 func idealType(typ *Type) *Type { 304 if typ.IsUntyped() { 305 // canonicalize ideal types 306 typ = Types[TIDEAL] 307 } 308 return typ 309 } 310 311 func (p *importer) obj(tag int) { 312 switch tag { 313 case constTag: 314 p.pos() 315 sym := p.qualifiedName() 316 typ := p.typ() 317 val := p.value(typ) 318 importconst(sym, idealType(typ), nodlit(val)) 319 320 case aliasTag: 321 p.pos() 322 sym := p.qualifiedName() 323 typ := p.typ() 324 importalias(sym, typ) 325 326 case typeTag: 327 p.typ() 328 329 case varTag: 330 p.pos() 331 sym := p.qualifiedName() 332 typ := p.typ() 333 importvar(sym, typ) 334 335 case funcTag: 336 p.pos() 337 sym := p.qualifiedName() 338 params := p.paramList() 339 result := p.paramList() 340 341 sig := functypefield(nil, params, result) 342 importsym(sym, ONAME) 343 if sym.Def != nil && sym.Def.Op == ONAME { 344 // function was imported before (via another import) 345 if !eqtype(sig, sym.Def.Type) { 346 formatErrorf("inconsistent definition for func %v during import\n\t%v\n\t%v", sym, sym.Def.Type, sig) 347 } 348 p.funcList = append(p.funcList, nil) 349 break 350 } 351 352 n := newfuncname(sym) 353 n.Type = sig 354 declare(n, PFUNC) 355 p.funcList = append(p.funcList, n) 356 importlist = append(importlist, n) 357 358 if Debug['E'] > 0 { 359 fmt.Printf("import [%q] func %v \n", importpkg.Path, n) 360 if Debug['m'] > 2 && n.Func.Inl.Len() != 0 { 361 fmt.Printf("inl body: %v\n", n.Func.Inl) 362 } 363 } 364 365 default: 366 formatErrorf("unexpected object (tag = %d)", tag) 367 } 368 } 369 370 func (p *importer) pos() { 371 if !p.posInfoFormat { 372 return 373 } 374 375 file := p.prevFile 376 line := p.prevLine 377 if delta := p.int(); delta != 0 { 378 // line changed 379 line += delta 380 } else if n := p.int(); n >= 0 { 381 // file changed 382 file = p.prevFile[:n] + p.string() 383 p.prevFile = file 384 line = p.int() 385 } 386 p.prevLine = line 387 388 // TODO(gri) register new position 389 } 390 391 func (p *importer) newtyp(etype EType) *Type { 392 t := typ(etype) 393 if p.trackAllTypes { 394 p.typList = append(p.typList, t) 395 } 396 return t 397 } 398 399 // importtype declares that pt, an imported named type, has underlying type t. 400 func (p *importer) importtype(pt, t *Type) { 401 if pt.Etype == TFORW { 402 n := pt.nod 403 copytype(pt.nod, t) 404 pt.nod = n // unzero nod 405 pt.Sym.Importdef = importpkg 406 pt.Sym.Lastlineno = lineno 407 declare(n, PEXTERN) 408 checkwidth(pt) 409 } else { 410 // pt.Orig and t must be identical. 411 if p.trackAllTypes { 412 // If we track all types, t may not be fully set up yet. 413 // Collect the types and verify identity later. 414 p.cmpList = append(p.cmpList, struct{ pt, t *Type }{pt, t}) 415 } else if !eqtype(pt.Orig, t) { 416 yyerror("inconsistent definition for type %v during import\n\t%L (in %q)\n\t%L (in %q)", pt.Sym, pt, pt.Sym.Importdef.Path, t, importpkg.Path) 417 } 418 } 419 420 if Debug['E'] != 0 { 421 fmt.Printf("import type %v %L\n", pt, t) 422 } 423 } 424 425 func (p *importer) typ() *Type { 426 // if the type was seen before, i is its index (>= 0) 427 i := p.tagOrIndex() 428 if i >= 0 { 429 return p.typList[i] 430 } 431 432 // otherwise, i is the type tag (< 0) 433 var t *Type 434 switch i { 435 case namedTag: 436 p.pos() 437 tsym := p.qualifiedName() 438 439 t = pkgtype(tsym) 440 p.typList = append(p.typList, t) 441 442 // read underlying type 443 t0 := p.typ() 444 p.importtype(t, t0) 445 446 // interfaces don't have associated methods 447 if t0.IsInterface() { 448 break 449 } 450 451 // set correct import context (since p.typ() may be called 452 // while importing the body of an inlined function) 453 savedContext := dclcontext 454 dclcontext = PEXTERN 455 456 // read associated methods 457 for i := p.int(); i > 0; i-- { 458 p.pos() 459 sym := p.fieldSym() 460 461 // during import unexported method names should be in the type's package 462 if !exportname(sym.Name) && sym.Pkg != tsym.Pkg { 463 Fatalf("imported method name %+v in wrong package %s\n", sym, tsym.Pkg.Name) 464 } 465 466 recv := p.paramList() // TODO(gri) do we need a full param list for the receiver? 467 params := p.paramList() 468 result := p.paramList() 469 nointerface := p.bool() 470 471 n := newfuncname(methodname(sym, recv[0].Type)) 472 n.Type = functypefield(recv[0], params, result) 473 checkwidth(n.Type) 474 addmethod(sym, n.Type, false, nointerface) 475 p.funcList = append(p.funcList, n) 476 importlist = append(importlist, n) 477 478 // (comment from parser.go) 479 // inl.C's inlnode in on a dotmeth node expects to find the inlineable body as 480 // (dotmeth's type).Nname.Inl, and dotmeth's type has been pulled 481 // out by typecheck's lookdot as this $$.ttype. So by providing 482 // this back link here we avoid special casing there. 483 n.Type.SetNname(n) 484 485 if Debug['E'] > 0 { 486 fmt.Printf("import [%q] meth %v \n", importpkg.Path, n) 487 if Debug['m'] > 2 && n.Func.Inl.Len() != 0 { 488 fmt.Printf("inl body: %v\n", n.Func.Inl) 489 } 490 } 491 } 492 493 dclcontext = savedContext 494 495 case arrayTag: 496 t = p.newtyp(TARRAY) 497 bound := p.int64() 498 elem := p.typ() 499 t.Extra = &ArrayType{Elem: elem, Bound: bound} 500 501 case sliceTag: 502 t = p.newtyp(TSLICE) 503 elem := p.typ() 504 t.Extra = SliceType{Elem: elem} 505 506 case dddTag: 507 t = p.newtyp(TDDDFIELD) 508 t.Extra = DDDFieldType{T: p.typ()} 509 510 case structTag: 511 t = p.newtyp(TSTRUCT) 512 t.SetFields(p.fieldList()) 513 checkwidth(t) 514 515 case pointerTag: 516 t = p.newtyp(Tptr) 517 t.Extra = PtrType{Elem: p.typ()} 518 519 case signatureTag: 520 t = p.newtyp(TFUNC) 521 params := p.paramList() 522 result := p.paramList() 523 functypefield0(t, nil, params, result) 524 525 case interfaceTag: 526 t = p.newtyp(TINTER) 527 if p.int() != 0 { 528 formatErrorf("unexpected embedded interface") 529 } 530 t.SetFields(p.methodList()) 531 checkwidth(t) 532 533 case mapTag: 534 t = p.newtyp(TMAP) 535 mt := t.MapType() 536 mt.Key = p.typ() 537 mt.Val = p.typ() 538 539 case chanTag: 540 t = p.newtyp(TCHAN) 541 ct := t.ChanType() 542 ct.Dir = ChanDir(p.int()) 543 ct.Elem = p.typ() 544 545 default: 546 formatErrorf("unexpected type (tag = %d)", i) 547 } 548 549 if t == nil { 550 formatErrorf("nil type (type tag = %d)", i) 551 } 552 553 return t 554 } 555 556 func (p *importer) qualifiedName() *Sym { 557 name := p.string() 558 pkg := p.pkg() 559 return pkg.Lookup(name) 560 } 561 562 func (p *importer) fieldList() (fields []*Field) { 563 if n := p.int(); n > 0 { 564 fields = make([]*Field, n) 565 for i := range fields { 566 fields[i] = p.field() 567 } 568 } 569 return 570 } 571 572 func (p *importer) field() *Field { 573 p.pos() 574 sym, alias := p.fieldName() 575 typ := p.typ() 576 note := p.string() 577 578 f := newField() 579 if sym.Name == "" { 580 // anonymous field: typ must be T or *T and T must be a type name 581 s := typ.Sym 582 if s == nil && typ.IsPtr() { 583 s = typ.Elem().Sym // deref 584 } 585 sym = sym.Pkg.Lookup(s.Name) 586 f.Embedded = 1 587 } else if alias { 588 // anonymous field: we have an explicit name because it's a type alias 589 f.Embedded = 1 590 } 591 592 f.Sym = sym 593 f.Nname = newname(sym) 594 f.Type = typ 595 f.Note = note 596 597 return f 598 } 599 600 func (p *importer) methodList() (methods []*Field) { 601 if n := p.int(); n > 0 { 602 methods = make([]*Field, n) 603 for i := range methods { 604 methods[i] = p.method() 605 } 606 } 607 return 608 } 609 610 func (p *importer) method() *Field { 611 p.pos() 612 sym := p.methodName() 613 params := p.paramList() 614 result := p.paramList() 615 616 f := newField() 617 f.Sym = sym 618 f.Nname = newname(sym) 619 f.Type = functypefield(fakethisfield(), params, result) 620 return f 621 } 622 623 func (p *importer) fieldName() (*Sym, bool) { 624 name := p.string() 625 if p.version == 0 && name == "_" { 626 // version 0 didn't export a package for _ field names 627 // but used the builtin package instead 628 return builtinpkg.Lookup(name), false 629 } 630 pkg := localpkg 631 alias := false 632 switch name { 633 case "": 634 // 1) field name matches base type name and is exported: nothing to do 635 case "?": 636 // 2) field name matches base type name and is not exported: need package 637 name = "" 638 pkg = p.pkg() 639 case "@": 640 // 3) field name doesn't match base type name (alias name): need name and possibly package 641 name = p.string() 642 alias = true 643 fallthrough 644 default: 645 if !exportname(name) { 646 pkg = p.pkg() 647 } 648 } 649 return pkg.Lookup(name), alias 650 } 651 652 func (p *importer) methodName() *Sym { 653 name := p.string() 654 if p.version == 0 && name == "_" { 655 // version 0 didn't export a package for _ method names 656 // but used the builtin package instead 657 return builtinpkg.Lookup(name) 658 } 659 pkg := localpkg 660 if !exportname(name) { 661 pkg = p.pkg() 662 } 663 return pkg.Lookup(name) 664 } 665 666 func (p *importer) paramList() []*Field { 667 i := p.int() 668 if i == 0 { 669 return nil 670 } 671 // negative length indicates unnamed parameters 672 named := true 673 if i < 0 { 674 i = -i 675 named = false 676 } 677 // i > 0 678 fs := make([]*Field, i) 679 for i := range fs { 680 fs[i] = p.param(named) 681 } 682 return fs 683 } 684 685 func (p *importer) param(named bool) *Field { 686 f := newField() 687 f.Type = p.typ() 688 if f.Type.Etype == TDDDFIELD { 689 // TDDDFIELD indicates wrapped ... slice type 690 f.Type = typSlice(f.Type.DDDField()) 691 f.Isddd = true 692 } 693 694 if named { 695 name := p.string() 696 if name == "" { 697 formatErrorf("expected named parameter") 698 } 699 // TODO(gri) Supply function/method package rather than 700 // encoding the package for each parameter repeatedly. 701 pkg := localpkg 702 if name != "_" { 703 pkg = p.pkg() 704 } 705 f.Sym = pkg.Lookup(name) 706 f.Nname = newname(f.Sym) 707 } 708 709 // TODO(gri) This is compiler-specific (escape info). 710 // Move into compiler-specific section eventually? 711 f.Note = p.string() 712 713 return f 714 } 715 716 func (p *importer) value(typ *Type) (x Val) { 717 switch tag := p.tagOrIndex(); tag { 718 case falseTag: 719 x.U = false 720 721 case trueTag: 722 x.U = true 723 724 case int64Tag: 725 u := new(Mpint) 726 u.SetInt64(p.int64()) 727 u.Rune = typ == idealrune 728 x.U = u 729 730 case floatTag: 731 f := newMpflt() 732 p.float(f) 733 if typ == idealint || typ.IsInteger() { 734 // uncommon case: large int encoded as float 735 u := new(Mpint) 736 u.SetFloat(f) 737 x.U = u 738 break 739 } 740 x.U = f 741 742 case complexTag: 743 u := new(Mpcplx) 744 p.float(&u.Real) 745 p.float(&u.Imag) 746 x.U = u 747 748 case stringTag: 749 x.U = p.string() 750 751 case unknownTag: 752 formatErrorf("unknown constant (importing package with errors)") 753 754 case nilTag: 755 x.U = new(NilVal) 756 757 default: 758 formatErrorf("unexpected value tag %d", tag) 759 } 760 761 // verify ideal type 762 if typ.IsUntyped() && untype(x.Ctype()) != typ { 763 formatErrorf("value %v and type %v don't match", x, typ) 764 } 765 766 return 767 } 768 769 func (p *importer) float(x *Mpflt) { 770 sign := p.int() 771 if sign == 0 { 772 x.SetFloat64(0) 773 return 774 } 775 776 exp := p.int() 777 mant := new(big.Int).SetBytes([]byte(p.string())) 778 779 m := x.Val.SetInt(mant) 780 m.SetMantExp(m, exp-mant.BitLen()) 781 if sign < 0 { 782 m.Neg(m) 783 } 784 } 785 786 // ---------------------------------------------------------------------------- 787 // Inlined function bodies 788 789 // Approach: Read nodes and use them to create/declare the same data structures 790 // as done originally by the (hidden) parser by closely following the parser's 791 // original code. In other words, "parsing" the import data (which happens to 792 // be encoded in binary rather textual form) is the best way at the moment to 793 // re-establish the syntax tree's invariants. At some future point we might be 794 // able to avoid this round-about way and create the rewritten nodes directly, 795 // possibly avoiding a lot of duplicate work (name resolution, type checking). 796 // 797 // Refined nodes (e.g., ODOTPTR as a refinement of OXDOT) are exported as their 798 // unrefined nodes (since this is what the importer uses). The respective case 799 // entries are unreachable in the importer. 800 801 func (p *importer) stmtList() []*Node { 802 var list []*Node 803 for { 804 n := p.node() 805 if n == nil { 806 break 807 } 808 // OBLOCK nodes may be created when importing ODCL nodes - unpack them 809 if n.Op == OBLOCK { 810 list = append(list, n.List.Slice()...) 811 } else { 812 list = append(list, n) 813 } 814 } 815 return list 816 } 817 818 func (p *importer) exprList() []*Node { 819 var list []*Node 820 for { 821 n := p.expr() 822 if n == nil { 823 break 824 } 825 list = append(list, n) 826 } 827 return list 828 } 829 830 func (p *importer) elemList() []*Node { 831 c := p.int() 832 list := make([]*Node, c) 833 for i := range list { 834 s := p.fieldSym() 835 list[i] = nodSym(OSTRUCTKEY, p.expr(), s) 836 } 837 return list 838 } 839 840 func (p *importer) expr() *Node { 841 n := p.node() 842 if n != nil && n.Op == OBLOCK { 843 Fatalf("unexpected block node: %v", n) 844 } 845 return n 846 } 847 848 // TODO(gri) split into expr and stmt 849 func (p *importer) node() *Node { 850 switch op := p.op(); op { 851 // expressions 852 // case OPAREN: 853 // unreachable - unpacked by exporter 854 855 // case ODDDARG: 856 // unimplemented 857 858 case OLITERAL: 859 typ := p.typ() 860 n := nodlit(p.value(typ)) 861 if !typ.IsUntyped() { 862 // Type-checking simplifies unsafe.Pointer(uintptr(c)) 863 // to unsafe.Pointer(c) which then cannot type-checked 864 // again. Re-introduce explicit uintptr(c) conversion. 865 // (issue 16317). 866 if typ.IsUnsafePtr() { 867 conv := nod(OCALL, typenod(Types[TUINTPTR]), nil) 868 conv.List.Set1(n) 869 n = conv 870 } 871 conv := nod(OCALL, typenod(typ), nil) 872 conv.List.Set1(n) 873 n = conv 874 } 875 return n 876 877 case ONAME: 878 return mkname(p.sym()) 879 880 // case OPACK, ONONAME: 881 // unreachable - should have been resolved by typechecking 882 883 case OTYPE: 884 if p.bool() { 885 return mkname(p.sym()) 886 } 887 return typenod(p.typ()) 888 889 // case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC: 890 // unreachable - should have been resolved by typechecking 891 892 // case OCLOSURE: 893 // unimplemented 894 895 case OPTRLIT: 896 n := p.expr() 897 if !p.bool() /* !implicit, i.e. '&' operator */ { 898 if n.Op == OCOMPLIT { 899 // Special case for &T{...}: turn into (*T){...}. 900 n.Right = nod(OIND, n.Right, nil) 901 n.Right.Implicit = true 902 } else { 903 n = nod(OADDR, n, nil) 904 } 905 } 906 return n 907 908 case OSTRUCTLIT: 909 n := nod(OCOMPLIT, nil, typenod(p.typ())) 910 n.List.Set(p.elemList()) // special handling of field names 911 return n 912 913 // case OARRAYLIT, OSLICELIT, OMAPLIT: 914 // unreachable - mapped to case OCOMPLIT below by exporter 915 916 case OCOMPLIT: 917 n := nod(OCOMPLIT, nil, typenod(p.typ())) 918 n.List.Set(p.exprList()) 919 return n 920 921 case OKEY: 922 left, right := p.exprsOrNil() 923 return nod(OKEY, left, right) 924 925 // case OSTRUCTKEY: 926 // unreachable - handled in case OSTRUCTLIT by elemList 927 928 // case OCALLPART: 929 // unimplemented 930 931 // case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH: 932 // unreachable - mapped to case OXDOT below by exporter 933 934 case OXDOT: 935 // see parser.new_dotname 936 return nodSym(OXDOT, p.expr(), p.fieldSym()) 937 938 // case ODOTTYPE, ODOTTYPE2: 939 // unreachable - mapped to case ODOTTYPE below by exporter 940 941 case ODOTTYPE: 942 n := nod(ODOTTYPE, p.expr(), nil) 943 if p.bool() { 944 n.Right = p.expr() 945 } else { 946 n.Right = typenod(p.typ()) 947 } 948 return n 949 950 // case OINDEX, OINDEXMAP, OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR: 951 // unreachable - mapped to cases below by exporter 952 953 case OINDEX: 954 return nod(op, p.expr(), p.expr()) 955 956 case OSLICE, OSLICE3: 957 n := nod(op, p.expr(), nil) 958 low, high := p.exprsOrNil() 959 var max *Node 960 if n.Op.IsSlice3() { 961 max = p.expr() 962 } 963 n.SetSliceBounds(low, high, max) 964 return n 965 966 // case OCONV, OCONVIFACE, OCONVNOP, OARRAYBYTESTR, OARRAYRUNESTR, OSTRARRAYBYTE, OSTRARRAYRUNE, ORUNESTR: 967 // unreachable - mapped to OCONV case below by exporter 968 969 case OCONV: 970 n := nod(OCALL, typenod(p.typ()), nil) 971 n.List.Set(p.exprList()) 972 return n 973 974 case OCOPY, OCOMPLEX, OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN: 975 n := builtinCall(op) 976 n.List.Set(p.exprList()) 977 if op == OAPPEND { 978 n.Isddd = p.bool() 979 } 980 return n 981 982 // case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG: 983 // unreachable - mapped to OCALL case below by exporter 984 985 case OCALL: 986 n := nod(OCALL, p.expr(), nil) 987 n.List.Set(p.exprList()) 988 n.Isddd = p.bool() 989 return n 990 991 case OMAKEMAP, OMAKECHAN, OMAKESLICE: 992 n := builtinCall(OMAKE) 993 n.List.Append(typenod(p.typ())) 994 n.List.Append(p.exprList()...) 995 return n 996 997 // unary expressions 998 case OPLUS, OMINUS, OADDR, OCOM, OIND, ONOT, ORECV: 999 return nod(op, p.expr(), nil) 1000 1001 // binary expressions 1002 case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, OLT, 1003 OLSH, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSEND, OSUB, OXOR: 1004 return nod(op, p.expr(), p.expr()) 1005 1006 case OADDSTR: 1007 list := p.exprList() 1008 x := list[0] 1009 for _, y := range list[1:] { 1010 x = nod(OADD, x, y) 1011 } 1012 return x 1013 1014 // case OCMPSTR, OCMPIFACE: 1015 // unreachable - mapped to std comparison operators by exporter 1016 1017 case ODCLCONST: 1018 // TODO(gri) these should not be exported in the first place 1019 return nod(OEMPTY, nil, nil) 1020 1021 // -------------------------------------------------------------------- 1022 // statements 1023 case ODCL: 1024 if p.version < 2 { 1025 // versions 0 and 1 exported a bool here but it 1026 // was always false - simply ignore in this case 1027 p.bool() 1028 } 1029 lhs := dclname(p.sym()) 1030 typ := typenod(p.typ()) 1031 return liststmt(variter([]*Node{lhs}, typ, nil)) // TODO(gri) avoid list creation 1032 1033 // case ODCLFIELD: 1034 // unimplemented 1035 1036 // case OAS, OASWB: 1037 // unreachable - mapped to OAS case below by exporter 1038 1039 case OAS: 1040 return nod(OAS, p.expr(), p.expr()) 1041 1042 case OASOP: 1043 n := nod(OASOP, nil, nil) 1044 n.Etype = EType(p.int()) 1045 n.Left = p.expr() 1046 if !p.bool() { 1047 n.Right = nodintconst(1) 1048 n.Implicit = true 1049 } else { 1050 n.Right = p.expr() 1051 } 1052 return n 1053 1054 // case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV: 1055 // unreachable - mapped to OAS2 case below by exporter 1056 1057 case OAS2: 1058 n := nod(OAS2, nil, nil) 1059 n.List.Set(p.exprList()) 1060 n.Rlist.Set(p.exprList()) 1061 return n 1062 1063 case ORETURN: 1064 n := nod(ORETURN, nil, nil) 1065 n.List.Set(p.exprList()) 1066 return n 1067 1068 // case ORETJMP: 1069 // unreachable - generated by compiler for trampolin routines (not exported) 1070 1071 case OPROC, ODEFER: 1072 return nod(op, p.expr(), nil) 1073 1074 case OIF: 1075 markdcl() 1076 n := nod(OIF, nil, nil) 1077 n.Ninit.Set(p.stmtList()) 1078 n.Left = p.expr() 1079 n.Nbody.Set(p.stmtList()) 1080 n.Rlist.Set(p.stmtList()) 1081 popdcl() 1082 return n 1083 1084 case OFOR: 1085 markdcl() 1086 n := nod(OFOR, nil, nil) 1087 n.Ninit.Set(p.stmtList()) 1088 n.Left, n.Right = p.exprsOrNil() 1089 n.Nbody.Set(p.stmtList()) 1090 popdcl() 1091 return n 1092 1093 case ORANGE: 1094 markdcl() 1095 n := nod(ORANGE, nil, nil) 1096 n.List.Set(p.stmtList()) 1097 n.Right = p.expr() 1098 n.Nbody.Set(p.stmtList()) 1099 popdcl() 1100 return n 1101 1102 case OSELECT, OSWITCH: 1103 markdcl() 1104 n := nod(op, nil, nil) 1105 n.Ninit.Set(p.stmtList()) 1106 n.Left, _ = p.exprsOrNil() 1107 n.List.Set(p.stmtList()) 1108 popdcl() 1109 return n 1110 1111 // case OCASE, OXCASE: 1112 // unreachable - mapped to OXCASE case below by exporter 1113 1114 case OXCASE: 1115 markdcl() 1116 n := nod(OXCASE, nil, nil) 1117 n.Xoffset = int64(block) 1118 n.List.Set(p.exprList()) 1119 // TODO(gri) eventually we must declare variables for type switch 1120 // statements (type switch statements are not yet exported) 1121 n.Nbody.Set(p.stmtList()) 1122 popdcl() 1123 return n 1124 1125 // case OFALL: 1126 // unreachable - mapped to OXFALL case below by exporter 1127 1128 case OXFALL: 1129 n := nod(OXFALL, nil, nil) 1130 n.Xoffset = int64(block) 1131 return n 1132 1133 case OBREAK, OCONTINUE: 1134 left, _ := p.exprsOrNil() 1135 if left != nil { 1136 left = newname(left.Sym) 1137 } 1138 return nod(op, left, nil) 1139 1140 // case OEMPTY: 1141 // unreachable - not emitted by exporter 1142 1143 case OGOTO, OLABEL: 1144 n := nod(op, newname(p.expr().Sym), nil) 1145 n.Sym = dclstack // context, for goto restrictions 1146 return n 1147 1148 case OEND: 1149 return nil 1150 1151 default: 1152 Fatalf("cannot import %v (%d) node\n"+ 1153 "==> please file an issue and assign to gri@\n", op, int(op)) 1154 panic("unreachable") // satisfy compiler 1155 } 1156 } 1157 1158 func builtinCall(op Op) *Node { 1159 return nod(OCALL, mkname(builtinpkg.Lookup(goopnames[op])), nil) 1160 } 1161 1162 func (p *importer) exprsOrNil() (a, b *Node) { 1163 ab := p.int() 1164 if ab&1 != 0 { 1165 a = p.expr() 1166 } 1167 if ab&2 != 0 { 1168 b = p.expr() 1169 } 1170 return 1171 } 1172 1173 func (p *importer) fieldSym() *Sym { 1174 name := p.string() 1175 pkg := localpkg 1176 if !exportname(name) { 1177 pkg = p.pkg() 1178 } 1179 return pkg.Lookup(name) 1180 } 1181 1182 func (p *importer) sym() *Sym { 1183 name := p.string() 1184 pkg := localpkg 1185 if name != "_" { 1186 pkg = p.pkg() 1187 } 1188 linkname := p.string() 1189 sym := pkg.Lookup(name) 1190 sym.Linkname = linkname 1191 return sym 1192 } 1193 1194 func (p *importer) bool() bool { 1195 return p.int() != 0 1196 } 1197 1198 func (p *importer) op() Op { 1199 return Op(p.int()) 1200 } 1201 1202 // ---------------------------------------------------------------------------- 1203 // Low-level decoders 1204 1205 func (p *importer) tagOrIndex() int { 1206 if p.debugFormat { 1207 p.marker('t') 1208 } 1209 1210 return int(p.rawInt64()) 1211 } 1212 1213 func (p *importer) int() int { 1214 x := p.int64() 1215 if int64(int(x)) != x { 1216 formatErrorf("exported integer too large") 1217 } 1218 return int(x) 1219 } 1220 1221 func (p *importer) int64() int64 { 1222 if p.debugFormat { 1223 p.marker('i') 1224 } 1225 1226 return p.rawInt64() 1227 } 1228 1229 func (p *importer) string() string { 1230 if p.debugFormat { 1231 p.marker('s') 1232 } 1233 // if the string was seen before, i is its index (>= 0) 1234 // (the empty string is at index 0) 1235 i := p.rawInt64() 1236 if i >= 0 { 1237 return p.strList[i] 1238 } 1239 // otherwise, i is the negative string length (< 0) 1240 if n := int(-i); n <= cap(p.buf) { 1241 p.buf = p.buf[:n] 1242 } else { 1243 p.buf = make([]byte, n) 1244 } 1245 for i := range p.buf { 1246 p.buf[i] = p.rawByte() 1247 } 1248 s := string(p.buf) 1249 p.strList = append(p.strList, s) 1250 return s 1251 } 1252 1253 func (p *importer) marker(want byte) { 1254 if got := p.rawByte(); got != want { 1255 formatErrorf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read) 1256 } 1257 1258 pos := p.read 1259 if n := int(p.rawInt64()); n != pos { 1260 formatErrorf("incorrect position: got %d; want %d", n, pos) 1261 } 1262 } 1263 1264 // rawInt64 should only be used by low-level decoders. 1265 func (p *importer) rawInt64() int64 { 1266 i, err := binary.ReadVarint(p) 1267 if err != nil { 1268 formatErrorf("read error: %v", err) 1269 } 1270 return i 1271 } 1272 1273 // rawStringln should only be used to read the initial version string. 1274 func (p *importer) rawStringln(b byte) string { 1275 p.buf = p.buf[:0] 1276 for b != '\n' { 1277 p.buf = append(p.buf, b) 1278 b = p.rawByte() 1279 } 1280 return string(p.buf) 1281 } 1282 1283 // needed for binary.ReadVarint in rawInt64 1284 func (p *importer) ReadByte() (byte, error) { 1285 return p.rawByte(), nil 1286 } 1287 1288 // rawByte is the bottleneck interface for reading from p.in. 1289 // It unescapes '|' 'S' to '$' and '|' '|' to '|'. 1290 // rawByte should only be used by low-level decoders. 1291 func (p *importer) rawByte() byte { 1292 c, err := p.in.ReadByte() 1293 p.read++ 1294 if err != nil { 1295 formatErrorf("read error: %v", err) 1296 } 1297 if c == '|' { 1298 c, err = p.in.ReadByte() 1299 p.read++ 1300 if err != nil { 1301 formatErrorf("read error: %v", err) 1302 } 1303 switch c { 1304 case 'S': 1305 c = '$' 1306 case '|': 1307 // nothing to do 1308 default: 1309 formatErrorf("unexpected escape sequence in export data") 1310 } 1311 } 1312 return c 1313 }