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