github.com/aloncn/graphics-go@v0.0.1/src/go/internal/gcimporter/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 package gcimporter 6 7 import ( 8 "encoding/binary" 9 "fmt" 10 "go/constant" 11 "go/token" 12 "go/types" 13 "sort" 14 "unicode" 15 "unicode/utf8" 16 ) 17 18 // BImportData imports a package from the serialized package data 19 // and returns the number of bytes consumed and a reference to the package. 20 // If data is obviously malformed, an error is returned but in 21 // general it is not recommended to call BImportData on untrusted data. 22 func BImportData(imports map[string]*types.Package, data []byte, path string) (int, *types.Package, error) { 23 p := importer{ 24 imports: imports, 25 data: data, 26 } 27 p.buf = p.bufarray[:] 28 29 // read low-level encoding format 30 switch format := p.byte(); format { 31 case 'c': 32 // compact format - nothing to do 33 case 'd': 34 p.debugFormat = true 35 default: 36 return p.read, nil, fmt.Errorf("invalid encoding format in export data: got %q; want 'c' or 'd'", format) 37 } 38 39 // --- generic export data --- 40 41 if v := p.string(); v != "v0" { 42 return p.read, nil, fmt.Errorf("unknown version: %s", v) 43 } 44 45 // populate typList with predeclared "known" types 46 p.typList = append(p.typList, predeclared...) 47 48 // read package data 49 // TODO(gri) clean this up 50 i := p.tagOrIndex() 51 if i != packageTag { 52 panic(fmt.Sprintf("package tag expected, got %d", i)) 53 } 54 name := p.string() 55 if s := p.string(); s != "" { 56 panic(fmt.Sprintf("empty path expected, got %s", s)) 57 } 58 pkg := p.imports[path] 59 if pkg == nil { 60 pkg = types.NewPackage(path, name) 61 p.imports[path] = pkg 62 } 63 p.pkgList = append(p.pkgList, pkg) 64 65 if debug && p.pkgList[0] != pkg { 66 panic("imported packaged not found in pkgList[0]") 67 } 68 69 // read compiler-specific flags 70 p.string() // discard 71 72 // read consts 73 for i := p.int(); i > 0; i-- { 74 name := p.string() 75 typ := p.typ(nil) 76 val := p.value() 77 p.declare(types.NewConst(token.NoPos, pkg, name, typ, val)) 78 } 79 80 // read vars 81 for i := p.int(); i > 0; i-- { 82 name := p.string() 83 typ := p.typ(nil) 84 p.declare(types.NewVar(token.NoPos, pkg, name, typ)) 85 } 86 87 // read funcs 88 for i := p.int(); i > 0; i-- { 89 name := p.string() 90 sig := p.typ(nil).(*types.Signature) 91 p.int() // read and discard index of inlined function body 92 p.declare(types.NewFunc(token.NoPos, pkg, name, sig)) 93 } 94 95 // read types 96 for i := p.int(); i > 0; i-- { 97 // name is parsed as part of named type and the 98 // type object is added to scope via respective 99 // named type 100 _ = p.typ(nil).(*types.Named) 101 } 102 103 // ignore compiler-specific import data 104 105 // complete interfaces 106 for _, typ := range p.typList { 107 if it, ok := typ.(*types.Interface); ok { 108 it.Complete() 109 } 110 } 111 112 // record all referenced packages as imports 113 list := append(([]*types.Package)(nil), p.pkgList[1:]...) 114 sort.Sort(byPath(list)) 115 pkg.SetImports(list) 116 117 // package was imported completely and without errors 118 pkg.MarkComplete() 119 120 return p.read, pkg, nil 121 } 122 123 type importer struct { 124 imports map[string]*types.Package 125 data []byte 126 buf []byte // for reading strings 127 bufarray [64]byte // initial underlying array for buf, large enough to avoid allocation when compiling std lib 128 pkgList []*types.Package 129 typList []types.Type 130 131 debugFormat bool 132 read int // bytes read 133 } 134 135 func (p *importer) declare(obj types.Object) { 136 if alt := p.pkgList[0].Scope().Insert(obj); alt != nil { 137 // This can only happen if we import a package a second time. 138 panic(fmt.Sprintf("%s already declared", alt.Name())) 139 } 140 } 141 142 func (p *importer) pkg() *types.Package { 143 // if the package was seen before, i is its index (>= 0) 144 i := p.tagOrIndex() 145 if i >= 0 { 146 return p.pkgList[i] 147 } 148 149 // otherwise, i is the package tag (< 0) 150 if i != packageTag { 151 panic(fmt.Sprintf("unexpected package tag %d", i)) 152 } 153 154 // read package data 155 name := p.string() 156 path := p.string() 157 158 // we should never see an empty package name 159 if name == "" { 160 panic("empty package name in import") 161 } 162 163 // we should never see an empty import path 164 if path == "" { 165 panic("empty import path") 166 } 167 168 // if the package was imported before, use that one; otherwise create a new one 169 pkg := p.imports[path] 170 if pkg == nil { 171 pkg = types.NewPackage(path, name) 172 p.imports[path] = pkg 173 } 174 p.pkgList = append(p.pkgList, pkg) 175 176 return pkg 177 } 178 179 func (p *importer) record(t types.Type) { 180 p.typList = append(p.typList, t) 181 } 182 183 // A dddSlice is a types.Type representing ...T parameters. 184 // It only appears for parameter types and does not escape 185 // the importer. 186 type dddSlice struct { 187 elem types.Type 188 } 189 190 func (t *dddSlice) Underlying() types.Type { return t } 191 func (t *dddSlice) String() string { return "..." + t.elem.String() } 192 193 // parent is the package which declared the type; parent == nil means 194 // the package currently imported. The parent package is needed for 195 // exported struct fields and interface methods which don't contain 196 // explicit package information in the export data. 197 func (p *importer) typ(parent *types.Package) types.Type { 198 // if the type was seen before, i is its index (>= 0) 199 i := p.tagOrIndex() 200 if i >= 0 { 201 return p.typList[i] 202 } 203 204 // otherwise, i is the type tag (< 0) 205 switch i { 206 case namedTag: 207 // read type object 208 name := p.string() 209 parent = p.pkg() 210 scope := parent.Scope() 211 obj := scope.Lookup(name) 212 213 // if the object doesn't exist yet, create and insert it 214 if obj == nil { 215 obj = types.NewTypeName(token.NoPos, parent, name, nil) 216 scope.Insert(obj) 217 } 218 219 if _, ok := obj.(*types.TypeName); !ok { 220 panic(fmt.Sprintf("pkg = %s, name = %s => %s", parent, name, obj)) 221 } 222 223 // associate new named type with obj if it doesn't exist yet 224 t0 := types.NewNamed(obj.(*types.TypeName), nil, nil) 225 226 // but record the existing type, if any 227 t := obj.Type().(*types.Named) 228 p.record(t) 229 230 // read underlying type 231 t0.SetUnderlying(p.typ(parent)) 232 233 // interfaces don't have associated methods 234 if _, ok := t0.Underlying().(*types.Interface); ok { 235 return t 236 } 237 238 // read associated methods 239 for i := p.int(); i > 0; i-- { 240 name := p.string() 241 recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver? 242 params, isddd := p.paramList() 243 result, _ := p.paramList() 244 p.int() // read and discard index of inlined function body 245 sig := types.NewSignature(recv.At(0), params, result, isddd) 246 t0.AddMethod(types.NewFunc(token.NoPos, parent, name, sig)) 247 } 248 249 return t 250 251 case arrayTag: 252 t := new(types.Array) 253 p.record(t) 254 255 n := p.int64() 256 *t = *types.NewArray(p.typ(parent), n) 257 return t 258 259 case sliceTag: 260 t := new(types.Slice) 261 p.record(t) 262 263 *t = *types.NewSlice(p.typ(parent)) 264 return t 265 266 case dddTag: 267 t := new(dddSlice) 268 p.record(t) 269 270 t.elem = p.typ(parent) 271 return t 272 273 case structTag: 274 t := new(types.Struct) 275 p.record(t) 276 277 n := p.int() 278 fields := make([]*types.Var, n) 279 tags := make([]string, n) 280 for i := range fields { 281 fields[i] = p.field(parent) 282 tags[i] = p.string() 283 } 284 *t = *types.NewStruct(fields, tags) 285 return t 286 287 case pointerTag: 288 t := new(types.Pointer) 289 p.record(t) 290 291 *t = *types.NewPointer(p.typ(parent)) 292 return t 293 294 case signatureTag: 295 t := new(types.Signature) 296 p.record(t) 297 298 params, isddd := p.paramList() 299 result, _ := p.paramList() 300 *t = *types.NewSignature(nil, params, result, isddd) 301 return t 302 303 case interfaceTag: 304 // Create a dummy entry in the type list. This is safe because we 305 // cannot expect the interface type to appear in a cycle, as any 306 // such cycle must contain a named type which would have been 307 // first defined earlier. 308 n := len(p.typList) 309 p.record(nil) 310 311 // no embedded interfaces with gc compiler 312 if p.int() != 0 { 313 panic("unexpected embedded interface") 314 } 315 316 // read methods 317 methods := make([]*types.Func, p.int()) 318 for i := range methods { 319 pkg, name := p.fieldName(parent) 320 params, isddd := p.paramList() 321 result, _ := p.paramList() 322 sig := types.NewSignature(nil, params, result, isddd) 323 methods[i] = types.NewFunc(token.NoPos, pkg, name, sig) 324 } 325 326 t := types.NewInterface(methods, nil) 327 p.typList[n] = t 328 return t 329 330 case mapTag: 331 t := new(types.Map) 332 p.record(t) 333 334 key := p.typ(parent) 335 val := p.typ(parent) 336 *t = *types.NewMap(key, val) 337 return t 338 339 case chanTag: 340 t := new(types.Chan) 341 p.record(t) 342 343 var dir types.ChanDir 344 // tag values must match the constants in cmd/compile/internal/gc/go.go 345 switch d := p.int(); d { 346 case 1 /* Crecv */ : 347 dir = types.RecvOnly 348 case 2 /* Csend */ : 349 dir = types.SendOnly 350 case 3 /* Cboth */ : 351 dir = types.SendRecv 352 default: 353 panic(fmt.Sprintf("unexpected channel dir %d", d)) 354 } 355 val := p.typ(parent) 356 *t = *types.NewChan(dir, val) 357 return t 358 359 default: 360 panic(fmt.Sprintf("unexpected type tag %d", i)) 361 } 362 } 363 364 func (p *importer) field(parent *types.Package) *types.Var { 365 pkg, name := p.fieldName(parent) 366 typ := p.typ(parent) 367 368 anonymous := false 369 if name == "" { 370 // anonymous field - typ must be T or *T and T must be a type name 371 switch typ := deref(typ).(type) { 372 case *types.Basic: // basic types are named types 373 pkg = nil // // objects defined in Universe scope have no package 374 name = typ.Name() 375 case *types.Named: 376 name = typ.Obj().Name() 377 default: 378 panic("anonymous field expected") 379 } 380 anonymous = true 381 } 382 383 return types.NewField(token.NoPos, pkg, name, typ, anonymous) 384 } 385 386 func (p *importer) fieldName(parent *types.Package) (*types.Package, string) { 387 pkg := parent 388 if pkg == nil { 389 // use the imported package instead 390 pkg = p.pkgList[0] 391 } 392 name := p.string() 393 if name == "" { 394 return pkg, "" // anonymous 395 } 396 if name == "?" || name != "_" && !exported(name) { 397 // explicitly qualified field 398 if name == "?" { 399 name = "" // anonymous 400 } 401 pkg = p.pkg() 402 } 403 return pkg, name 404 } 405 406 func (p *importer) paramList() (*types.Tuple, bool) { 407 n := p.int() 408 if n == 0 { 409 return nil, false 410 } 411 // negative length indicates unnamed parameters 412 named := true 413 if n < 0 { 414 n = -n 415 named = false 416 } 417 // n > 0 418 params := make([]*types.Var, n) 419 isddd := false 420 for i := range params { 421 params[i], isddd = p.param(named) 422 } 423 return types.NewTuple(params...), isddd 424 } 425 426 func (p *importer) param(named bool) (*types.Var, bool) { 427 t := p.typ(nil) 428 td, isddd := t.(*dddSlice) 429 if isddd { 430 t = types.NewSlice(td.elem) 431 } 432 433 var name string 434 if named { 435 name = p.string() 436 if name == "" { 437 panic("expected named parameter") 438 } 439 } 440 441 // read and discard compiler-specific info 442 p.string() 443 444 return types.NewVar(token.NoPos, nil, name, t), isddd 445 } 446 447 func exported(name string) bool { 448 ch, _ := utf8.DecodeRuneInString(name) 449 return unicode.IsUpper(ch) 450 } 451 452 func (p *importer) value() constant.Value { 453 switch tag := p.tagOrIndex(); tag { 454 case falseTag: 455 return constant.MakeBool(false) 456 case trueTag: 457 return constant.MakeBool(true) 458 case int64Tag: 459 return constant.MakeInt64(p.int64()) 460 case floatTag: 461 return p.float() 462 case complexTag: 463 re := p.float() 464 im := p.float() 465 return constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) 466 case stringTag: 467 return constant.MakeString(p.string()) 468 default: 469 panic(fmt.Sprintf("unexpected value tag %d", tag)) 470 } 471 } 472 473 func (p *importer) float() constant.Value { 474 sign := p.int() 475 if sign == 0 { 476 return constant.MakeInt64(0) 477 } 478 479 exp := p.int() 480 mant := []byte(p.string()) // big endian 481 482 // remove leading 0's if any 483 for len(mant) > 0 && mant[0] == 0 { 484 mant = mant[1:] 485 } 486 487 // convert to little endian 488 // TODO(gri) go/constant should have a more direct conversion function 489 // (e.g., once it supports a big.Float based implementation) 490 for i, j := 0, len(mant)-1; i < j; i, j = i+1, j-1 { 491 mant[i], mant[j] = mant[j], mant[i] 492 } 493 494 // adjust exponent (constant.MakeFromBytes creates an integer value, 495 // but mant represents the mantissa bits such that 0.5 <= mant < 1.0) 496 exp -= len(mant) << 3 497 if len(mant) > 0 { 498 for msd := mant[len(mant)-1]; msd&0x80 == 0; msd <<= 1 { 499 exp++ 500 } 501 } 502 503 x := constant.MakeFromBytes(mant) 504 switch { 505 case exp < 0: 506 d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp)) 507 x = constant.BinaryOp(x, token.QUO, d) 508 case exp > 0: 509 x = constant.Shift(x, token.SHL, uint(exp)) 510 } 511 512 if sign < 0 { 513 x = constant.UnaryOp(token.SUB, x, 0) 514 } 515 return x 516 } 517 518 // ---------------------------------------------------------------------------- 519 // Low-level decoders 520 521 func (p *importer) tagOrIndex() int { 522 if p.debugFormat { 523 p.marker('t') 524 } 525 526 return int(p.rawInt64()) 527 } 528 529 func (p *importer) int() int { 530 x := p.int64() 531 if int64(int(x)) != x { 532 panic("exported integer too large") 533 } 534 return int(x) 535 } 536 537 func (p *importer) int64() int64 { 538 if p.debugFormat { 539 p.marker('i') 540 } 541 542 return p.rawInt64() 543 } 544 545 func (p *importer) string() string { 546 if p.debugFormat { 547 p.marker('s') 548 } 549 550 if n := int(p.rawInt64()); n > 0 { 551 if cap(p.buf) < n { 552 p.buf = make([]byte, n) 553 } else { 554 p.buf = p.buf[:n] 555 } 556 for i := 0; i < n; i++ { 557 p.buf[i] = p.byte() 558 } 559 return string(p.buf) 560 } 561 562 return "" 563 } 564 565 func (p *importer) marker(want byte) { 566 if got := p.byte(); got != want { 567 panic(fmt.Sprintf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read)) 568 } 569 570 pos := p.read 571 if n := int(p.rawInt64()); n != pos { 572 panic(fmt.Sprintf("incorrect position: got %d; want %d", n, pos)) 573 } 574 } 575 576 // rawInt64 should only be used by low-level decoders 577 func (p *importer) rawInt64() int64 { 578 i, err := binary.ReadVarint(p) 579 if err != nil { 580 panic(fmt.Sprintf("read error: %v", err)) 581 } 582 return i 583 } 584 585 // needed for binary.ReadVarint in rawInt64 586 func (p *importer) ReadByte() (byte, error) { 587 return p.byte(), nil 588 } 589 590 // byte is the bottleneck interface for reading p.data. 591 // It unescapes '|' 'S' to '$' and '|' '|' to '|'. 592 func (p *importer) byte() byte { 593 b := p.data[0] 594 r := 1 595 if b == '|' { 596 b = p.data[1] 597 r = 2 598 switch b { 599 case 'S': 600 b = '$' 601 case '|': 602 // nothing to do 603 default: 604 panic("unexpected escape sequence in export data") 605 } 606 } 607 p.data = p.data[r:] 608 p.read += r 609 return b 610 611 } 612 613 // ---------------------------------------------------------------------------- 614 // Export format 615 616 // Tags. Must be < 0. 617 const ( 618 // Packages 619 packageTag = -(iota + 1) 620 621 // Types 622 namedTag 623 arrayTag 624 sliceTag 625 dddTag 626 structTag 627 pointerTag 628 signatureTag 629 interfaceTag 630 mapTag 631 chanTag 632 633 // Values 634 falseTag 635 trueTag 636 int64Tag 637 floatTag 638 fractionTag // not used by gc 639 complexTag 640 stringTag 641 ) 642 643 var predeclared = []types.Type{ 644 // basic types 645 types.Typ[types.Bool], 646 types.Typ[types.Int], 647 types.Typ[types.Int8], 648 types.Typ[types.Int16], 649 types.Typ[types.Int32], 650 types.Typ[types.Int64], 651 types.Typ[types.Uint], 652 types.Typ[types.Uint8], 653 types.Typ[types.Uint16], 654 types.Typ[types.Uint32], 655 types.Typ[types.Uint64], 656 types.Typ[types.Uintptr], 657 types.Typ[types.Float32], 658 types.Typ[types.Float64], 659 types.Typ[types.Complex64], 660 types.Typ[types.Complex128], 661 types.Typ[types.String], 662 663 // aliases 664 types.Universe.Lookup("byte").Type(), 665 types.Universe.Lookup("rune").Type(), 666 667 // error 668 types.Universe.Lookup("error").Type(), 669 670 // untyped types 671 types.Typ[types.UntypedBool], 672 types.Typ[types.UntypedInt], 673 types.Typ[types.UntypedRune], 674 types.Typ[types.UntypedFloat], 675 types.Typ[types.UntypedComplex], 676 types.Typ[types.UntypedString], 677 types.Typ[types.UntypedNil], 678 679 // package unsafe 680 types.Typ[types.UnsafePointer], 681 }