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