github.com/Filosottile/go@v0.0.0-20170906193555-dbed9972d994/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() 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 pos := p.pos() 330 sym := p.qualifiedName() 331 typ := p.typ() 332 val := p.value(typ) 333 importconst(p.imp, sym, idealType(typ), npos(pos, nodlit(val))) 334 335 case aliasTag: 336 pos := p.pos() 337 sym := p.qualifiedName() 338 typ := p.typ() 339 importalias(pos, p.imp, sym, typ) 340 341 case typeTag: 342 p.typ() 343 344 case varTag: 345 pos := p.pos() 346 sym := p.qualifiedName() 347 typ := p.typ() 348 importvar(pos, p.imp, sym, typ) 349 350 case funcTag: 351 pos := 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 := newfuncnamel(pos, 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 pos := p.pos() 483 tsym := p.qualifiedName() 484 485 t = pkgtype(pos, p.imp, tsym) 486 p.typList = append(p.typList, t) 487 dup := !t.IsKind(types.TFORW) // type already imported 488 489 // read underlying type 490 t0 := p.typ() 491 p.importtype(t, t0) 492 493 // interfaces don't have associated methods 494 if t0.IsInterface() { 495 break 496 } 497 498 // set correct import context (since p.typ() may be called 499 // while importing the body of an inlined function) 500 savedContext := dclcontext 501 dclcontext = PEXTERN 502 503 // read associated methods 504 for i := p.int(); i > 0; i-- { 505 mpos := p.pos() 506 sym := p.fieldSym() 507 508 // during import unexported method names should be in the type's package 509 if !exportname(sym.Name) && sym.Pkg != tsym.Pkg { 510 Fatalf("imported method name %+v in wrong package %s\n", sym, tsym.Pkg.Name) 511 } 512 513 recv := p.paramList() // TODO(gri) do we need a full param list for the receiver? 514 params := p.paramList() 515 result := p.paramList() 516 nointerface := p.bool() 517 518 mt := functypefield(recv[0], params, result) 519 addmethod(sym, mt, false, nointerface) 520 521 if dup { 522 // An earlier import already declared this type and its methods. 523 // Discard the duplicate method declaration. 524 p.funcList = append(p.funcList, nil) 525 continue 526 } 527 528 n := newfuncnamel(mpos, methodname(sym, recv[0].Type)) 529 n.Type = mt 530 checkwidth(n.Type) 531 p.funcList = append(p.funcList, n) 532 importlist = append(importlist, n) 533 534 // (comment from parser.go) 535 // inl.C's inlnode in on a dotmeth node expects to find the inlineable body as 536 // (dotmeth's type).Nname.Inl, and dotmeth's type has been pulled 537 // out by typecheck's lookdot as this $$.ttype. So by providing 538 // this back link here we avoid special casing there. 539 n.Type.FuncType().Nname = asTypesNode(n) 540 541 if Debug['E'] > 0 { 542 fmt.Printf("import [%q] meth %v \n", p.imp.Path, n) 543 if Debug['m'] > 2 && n.Func.Inl.Len() != 0 { 544 fmt.Printf("inl body: %v\n", n.Func.Inl) 545 } 546 } 547 } 548 549 dclcontext = savedContext 550 551 case arrayTag: 552 t = p.newtyp(TARRAY) 553 bound := p.int64() 554 elem := p.typ() 555 t.Extra = &types.Array{Elem: elem, Bound: bound} 556 557 case sliceTag: 558 t = p.newtyp(TSLICE) 559 elem := p.typ() 560 t.Extra = types.Slice{Elem: elem} 561 562 case dddTag: 563 t = p.newtyp(TDDDFIELD) 564 t.Extra = types.DDDField{T: p.typ()} 565 566 case structTag: 567 t = p.newtyp(TSTRUCT) 568 t.SetFields(p.fieldList()) 569 checkwidth(t) 570 571 case pointerTag: 572 t = p.newtyp(types.Tptr) 573 t.Extra = types.Ptr{Elem: p.typ()} 574 575 case signatureTag: 576 t = p.newtyp(TFUNC) 577 params := p.paramList() 578 result := p.paramList() 579 functypefield0(t, nil, params, result) 580 581 case interfaceTag: 582 if ml := p.methodList(); len(ml) == 0 { 583 t = types.Types[TINTER] 584 } else { 585 t = p.newtyp(TINTER) 586 t.SetInterface(ml) 587 } 588 589 case mapTag: 590 t = p.newtyp(TMAP) 591 mt := t.MapType() 592 mt.Key = p.typ() 593 mt.Val = p.typ() 594 595 case chanTag: 596 t = p.newtyp(TCHAN) 597 ct := t.ChanType() 598 ct.Dir = types.ChanDir(p.int()) 599 ct.Elem = p.typ() 600 601 default: 602 p.formatErrorf("unexpected type (tag = %d)", i) 603 } 604 605 if t == nil { 606 p.formatErrorf("nil type (type tag = %d)", i) 607 } 608 609 return t 610 } 611 612 func (p *importer) qualifiedName() *types.Sym { 613 name := p.string() 614 pkg := p.pkg() 615 return pkg.Lookup(name) 616 } 617 618 func (p *importer) fieldList() (fields []*types.Field) { 619 if n := p.int(); n > 0 { 620 fields = make([]*types.Field, n) 621 for i := range fields { 622 fields[i] = p.field() 623 } 624 } 625 return 626 } 627 628 func (p *importer) field() *types.Field { 629 pos := p.pos() 630 sym, alias := p.fieldName() 631 typ := p.typ() 632 note := p.string() 633 634 f := types.NewField() 635 if sym.Name == "" { 636 // anonymous field: typ must be T or *T and T must be a type name 637 s := typ.Sym 638 if s == nil && typ.IsPtr() { 639 s = typ.Elem().Sym // deref 640 } 641 sym = sym.Pkg.Lookup(s.Name) 642 f.Embedded = 1 643 } else if alias { 644 // anonymous field: we have an explicit name because it's a type alias 645 f.Embedded = 1 646 } 647 648 f.Sym = sym 649 f.Nname = asTypesNode(newnamel(pos, sym)) 650 f.Type = typ 651 f.Note = note 652 653 return f 654 } 655 656 func (p *importer) methodList() (methods []*types.Field) { 657 for n := p.int(); n > 0; n-- { 658 f := types.NewField() 659 f.Nname = asTypesNode(newname(nblank.Sym)) 660 asNode(f.Nname).Pos = p.pos() 661 f.Type = p.typ() 662 methods = append(methods, f) 663 } 664 665 for n := p.int(); n > 0; n-- { 666 methods = append(methods, p.method()) 667 } 668 669 return 670 } 671 672 func (p *importer) method() *types.Field { 673 pos := p.pos() 674 sym := p.methodName() 675 params := p.paramList() 676 result := p.paramList() 677 678 f := types.NewField() 679 f.Sym = sym 680 f.Nname = asTypesNode(newnamel(pos, sym)) 681 f.Type = functypefield(fakeRecvField(), params, result) 682 return f 683 } 684 685 func (p *importer) fieldName() (*types.Sym, bool) { 686 name := p.string() 687 if p.version == 0 && name == "_" { 688 // version 0 didn't export a package for _ field names 689 // but used the builtin package instead 690 return builtinpkg.Lookup(name), false 691 } 692 pkg := localpkg 693 alias := false 694 switch name { 695 case "": 696 // 1) field name matches base type name and is exported: nothing to do 697 case "?": 698 // 2) field name matches base type name and is not exported: need package 699 name = "" 700 pkg = p.pkg() 701 case "@": 702 // 3) field name doesn't match base type name (alias name): need name and possibly package 703 name = p.string() 704 alias = true 705 fallthrough 706 default: 707 if !exportname(name) { 708 pkg = p.pkg() 709 } 710 } 711 return pkg.Lookup(name), alias 712 } 713 714 func (p *importer) methodName() *types.Sym { 715 name := p.string() 716 if p.version == 0 && name == "_" { 717 // version 0 didn't export a package for _ method names 718 // but used the builtin package instead 719 return builtinpkg.Lookup(name) 720 } 721 pkg := localpkg 722 if !exportname(name) { 723 pkg = p.pkg() 724 } 725 return pkg.Lookup(name) 726 } 727 728 func (p *importer) paramList() []*types.Field { 729 i := p.int() 730 if i == 0 { 731 return nil 732 } 733 // negative length indicates unnamed parameters 734 named := true 735 if i < 0 { 736 i = -i 737 named = false 738 } 739 // i > 0 740 fs := make([]*types.Field, i) 741 for i := range fs { 742 fs[i] = p.param(named) 743 } 744 return fs 745 } 746 747 func (p *importer) param(named bool) *types.Field { 748 f := types.NewField() 749 f.Type = p.typ() 750 if f.Type.Etype == TDDDFIELD { 751 // TDDDFIELD indicates wrapped ... slice type 752 f.Type = types.NewSlice(f.Type.DDDField()) 753 f.SetIsddd(true) 754 } 755 756 if named { 757 name := p.string() 758 if name == "" { 759 p.formatErrorf("expected named parameter") 760 } 761 // TODO(gri) Supply function/method package rather than 762 // encoding the package for each parameter repeatedly. 763 pkg := localpkg 764 if name != "_" { 765 pkg = p.pkg() 766 } 767 f.Sym = pkg.Lookup(name) 768 f.Nname = asTypesNode(newname(f.Sym)) 769 } 770 771 // TODO(gri) This is compiler-specific (escape info). 772 // Move into compiler-specific section eventually? 773 f.Note = p.string() 774 775 return f 776 } 777 778 func (p *importer) value(typ *types.Type) (x Val) { 779 switch tag := p.tagOrIndex(); tag { 780 case falseTag: 781 x.U = false 782 783 case trueTag: 784 x.U = true 785 786 case int64Tag: 787 u := new(Mpint) 788 u.SetInt64(p.int64()) 789 u.Rune = typ == types.Idealrune 790 x.U = u 791 792 case floatTag: 793 f := newMpflt() 794 p.float(f) 795 if typ == types.Idealint || typ.IsInteger() { 796 // uncommon case: large int encoded as float 797 u := new(Mpint) 798 u.SetFloat(f) 799 x.U = u 800 break 801 } 802 x.U = f 803 804 case complexTag: 805 u := new(Mpcplx) 806 p.float(&u.Real) 807 p.float(&u.Imag) 808 x.U = u 809 810 case stringTag: 811 x.U = p.string() 812 813 case unknownTag: 814 p.formatErrorf("unknown constant (importing package with errors)") 815 816 case nilTag: 817 x.U = new(NilVal) 818 819 default: 820 p.formatErrorf("unexpected value tag %d", tag) 821 } 822 823 // verify ideal type 824 if typ.IsUntyped() && untype(x.Ctype()) != typ { 825 p.formatErrorf("value %v and type %v don't match", x, typ) 826 } 827 828 return 829 } 830 831 func (p *importer) float(x *Mpflt) { 832 sign := p.int() 833 if sign == 0 { 834 x.SetFloat64(0) 835 return 836 } 837 838 exp := p.int() 839 mant := new(big.Int).SetBytes([]byte(p.string())) 840 841 m := x.Val.SetInt(mant) 842 m.SetMantExp(m, exp-mant.BitLen()) 843 if sign < 0 { 844 m.Neg(m) 845 } 846 } 847 848 // ---------------------------------------------------------------------------- 849 // Inlined function bodies 850 851 // Approach: Read nodes and use them to create/declare the same data structures 852 // as done originally by the (hidden) parser by closely following the parser's 853 // original code. In other words, "parsing" the import data (which happens to 854 // be encoded in binary rather textual form) is the best way at the moment to 855 // re-establish the syntax tree's invariants. At some future point we might be 856 // able to avoid this round-about way and create the rewritten nodes directly, 857 // possibly avoiding a lot of duplicate work (name resolution, type checking). 858 // 859 // Refined nodes (e.g., ODOTPTR as a refinement of OXDOT) are exported as their 860 // unrefined nodes (since this is what the importer uses). The respective case 861 // entries are unreachable in the importer. 862 863 func (p *importer) stmtList() []*Node { 864 var list []*Node 865 for { 866 n := p.node() 867 if n == nil { 868 break 869 } 870 // OBLOCK nodes may be created when importing ODCL nodes - unpack them 871 if n.Op == OBLOCK { 872 list = append(list, n.List.Slice()...) 873 } else { 874 list = append(list, n) 875 } 876 } 877 return list 878 } 879 880 func (p *importer) exprList() []*Node { 881 var list []*Node 882 for { 883 n := p.expr() 884 if n == nil { 885 break 886 } 887 list = append(list, n) 888 } 889 return list 890 } 891 892 func (p *importer) elemList() []*Node { 893 c := p.int() 894 list := make([]*Node, c) 895 for i := range list { 896 s := p.fieldSym() 897 list[i] = nodSym(OSTRUCTKEY, p.expr(), s) 898 } 899 return list 900 } 901 902 func (p *importer) expr() *Node { 903 n := p.node() 904 if n != nil && n.Op == OBLOCK { 905 Fatalf("unexpected block node: %v", n) 906 } 907 return n 908 } 909 910 func npos(pos src.XPos, n *Node) *Node { 911 n.Pos = pos 912 return n 913 } 914 915 // TODO(gri) split into expr and stmt 916 func (p *importer) node() *Node { 917 switch op := p.op(); op { 918 // expressions 919 // case OPAREN: 920 // unreachable - unpacked by exporter 921 922 // case ODDDARG: 923 // unimplemented 924 925 case OLITERAL: 926 pos := p.pos() 927 typ := p.typ() 928 n := npos(pos, nodlit(p.value(typ))) 929 if !typ.IsUntyped() { 930 // Type-checking simplifies unsafe.Pointer(uintptr(c)) 931 // to unsafe.Pointer(c) which then cannot type-checked 932 // again. Re-introduce explicit uintptr(c) conversion. 933 // (issue 16317). 934 if typ.IsUnsafePtr() { 935 n = nodl(pos, OCONV, n, nil) 936 n.Type = types.Types[TUINTPTR] 937 } 938 n = nodl(pos, OCONV, n, nil) 939 n.Type = typ 940 } 941 return n 942 943 case ONAME: 944 return npos(p.pos(), mkname(p.sym())) 945 946 // case OPACK, ONONAME: 947 // unreachable - should have been resolved by typechecking 948 949 case OTYPE: 950 pos := p.pos() 951 if p.bool() { 952 return npos(pos, mkname(p.sym())) 953 } 954 return npos(pos, typenod(p.typ())) 955 956 // case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC: 957 // unreachable - should have been resolved by typechecking 958 959 // case OCLOSURE: 960 // unimplemented 961 962 case OPTRLIT: 963 n := npos(p.pos(), p.expr()) 964 if !p.bool() /* !implicit, i.e. '&' operator */ { 965 if n.Op == OCOMPLIT { 966 // Special case for &T{...}: turn into (*T){...}. 967 n.Right = nod(OIND, n.Right, nil) 968 n.Right.SetImplicit(true) 969 } else { 970 n = nod(OADDR, n, nil) 971 } 972 } 973 return n 974 975 case OSTRUCTLIT: 976 n := nodl(p.pos(), OCOMPLIT, nil, typenod(p.typ())) 977 n.List.Set(p.elemList()) // special handling of field names 978 return n 979 980 // case OARRAYLIT, OSLICELIT, OMAPLIT: 981 // unreachable - mapped to case OCOMPLIT below by exporter 982 983 case OCOMPLIT: 984 n := nodl(p.pos(), OCOMPLIT, nil, typenod(p.typ())) 985 n.List.Set(p.exprList()) 986 return n 987 988 case OKEY: 989 pos := p.pos() 990 left, right := p.exprsOrNil() 991 return nodl(pos, OKEY, left, right) 992 993 // case OSTRUCTKEY: 994 // unreachable - handled in case OSTRUCTLIT by elemList 995 996 // case OCALLPART: 997 // unimplemented 998 999 // case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH: 1000 // unreachable - mapped to case OXDOT below by exporter 1001 1002 case OXDOT: 1003 // see parser.new_dotname 1004 return npos(p.pos(), nodSym(OXDOT, p.expr(), p.fieldSym())) 1005 1006 // case ODOTTYPE, ODOTTYPE2: 1007 // unreachable - mapped to case ODOTTYPE below by exporter 1008 1009 case ODOTTYPE: 1010 n := nodl(p.pos(), ODOTTYPE, p.expr(), nil) 1011 n.Type = p.typ() 1012 return n 1013 1014 // case OINDEX, OINDEXMAP, OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR: 1015 // unreachable - mapped to cases below by exporter 1016 1017 case OINDEX: 1018 return nodl(p.pos(), op, p.expr(), p.expr()) 1019 1020 case OSLICE, OSLICE3: 1021 n := nodl(p.pos(), op, p.expr(), nil) 1022 low, high := p.exprsOrNil() 1023 var max *Node 1024 if n.Op.IsSlice3() { 1025 max = p.expr() 1026 } 1027 n.SetSliceBounds(low, high, max) 1028 return n 1029 1030 // case OCONV, OCONVIFACE, OCONVNOP, OARRAYBYTESTR, OARRAYRUNESTR, OSTRARRAYBYTE, OSTRARRAYRUNE, ORUNESTR: 1031 // unreachable - mapped to OCONV case below by exporter 1032 1033 case OCONV: 1034 n := nodl(p.pos(), OCONV, p.expr(), nil) 1035 n.Type = p.typ() 1036 return n 1037 1038 case OCOPY, OCOMPLEX, OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN: 1039 n := npos(p.pos(), builtinCall(op)) 1040 n.List.Set(p.exprList()) 1041 if op == OAPPEND { 1042 n.SetIsddd(p.bool()) 1043 } 1044 return n 1045 1046 // case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG: 1047 // unreachable - mapped to OCALL case below by exporter 1048 1049 case OCALL: 1050 n := nodl(p.pos(), OCALL, p.expr(), nil) 1051 n.List.Set(p.exprList()) 1052 n.SetIsddd(p.bool()) 1053 return n 1054 1055 case OMAKEMAP, OMAKECHAN, OMAKESLICE: 1056 n := npos(p.pos(), builtinCall(OMAKE)) 1057 n.List.Append(typenod(p.typ())) 1058 n.List.Append(p.exprList()...) 1059 return n 1060 1061 // unary expressions 1062 case OPLUS, OMINUS, OADDR, OCOM, OIND, ONOT, ORECV: 1063 return nodl(p.pos(), op, p.expr(), nil) 1064 1065 // binary expressions 1066 case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, OLT, 1067 OLSH, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSEND, OSUB, OXOR: 1068 return nodl(p.pos(), op, p.expr(), p.expr()) 1069 1070 case OADDSTR: 1071 pos := p.pos() 1072 list := p.exprList() 1073 x := npos(pos, list[0]) 1074 for _, y := range list[1:] { 1075 x = nodl(pos, OADD, x, y) 1076 } 1077 return x 1078 1079 // case OCMPSTR, OCMPIFACE: 1080 // unreachable - mapped to std comparison operators by exporter 1081 1082 case ODCLCONST: 1083 // TODO(gri) these should not be exported in the first place 1084 return nodl(p.pos(), OEMPTY, nil, nil) 1085 1086 // -------------------------------------------------------------------- 1087 // statements 1088 case ODCL: 1089 if p.version < 2 { 1090 // versions 0 and 1 exported a bool here but it 1091 // was always false - simply ignore in this case 1092 p.bool() 1093 } 1094 pos := p.pos() 1095 lhs := dclname(p.sym()) 1096 typ := typenod(p.typ()) 1097 return npos(pos, liststmt(variter([]*Node{lhs}, typ, nil))) // TODO(gri) avoid list creation 1098 1099 // case ODCLFIELD: 1100 // unimplemented 1101 1102 // case OAS, OASWB: 1103 // unreachable - mapped to OAS case below by exporter 1104 1105 case OAS: 1106 return nodl(p.pos(), OAS, p.expr(), p.expr()) 1107 1108 case OASOP: 1109 n := nodl(p.pos(), OASOP, nil, nil) 1110 n.Etype = types.EType(p.int()) 1111 n.Left = p.expr() 1112 if !p.bool() { 1113 n.Right = nodintconst(1) 1114 n.SetImplicit(true) 1115 } else { 1116 n.Right = p.expr() 1117 } 1118 return n 1119 1120 // case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV: 1121 // unreachable - mapped to OAS2 case below by exporter 1122 1123 case OAS2: 1124 n := nodl(p.pos(), OAS2, nil, nil) 1125 n.List.Set(p.exprList()) 1126 n.Rlist.Set(p.exprList()) 1127 return n 1128 1129 case ORETURN: 1130 n := nodl(p.pos(), ORETURN, nil, nil) 1131 n.List.Set(p.exprList()) 1132 return n 1133 1134 // case ORETJMP: 1135 // unreachable - generated by compiler for trampolin routines (not exported) 1136 1137 case OPROC, ODEFER: 1138 return nodl(p.pos(), op, p.expr(), nil) 1139 1140 case OIF: 1141 types.Markdcl() 1142 n := nodl(p.pos(), OIF, nil, nil) 1143 n.Ninit.Set(p.stmtList()) 1144 n.Left = p.expr() 1145 n.Nbody.Set(p.stmtList()) 1146 n.Rlist.Set(p.stmtList()) 1147 types.Popdcl() 1148 return n 1149 1150 case OFOR: 1151 types.Markdcl() 1152 n := nodl(p.pos(), OFOR, nil, nil) 1153 n.Ninit.Set(p.stmtList()) 1154 n.Left, n.Right = p.exprsOrNil() 1155 n.Nbody.Set(p.stmtList()) 1156 types.Popdcl() 1157 return n 1158 1159 case ORANGE: 1160 types.Markdcl() 1161 n := nodl(p.pos(), ORANGE, nil, nil) 1162 n.List.Set(p.stmtList()) 1163 n.Right = p.expr() 1164 n.Nbody.Set(p.stmtList()) 1165 types.Popdcl() 1166 return n 1167 1168 case OSELECT, OSWITCH: 1169 types.Markdcl() 1170 n := nodl(p.pos(), op, nil, nil) 1171 n.Ninit.Set(p.stmtList()) 1172 n.Left, _ = p.exprsOrNil() 1173 n.List.Set(p.stmtList()) 1174 types.Popdcl() 1175 return n 1176 1177 // case OCASE, OXCASE: 1178 // unreachable - mapped to OXCASE case below by exporter 1179 1180 case OXCASE: 1181 types.Markdcl() 1182 n := nodl(p.pos(), OXCASE, nil, nil) 1183 n.Xoffset = int64(types.Block) 1184 n.List.Set(p.exprList()) 1185 // TODO(gri) eventually we must declare variables for type switch 1186 // statements (type switch statements are not yet exported) 1187 n.Nbody.Set(p.stmtList()) 1188 types.Popdcl() 1189 return n 1190 1191 // case OFALL: 1192 // unreachable - mapped to OXFALL case below by exporter 1193 1194 case OXFALL: 1195 n := nodl(p.pos(), OXFALL, nil, nil) 1196 n.Xoffset = int64(types.Block) 1197 return n 1198 1199 case OBREAK, OCONTINUE: 1200 pos := p.pos() 1201 left, _ := p.exprsOrNil() 1202 if left != nil { 1203 left = newname(left.Sym) 1204 } 1205 return nodl(pos, op, left, nil) 1206 1207 // case OEMPTY: 1208 // unreachable - not emitted by exporter 1209 1210 case OGOTO, OLABEL: 1211 return nodl(p.pos(), op, newname(p.expr().Sym), nil) 1212 1213 case OEND: 1214 return nil 1215 1216 default: 1217 Fatalf("cannot import %v (%d) node\n"+ 1218 "==> please file an issue and assign to gri@\n", op, int(op)) 1219 panic("unreachable") // satisfy compiler 1220 } 1221 } 1222 1223 func builtinCall(op Op) *Node { 1224 return nod(OCALL, mkname(builtinpkg.Lookup(goopnames[op])), nil) 1225 } 1226 1227 func (p *importer) exprsOrNil() (a, b *Node) { 1228 ab := p.int() 1229 if ab&1 != 0 { 1230 a = p.expr() 1231 } 1232 if ab&2 != 0 { 1233 b = p.expr() 1234 } 1235 return 1236 } 1237 1238 func (p *importer) fieldSym() *types.Sym { 1239 name := p.string() 1240 pkg := localpkg 1241 if !exportname(name) { 1242 pkg = p.pkg() 1243 } 1244 return pkg.Lookup(name) 1245 } 1246 1247 func (p *importer) sym() *types.Sym { 1248 name := p.string() 1249 pkg := localpkg 1250 if name != "_" { 1251 pkg = p.pkg() 1252 } 1253 linkname := p.string() 1254 sym := pkg.Lookup(name) 1255 sym.Linkname = linkname 1256 return sym 1257 } 1258 1259 func (p *importer) bool() bool { 1260 return p.int() != 0 1261 } 1262 1263 func (p *importer) op() Op { 1264 return Op(p.int()) 1265 } 1266 1267 // ---------------------------------------------------------------------------- 1268 // Low-level decoders 1269 1270 func (p *importer) tagOrIndex() int { 1271 if p.debugFormat { 1272 p.marker('t') 1273 } 1274 1275 return int(p.rawInt64()) 1276 } 1277 1278 func (p *importer) int() int { 1279 x := p.int64() 1280 if int64(int(x)) != x { 1281 p.formatErrorf("exported integer too large") 1282 } 1283 return int(x) 1284 } 1285 1286 func (p *importer) int64() int64 { 1287 if p.debugFormat { 1288 p.marker('i') 1289 } 1290 1291 return p.rawInt64() 1292 } 1293 1294 func (p *importer) string() string { 1295 if p.debugFormat { 1296 p.marker('s') 1297 } 1298 // if the string was seen before, i is its index (>= 0) 1299 // (the empty string is at index 0) 1300 i := p.rawInt64() 1301 if i >= 0 { 1302 return p.strList[i] 1303 } 1304 // otherwise, i is the negative string length (< 0) 1305 if n := int(-i); n <= cap(p.buf) { 1306 p.buf = p.buf[:n] 1307 } else { 1308 p.buf = make([]byte, n) 1309 } 1310 for i := range p.buf { 1311 p.buf[i] = p.rawByte() 1312 } 1313 s := string(p.buf) 1314 p.strList = append(p.strList, s) 1315 return s 1316 } 1317 1318 func (p *importer) marker(want byte) { 1319 if got := p.rawByte(); got != want { 1320 p.formatErrorf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read) 1321 } 1322 1323 pos := p.read 1324 if n := int(p.rawInt64()); n != pos { 1325 p.formatErrorf("incorrect position: got %d; want %d", n, pos) 1326 } 1327 } 1328 1329 // rawInt64 should only be used by low-level decoders. 1330 func (p *importer) rawInt64() int64 { 1331 i, err := binary.ReadVarint(p) 1332 if err != nil { 1333 p.formatErrorf("read error: %v", err) 1334 } 1335 return i 1336 } 1337 1338 // rawStringln should only be used to read the initial version string. 1339 func (p *importer) rawStringln(b byte) string { 1340 p.buf = p.buf[:0] 1341 for b != '\n' { 1342 p.buf = append(p.buf, b) 1343 b = p.rawByte() 1344 } 1345 return string(p.buf) 1346 } 1347 1348 // needed for binary.ReadVarint in rawInt64 1349 func (p *importer) ReadByte() (byte, error) { 1350 return p.rawByte(), nil 1351 } 1352 1353 // rawByte is the bottleneck interface for reading from p.in. 1354 // It unescapes '|' 'S' to '$' and '|' '|' to '|'. 1355 // rawByte should only be used by low-level decoders. 1356 func (p *importer) rawByte() byte { 1357 c, err := p.in.ReadByte() 1358 p.read++ 1359 if err != nil { 1360 p.formatErrorf("read error: %v", err) 1361 } 1362 if c == '|' { 1363 c, err = p.in.ReadByte() 1364 p.read++ 1365 if err != nil { 1366 p.formatErrorf("read error: %v", err) 1367 } 1368 switch c { 1369 case 'S': 1370 c = '$' 1371 case '|': 1372 // nothing to do 1373 default: 1374 p.formatErrorf("unexpected escape sequence in export data") 1375 } 1376 } 1377 return c 1378 }