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