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