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