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