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