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