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