github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/go/internal/gcimporter/iimport.go (about) 1 // Copyright 2018 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 // Indexed package import. 6 // See cmd/compile/internal/gc/iexport.go for the export data format. 7 8 package gcimporter 9 10 import ( 11 "bytes" 12 "encoding/binary" 13 "fmt" 14 "go/constant" 15 "go/token" 16 "go/types" 17 "io" 18 "sort" 19 ) 20 21 type intReader struct { 22 *bytes.Reader 23 path string 24 } 25 26 func (r *intReader) int64() int64 { 27 i, err := binary.ReadVarint(r.Reader) 28 if err != nil { 29 errorf("import %q: read varint error: %v", r.path, err) 30 } 31 return i 32 } 33 34 func (r *intReader) uint64() uint64 { 35 i, err := binary.ReadUvarint(r.Reader) 36 if err != nil { 37 errorf("import %q: read varint error: %v", r.path, err) 38 } 39 return i 40 } 41 42 const predeclReserved = 32 43 44 type itag uint64 45 46 const ( 47 // Types 48 definedType itag = iota 49 pointerType 50 sliceType 51 arrayType 52 chanType 53 mapType 54 signatureType 55 structType 56 interfaceType 57 ) 58 59 // iImportData imports a package from the serialized package data 60 // and returns the number of bytes consumed and a reference to the package. 61 // If the export data version is not recognized or the format is otherwise 62 // compromised, an error is returned. 63 func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) { 64 const currentVersion = 0 65 version := -1 66 defer func() { 67 if e := recover(); e != nil { 68 if version > currentVersion { 69 err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e) 70 } else { 71 err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e) 72 } 73 } 74 }() 75 76 r := &intReader{bytes.NewReader(data), path} 77 78 version = int(r.uint64()) 79 switch version { 80 case currentVersion: 81 default: 82 errorf("unknown iexport format version %d", version) 83 } 84 85 sLen := int64(r.uint64()) 86 dLen := int64(r.uint64()) 87 88 whence, _ := r.Seek(0, io.SeekCurrent) 89 stringData := data[whence : whence+sLen] 90 declData := data[whence+sLen : whence+sLen+dLen] 91 r.Seek(sLen+dLen, io.SeekCurrent) 92 93 p := iimporter{ 94 ipath: path, 95 96 stringData: stringData, 97 stringCache: make(map[uint64]string), 98 pkgCache: make(map[uint64]*types.Package), 99 100 declData: declData, 101 pkgIndex: make(map[*types.Package]map[string]uint64), 102 typCache: make(map[uint64]types.Type), 103 104 fake: fakeFileSet{ 105 fset: fset, 106 files: make(map[string]*token.File), 107 }, 108 } 109 110 for i, pt := range predeclared { 111 p.typCache[uint64(i)] = pt 112 } 113 114 pkgList := make([]*types.Package, r.uint64()) 115 for i := range pkgList { 116 pkgPathOff := r.uint64() 117 pkgPath := p.stringAt(pkgPathOff) 118 pkgName := p.stringAt(r.uint64()) 119 _ = r.uint64() // package height; unused by go/types 120 121 if pkgPath == "" { 122 pkgPath = path 123 } 124 pkg := imports[pkgPath] 125 if pkg == nil { 126 pkg = types.NewPackage(pkgPath, pkgName) 127 imports[pkgPath] = pkg 128 } else if pkg.Name() != pkgName { 129 errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path) 130 } 131 132 p.pkgCache[pkgPathOff] = pkg 133 134 nameIndex := make(map[string]uint64) 135 for nSyms := r.uint64(); nSyms > 0; nSyms-- { 136 name := p.stringAt(r.uint64()) 137 nameIndex[name] = r.uint64() 138 } 139 140 p.pkgIndex[pkg] = nameIndex 141 pkgList[i] = pkg 142 } 143 144 localpkg := pkgList[0] 145 146 names := make([]string, 0, len(p.pkgIndex[localpkg])) 147 for name := range p.pkgIndex[localpkg] { 148 names = append(names, name) 149 } 150 sort.Strings(names) 151 for _, name := range names { 152 p.doDecl(localpkg, name) 153 } 154 155 for _, typ := range p.interfaceList { 156 typ.Complete() 157 } 158 159 // record all referenced packages as imports 160 list := append(([]*types.Package)(nil), pkgList[1:]...) 161 sort.Sort(byPath(list)) 162 localpkg.SetImports(list) 163 164 // package was imported completely and without errors 165 localpkg.MarkComplete() 166 167 consumed, _ := r.Seek(0, io.SeekCurrent) 168 return int(consumed), localpkg, nil 169 } 170 171 type iimporter struct { 172 ipath string 173 174 stringData []byte 175 stringCache map[uint64]string 176 pkgCache map[uint64]*types.Package 177 178 declData []byte 179 pkgIndex map[*types.Package]map[string]uint64 180 typCache map[uint64]types.Type 181 182 fake fakeFileSet 183 interfaceList []*types.Interface 184 } 185 186 func (p *iimporter) doDecl(pkg *types.Package, name string) { 187 // See if we've already imported this declaration. 188 if obj := pkg.Scope().Lookup(name); obj != nil { 189 return 190 } 191 192 off, ok := p.pkgIndex[pkg][name] 193 if !ok { 194 errorf("%v.%v not in index", pkg, name) 195 } 196 197 r := &importReader{p: p, currPkg: pkg} 198 r.declReader.Reset(p.declData[off:]) 199 200 r.obj(name) 201 } 202 203 func (p *iimporter) stringAt(off uint64) string { 204 if s, ok := p.stringCache[off]; ok { 205 return s 206 } 207 208 slen, n := binary.Uvarint(p.stringData[off:]) 209 if n <= 0 { 210 errorf("varint failed") 211 } 212 spos := off + uint64(n) 213 s := string(p.stringData[spos : spos+slen]) 214 p.stringCache[off] = s 215 return s 216 } 217 218 func (p *iimporter) pkgAt(off uint64) *types.Package { 219 if pkg, ok := p.pkgCache[off]; ok { 220 return pkg 221 } 222 path := p.stringAt(off) 223 errorf("missing package %q in %q", path, p.ipath) 224 return nil 225 } 226 227 func (p *iimporter) typAt(off uint64, base *types.Named) types.Type { 228 if t, ok := p.typCache[off]; ok && (base == nil || !isInterface(t)) { 229 return t 230 } 231 232 if off < predeclReserved { 233 errorf("predeclared type missing from cache: %v", off) 234 } 235 236 r := &importReader{p: p} 237 r.declReader.Reset(p.declData[off-predeclReserved:]) 238 t := r.doType(base) 239 240 if base == nil || !isInterface(t) { 241 p.typCache[off] = t 242 } 243 return t 244 } 245 246 type importReader struct { 247 p *iimporter 248 declReader bytes.Reader 249 currPkg *types.Package 250 prevFile string 251 prevLine int64 252 } 253 254 func (r *importReader) obj(name string) { 255 tag := r.byte() 256 pos := r.pos() 257 258 switch tag { 259 case 'A': 260 typ := r.typ() 261 262 r.declare(types.NewTypeName(pos, r.currPkg, name, typ)) 263 264 case 'C': 265 typ, val := r.value() 266 267 r.declare(types.NewConst(pos, r.currPkg, name, typ, val)) 268 269 case 'F': 270 sig := r.signature(nil) 271 272 r.declare(types.NewFunc(pos, r.currPkg, name, sig)) 273 274 case 'T': 275 // Types can be recursive. We need to setup a stub 276 // declaration before recursing. 277 obj := types.NewTypeName(pos, r.currPkg, name, nil) 278 named := types.NewNamed(obj, nil, nil) 279 r.declare(obj) 280 281 underlying := r.p.typAt(r.uint64(), named).Underlying() 282 named.SetUnderlying(underlying) 283 284 if !isInterface(underlying) { 285 for n := r.uint64(); n > 0; n-- { 286 mpos := r.pos() 287 mname := r.ident() 288 recv := r.param() 289 msig := r.signature(recv) 290 291 named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig)) 292 } 293 } 294 295 case 'V': 296 typ := r.typ() 297 298 r.declare(types.NewVar(pos, r.currPkg, name, typ)) 299 300 default: 301 errorf("unexpected tag: %v", tag) 302 } 303 } 304 305 func (r *importReader) declare(obj types.Object) { 306 obj.Pkg().Scope().Insert(obj) 307 } 308 309 func (r *importReader) value() (typ types.Type, val constant.Value) { 310 typ = r.typ() 311 312 switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType { 313 case types.IsBoolean: 314 val = constant.MakeBool(r.bool()) 315 316 case types.IsString: 317 val = constant.MakeString(r.string()) 318 319 case types.IsInteger: 320 val = r.mpint(b) 321 322 case types.IsFloat: 323 val = r.mpfloat(b) 324 325 case types.IsComplex: 326 re := r.mpfloat(b) 327 im := r.mpfloat(b) 328 val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) 329 330 default: 331 errorf("unexpected type %v", typ) // panics 332 panic("unreachable") 333 } 334 335 return 336 } 337 338 func intSize(b *types.Basic) (signed bool, maxBytes uint) { 339 if (b.Info() & types.IsUntyped) != 0 { 340 return true, 64 341 } 342 343 switch b.Kind() { 344 case types.Float32, types.Complex64: 345 return true, 3 346 case types.Float64, types.Complex128: 347 return true, 7 348 } 349 350 signed = (b.Info() & types.IsUnsigned) == 0 351 switch b.Kind() { 352 case types.Int8, types.Uint8: 353 maxBytes = 1 354 case types.Int16, types.Uint16: 355 maxBytes = 2 356 case types.Int32, types.Uint32: 357 maxBytes = 4 358 default: 359 maxBytes = 8 360 } 361 362 return 363 } 364 365 func (r *importReader) mpint(b *types.Basic) constant.Value { 366 signed, maxBytes := intSize(b) 367 368 maxSmall := 256 - maxBytes 369 if signed { 370 maxSmall = 256 - 2*maxBytes 371 } 372 if maxBytes == 1 { 373 maxSmall = 256 374 } 375 376 n, _ := r.declReader.ReadByte() 377 if uint(n) < maxSmall { 378 v := int64(n) 379 if signed { 380 v >>= 1 381 if n&1 != 0 { 382 v = ^v 383 } 384 } 385 return constant.MakeInt64(v) 386 } 387 388 v := -n 389 if signed { 390 v = -(n &^ 1) >> 1 391 } 392 if v < 1 || uint(v) > maxBytes { 393 errorf("weird decoding: %v, %v => %v", n, signed, v) 394 } 395 396 buf := make([]byte, v) 397 io.ReadFull(&r.declReader, buf) 398 399 // convert to little endian 400 // TODO(gri) go/constant should have a more direct conversion function 401 // (e.g., once it supports a big.Float based implementation) 402 for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 { 403 buf[i], buf[j] = buf[j], buf[i] 404 } 405 406 x := constant.MakeFromBytes(buf) 407 if signed && n&1 != 0 { 408 x = constant.UnaryOp(token.SUB, x, 0) 409 } 410 return x 411 } 412 413 func (r *importReader) mpfloat(b *types.Basic) constant.Value { 414 x := r.mpint(b) 415 if constant.Sign(x) == 0 { 416 return x 417 } 418 419 exp := r.int64() 420 switch { 421 case exp > 0: 422 x = constant.Shift(x, token.SHL, uint(exp)) 423 case exp < 0: 424 d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp)) 425 x = constant.BinaryOp(x, token.QUO, d) 426 } 427 return x 428 } 429 430 func (r *importReader) ident() string { 431 return r.string() 432 } 433 434 func (r *importReader) qualifiedIdent() (*types.Package, string) { 435 name := r.string() 436 pkg := r.pkg() 437 return pkg, name 438 } 439 440 func (r *importReader) pos() token.Pos { 441 delta := r.int64() 442 if delta != deltaNewFile { 443 r.prevLine += delta 444 } else if l := r.int64(); l == -1 { 445 r.prevLine += deltaNewFile 446 } else { 447 r.prevFile = r.string() 448 r.prevLine = l 449 } 450 451 if r.prevFile == "" && r.prevLine == 0 { 452 return token.NoPos 453 } 454 455 return r.p.fake.pos(r.prevFile, int(r.prevLine)) 456 } 457 458 func (r *importReader) typ() types.Type { 459 return r.p.typAt(r.uint64(), nil) 460 } 461 462 func isInterface(t types.Type) bool { 463 _, ok := t.(*types.Interface) 464 return ok 465 } 466 467 func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) } 468 func (r *importReader) string() string { return r.p.stringAt(r.uint64()) } 469 470 func (r *importReader) doType(base *types.Named) types.Type { 471 switch k := r.kind(); k { 472 default: 473 errorf("unexpected kind tag in %q: %v", r.p.ipath, k) 474 return nil 475 476 case definedType: 477 pkg, name := r.qualifiedIdent() 478 r.p.doDecl(pkg, name) 479 return pkg.Scope().Lookup(name).(*types.TypeName).Type() 480 case pointerType: 481 return types.NewPointer(r.typ()) 482 case sliceType: 483 return types.NewSlice(r.typ()) 484 case arrayType: 485 n := r.uint64() 486 return types.NewArray(r.typ(), int64(n)) 487 case chanType: 488 dir := chanDir(int(r.uint64())) 489 return types.NewChan(dir, r.typ()) 490 case mapType: 491 return types.NewMap(r.typ(), r.typ()) 492 case signatureType: 493 r.currPkg = r.pkg() 494 return r.signature(nil) 495 496 case structType: 497 r.currPkg = r.pkg() 498 499 fields := make([]*types.Var, r.uint64()) 500 tags := make([]string, len(fields)) 501 for i := range fields { 502 fpos := r.pos() 503 fname := r.ident() 504 ftyp := r.typ() 505 emb := r.bool() 506 tag := r.string() 507 508 fields[i] = types.NewField(fpos, r.currPkg, fname, ftyp, emb) 509 tags[i] = tag 510 } 511 return types.NewStruct(fields, tags) 512 513 case interfaceType: 514 r.currPkg = r.pkg() 515 516 embeddeds := make([]types.Type, r.uint64()) 517 for i := range embeddeds { 518 _ = r.pos() 519 embeddeds[i] = r.typ() 520 } 521 522 methods := make([]*types.Func, r.uint64()) 523 for i := range methods { 524 mpos := r.pos() 525 mname := r.ident() 526 527 // TODO(mdempsky): Matches bimport.go, but I 528 // don't agree with this. 529 var recv *types.Var 530 if base != nil { 531 recv = types.NewVar(token.NoPos, r.currPkg, "", base) 532 } 533 534 msig := r.signature(recv) 535 methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig) 536 } 537 538 typ := types.NewInterfaceType(methods, embeddeds) 539 r.p.interfaceList = append(r.p.interfaceList, typ) 540 return typ 541 } 542 } 543 544 func (r *importReader) kind() itag { 545 return itag(r.uint64()) 546 } 547 548 func (r *importReader) signature(recv *types.Var) *types.Signature { 549 params := r.paramList() 550 results := r.paramList() 551 variadic := params.Len() > 0 && r.bool() 552 return types.NewSignature(recv, params, results, variadic) 553 } 554 555 func (r *importReader) paramList() *types.Tuple { 556 xs := make([]*types.Var, r.uint64()) 557 for i := range xs { 558 xs[i] = r.param() 559 } 560 return types.NewTuple(xs...) 561 } 562 563 func (r *importReader) param() *types.Var { 564 pos := r.pos() 565 name := r.ident() 566 typ := r.typ() 567 return types.NewParam(pos, r.currPkg, name, typ) 568 } 569 570 func (r *importReader) bool() bool { 571 return r.uint64() != 0 572 } 573 574 func (r *importReader) int64() int64 { 575 n, err := binary.ReadVarint(&r.declReader) 576 if err != nil { 577 errorf("readVarint: %v", err) 578 } 579 return n 580 } 581 582 func (r *importReader) uint64() uint64 { 583 n, err := binary.ReadUvarint(&r.declReader) 584 if err != nil { 585 errorf("readUvarint: %v", err) 586 } 587 return n 588 } 589 590 func (r *importReader) byte() byte { 591 x, err := r.declReader.ReadByte() 592 if err != nil { 593 errorf("declReader.ReadByte: %v", err) 594 } 595 return x 596 }