github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/cmd/compile/internal/gc/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 iexport.go for the export data format. 7 8 package gc 9 10 import ( 11 "cmd/compile/internal/types" 12 "cmd/internal/bio" 13 "cmd/internal/src" 14 "encoding/binary" 15 "fmt" 16 "math/big" 17 "os" 18 "strings" 19 ) 20 21 // An iimporterAndOffset identifies an importer and an offset within 22 // its data section. 23 type iimporterAndOffset struct { 24 p *iimporter 25 off uint64 26 } 27 28 var ( 29 // declImporter maps from imported identifiers to an importer 30 // and offset where that identifier's declaration can be read. 31 declImporter = map[*types.Sym]iimporterAndOffset{} 32 33 // inlineImporter is like declImporter, but for inline bodies 34 // for function and method symbols. 35 inlineImporter = map[*types.Sym]iimporterAndOffset{} 36 ) 37 38 func expandDecl(n *Node) { 39 if n.Op != ONONAME { 40 return 41 } 42 43 r := importReaderFor(n, declImporter) 44 if r == nil { 45 // Can happen if user tries to reference an undeclared name. 46 return 47 } 48 49 r.doDecl(n) 50 } 51 52 func expandInline(fn *Node) { 53 if fn.Func.Inl.Body != nil { 54 return 55 } 56 57 r := importReaderFor(fn, inlineImporter) 58 if r == nil { 59 Fatalf("missing import reader for %v", fn) 60 } 61 62 r.doInline(fn) 63 } 64 65 func importReaderFor(n *Node, importers map[*types.Sym]iimporterAndOffset) *importReader { 66 x, ok := importers[n.Sym] 67 if !ok { 68 return nil 69 } 70 71 return x.p.newReader(x.off, n.Sym.Pkg) 72 } 73 74 type intReader struct { 75 *bio.Reader 76 pkg *types.Pkg 77 } 78 79 func (r *intReader) int64() int64 { 80 i, err := binary.ReadVarint(r.Reader) 81 if err != nil { 82 yyerror("import %q: read error: %v", r.pkg.Path, err) 83 errorexit() 84 } 85 return i 86 } 87 88 func (r *intReader) uint64() uint64 { 89 i, err := binary.ReadUvarint(r.Reader) 90 if err != nil { 91 yyerror("import %q: read error: %v", r.pkg.Path, err) 92 errorexit() 93 } 94 return i 95 } 96 97 func iimport(pkg *types.Pkg, in *bio.Reader) { 98 ir := &intReader{in, pkg} 99 100 version := ir.uint64() 101 if version != iexportVersion { 102 yyerror("import %q: unknown export format version %d", pkg.Path, version) 103 errorexit() 104 } 105 106 sLen := ir.uint64() 107 dLen := ir.uint64() 108 109 // Map string (and data) section into memory as a single large 110 // string. This reduces heap fragmentation and allows 111 // returning individual substrings very efficiently. 112 data, err := mapFile(in.File(), in.Offset(), int64(sLen+dLen)) 113 if err != nil { 114 yyerror("import %q: mapping input: %v", pkg.Path, err) 115 errorexit() 116 } 117 stringData := data[:sLen] 118 declData := data[sLen:] 119 120 in.Seek(int64(sLen+dLen), os.SEEK_CUR) 121 122 p := &iimporter{ 123 ipkg: pkg, 124 125 pkgCache: map[uint64]*types.Pkg{}, 126 posBaseCache: map[uint64]*src.PosBase{}, 127 typCache: map[uint64]*types.Type{}, 128 129 stringData: stringData, 130 declData: declData, 131 } 132 133 for i, pt := range predeclared() { 134 p.typCache[uint64(i)] = pt 135 } 136 137 // Declaration index. 138 for nPkgs := ir.uint64(); nPkgs > 0; nPkgs-- { 139 pkg := p.pkgAt(ir.uint64()) 140 pkgName := p.stringAt(ir.uint64()) 141 pkgHeight := int(ir.uint64()) 142 if pkg.Name == "" { 143 pkg.Name = pkgName 144 pkg.Height = pkgHeight 145 numImport[pkgName]++ 146 147 // TODO(mdempsky): This belongs somewhere else. 148 pkg.Lookup("_").Def = asTypesNode(nblank) 149 } else { 150 if pkg.Name != pkgName { 151 Fatalf("conflicting package names %v and %v for path %q", pkg.Name, pkgName, pkg.Path) 152 } 153 if pkg.Height != pkgHeight { 154 Fatalf("conflicting package heights %v and %v for path %q", pkg.Height, pkgHeight, pkg.Path) 155 } 156 } 157 158 for nSyms := ir.uint64(); nSyms > 0; nSyms-- { 159 s := pkg.Lookup(p.stringAt(ir.uint64())) 160 off := ir.uint64() 161 162 if _, ok := declImporter[s]; ok { 163 continue 164 } 165 declImporter[s] = iimporterAndOffset{p, off} 166 167 // Create stub declaration. If used, this will 168 // be overwritten by expandDecl. 169 if s.Def != nil { 170 Fatalf("unexpected definition for %v: %v", s, asNode(s.Def)) 171 } 172 s.Def = asTypesNode(npos(src.NoXPos, dclname(s))) 173 } 174 } 175 176 // Inline body index. 177 for nPkgs := ir.uint64(); nPkgs > 0; nPkgs-- { 178 pkg := p.pkgAt(ir.uint64()) 179 180 for nSyms := ir.uint64(); nSyms > 0; nSyms-- { 181 s := pkg.Lookup(p.stringAt(ir.uint64())) 182 off := ir.uint64() 183 184 if _, ok := inlineImporter[s]; ok { 185 continue 186 } 187 inlineImporter[s] = iimporterAndOffset{p, off} 188 } 189 } 190 } 191 192 type iimporter struct { 193 ipkg *types.Pkg 194 195 pkgCache map[uint64]*types.Pkg 196 posBaseCache map[uint64]*src.PosBase 197 typCache map[uint64]*types.Type 198 199 stringData string 200 declData string 201 } 202 203 func (p *iimporter) stringAt(off uint64) string { 204 var x [binary.MaxVarintLen64]byte 205 n := copy(x[:], p.stringData[off:]) 206 207 slen, n := binary.Uvarint(x[:n]) 208 if n <= 0 { 209 Fatalf("varint failed") 210 } 211 spos := off + uint64(n) 212 return p.stringData[spos : spos+slen] 213 } 214 215 func (p *iimporter) posBaseAt(off uint64) *src.PosBase { 216 if posBase, ok := p.posBaseCache[off]; ok { 217 return posBase 218 } 219 220 file := p.stringAt(off) 221 posBase := src.NewFileBase(file, file) 222 p.posBaseCache[off] = posBase 223 return posBase 224 } 225 226 func (p *iimporter) pkgAt(off uint64) *types.Pkg { 227 if pkg, ok := p.pkgCache[off]; ok { 228 return pkg 229 } 230 231 pkg := p.ipkg 232 if pkgPath := p.stringAt(off); pkgPath != "" { 233 pkg = types.NewPkg(pkgPath, "") 234 } 235 p.pkgCache[off] = pkg 236 return pkg 237 } 238 239 // An importReader keeps state for reading an individual imported 240 // object (declaration or inline body). 241 type importReader struct { 242 strings.Reader 243 p *iimporter 244 245 currPkg *types.Pkg 246 prevBase *src.PosBase 247 prevLine int64 248 } 249 250 func (p *iimporter) newReader(off uint64, pkg *types.Pkg) *importReader { 251 r := &importReader{ 252 p: p, 253 currPkg: pkg, 254 } 255 // (*strings.Reader).Reset wasn't added until Go 1.7, and we 256 // need to build with Go 1.4. 257 r.Reader = *strings.NewReader(p.declData[off:]) 258 return r 259 } 260 261 func (r *importReader) string() string { return r.p.stringAt(r.uint64()) } 262 func (r *importReader) posBase() *src.PosBase { return r.p.posBaseAt(r.uint64()) } 263 func (r *importReader) pkg() *types.Pkg { return r.p.pkgAt(r.uint64()) } 264 265 func (r *importReader) setPkg() { 266 r.currPkg = r.pkg() 267 } 268 269 func (r *importReader) doDecl(n *Node) { 270 if n.Op != ONONAME { 271 Fatalf("doDecl: unexpected Op for %v: %v", n.Sym, n.Op) 272 } 273 274 tag := r.byte() 275 pos := r.pos() 276 277 switch tag { 278 case 'A': 279 typ := r.typ() 280 281 importalias(r.p.ipkg, pos, n.Sym, typ) 282 283 case 'C': 284 typ, val := r.value() 285 286 importconst(r.p.ipkg, pos, n.Sym, typ, val) 287 288 case 'F': 289 typ := r.signature(nil) 290 291 importfunc(r.p.ipkg, pos, n.Sym, typ) 292 r.funcExt(n) 293 294 case 'T': 295 // Types can be recursive. We need to setup a stub 296 // declaration before recursing. 297 t := importtype(r.p.ipkg, pos, n.Sym) 298 299 // We also need to defer width calculations until 300 // after the underlying type has been assigned. 301 // 302 // TODO(mdempsky): Add nesting support directly to 303 // {defer,resume}checkwidth? Width calculations are 304 // already deferred during initial typechecking, but 305 // not when we're expanding inline function bodies, so 306 // we currently need to handle both cases here. 307 deferring := defercalc != 0 308 if !deferring { 309 defercheckwidth() 310 } 311 underlying := r.typ() 312 copytype(typenod(t), underlying) 313 if !deferring { 314 resumecheckwidth() 315 } 316 317 if underlying.IsInterface() { 318 break 319 } 320 321 ms := make([]*types.Field, r.uint64()) 322 for i := range ms { 323 mpos := r.pos() 324 msym := r.ident() 325 recv := r.param() 326 mtyp := r.signature(recv) 327 328 f := types.NewField() 329 f.Pos = mpos 330 f.Sym = msym 331 f.Type = mtyp 332 ms[i] = f 333 334 m := newfuncnamel(mpos, methodSym(recv.Type, msym)) 335 m.Type = mtyp 336 m.SetClass(PFUNC) 337 // methodSym already marked m.Sym as a function. 338 339 // (comment from parser.go) 340 // inl.C's inlnode in on a dotmeth node expects to find the inlineable body as 341 // (dotmeth's type).Nname.Inl, and dotmeth's type has been pulled 342 // out by typecheck's lookdot as this $$.ttype. So by providing 343 // this back link here we avoid special casing there. 344 mtyp.SetNname(asTypesNode(m)) 345 } 346 t.Methods().Set(ms) 347 348 for _, m := range ms { 349 r.methExt(m) 350 } 351 352 case 'V': 353 typ := r.typ() 354 355 importvar(r.p.ipkg, pos, n.Sym, typ) 356 r.varExt(n) 357 358 default: 359 Fatalf("unexpected tag: %v", tag) 360 } 361 } 362 363 func (p *importReader) value() (typ *types.Type, v Val) { 364 typ = p.typ() 365 366 switch constTypeOf(typ) { 367 case CTNIL: 368 v.U = &NilVal{} 369 case CTBOOL: 370 v.U = p.bool() 371 case CTSTR: 372 v.U = p.string() 373 case CTINT: 374 x := new(Mpint) 375 x.Rune = typ == types.Idealrune 376 p.mpint(&x.Val, typ) 377 v.U = x 378 case CTFLT: 379 x := newMpflt() 380 p.float(x, typ) 381 v.U = x 382 case CTCPLX: 383 x := newMpcmplx() 384 p.float(&x.Real, typ) 385 p.float(&x.Imag, typ) 386 v.U = x 387 } 388 389 typ = idealType(typ) 390 return 391 } 392 393 func (p *importReader) mpint(x *big.Int, typ *types.Type) { 394 signed, maxBytes := intSize(typ) 395 396 maxSmall := 256 - maxBytes 397 if signed { 398 maxSmall = 256 - 2*maxBytes 399 } 400 if maxBytes == 1 { 401 maxSmall = 256 402 } 403 404 n, _ := p.ReadByte() 405 if uint(n) < maxSmall { 406 v := int64(n) 407 if signed { 408 v >>= 1 409 if n&1 != 0 { 410 v = ^v 411 } 412 } 413 x.SetInt64(v) 414 return 415 } 416 417 v := -n 418 if signed { 419 v = -(n &^ 1) >> 1 420 } 421 if v < 1 || uint(v) > maxBytes { 422 Fatalf("weird decoding: %v, %v => %v", n, signed, v) 423 } 424 b := make([]byte, v) 425 p.Read(b) 426 x.SetBytes(b) 427 if signed && n&1 != 0 { 428 x.Neg(x) 429 } 430 } 431 432 func (p *importReader) float(x *Mpflt, typ *types.Type) { 433 var mant big.Int 434 p.mpint(&mant, typ) 435 m := x.Val.SetInt(&mant) 436 if m.Sign() == 0 { 437 return 438 } 439 m.SetMantExp(m, int(p.int64())) 440 } 441 442 func (r *importReader) ident() *types.Sym { 443 name := r.string() 444 if name == "" { 445 return nil 446 } 447 pkg := r.currPkg 448 if types.IsExported(name) { 449 pkg = localpkg 450 } 451 return pkg.Lookup(name) 452 } 453 454 func (r *importReader) qualifiedIdent() *types.Sym { 455 name := r.string() 456 pkg := r.pkg() 457 return pkg.Lookup(name) 458 } 459 460 func (r *importReader) pos() src.XPos { 461 delta := r.int64() 462 if delta != deltaNewFile { 463 r.prevLine += delta 464 } else if l := r.int64(); l == -1 { 465 r.prevLine += deltaNewFile 466 } else { 467 r.prevBase = r.posBase() 468 r.prevLine = l 469 } 470 471 if (r.prevBase == nil || r.prevBase.AbsFilename() == "") && r.prevLine == 0 { 472 // TODO(mdempsky): Remove once we reliably write 473 // position information for all nodes. 474 return src.NoXPos 475 } 476 477 if r.prevBase == nil { 478 Fatalf("missing posbase") 479 } 480 pos := src.MakePos(r.prevBase, uint(r.prevLine), 0) 481 return Ctxt.PosTable.XPos(pos) 482 } 483 484 func (r *importReader) typ() *types.Type { 485 return r.p.typAt(r.uint64()) 486 } 487 488 func (p *iimporter) typAt(off uint64) *types.Type { 489 t, ok := p.typCache[off] 490 if !ok { 491 if off < predeclReserved { 492 Fatalf("predeclared type missing from cache: %d", off) 493 } 494 t = p.newReader(off-predeclReserved, nil).typ1() 495 p.typCache[off] = t 496 } 497 return t 498 } 499 500 func (r *importReader) typ1() *types.Type { 501 switch k := r.kind(); k { 502 default: 503 Fatalf("unexpected kind tag in %q: %v", r.p.ipkg.Path, k) 504 return nil 505 506 case definedType: 507 // We might be called from within doInline, in which 508 // case Sym.Def can point to declared parameters 509 // instead of the top-level types. Also, we don't 510 // support inlining functions with local defined 511 // types. Therefore, this must be a package-scope 512 // type. 513 n := asNode(r.qualifiedIdent().PkgDef()) 514 if n.Op == ONONAME { 515 expandDecl(n) 516 } 517 if n.Op != OTYPE { 518 Fatalf("expected OTYPE, got %v: %v, %v", n.Op, n.Sym, n) 519 } 520 return n.Type 521 case pointerType: 522 return types.NewPtr(r.typ()) 523 case sliceType: 524 return types.NewSlice(r.typ()) 525 case arrayType: 526 n := r.uint64() 527 return types.NewArray(r.typ(), int64(n)) 528 case chanType: 529 dir := types.ChanDir(r.uint64()) 530 return types.NewChan(r.typ(), dir) 531 case mapType: 532 return types.NewMap(r.typ(), r.typ()) 533 534 case signatureType: 535 r.setPkg() 536 return r.signature(nil) 537 538 case structType: 539 r.setPkg() 540 541 fs := make([]*types.Field, r.uint64()) 542 for i := range fs { 543 pos := r.pos() 544 sym := r.ident() 545 typ := r.typ() 546 emb := r.bool() 547 note := r.string() 548 549 f := types.NewField() 550 f.Pos = pos 551 f.Sym = sym 552 f.Type = typ 553 if emb { 554 f.Embedded = 1 555 } 556 f.Note = note 557 fs[i] = f 558 } 559 560 t := types.New(TSTRUCT) 561 t.SetPkg(r.currPkg) 562 t.SetFields(fs) 563 return t 564 565 case interfaceType: 566 r.setPkg() 567 568 embeddeds := make([]*types.Field, r.uint64()) 569 for i := range embeddeds { 570 pos := r.pos() 571 typ := r.typ() 572 573 f := types.NewField() 574 f.Pos = pos 575 f.Type = typ 576 embeddeds[i] = f 577 } 578 579 methods := make([]*types.Field, r.uint64()) 580 for i := range methods { 581 pos := r.pos() 582 sym := r.ident() 583 typ := r.signature(fakeRecvField()) 584 585 f := types.NewField() 586 f.Pos = pos 587 f.Sym = sym 588 f.Type = typ 589 methods[i] = f 590 } 591 592 t := types.New(TINTER) 593 t.SetPkg(r.currPkg) 594 t.SetInterface(append(embeddeds, methods...)) 595 596 // Ensure we expand the interface in the frontend (#25055). 597 checkwidth(t) 598 599 return t 600 } 601 } 602 603 func (r *importReader) kind() itag { 604 return itag(r.uint64()) 605 } 606 607 func (r *importReader) signature(recv *types.Field) *types.Type { 608 params := r.paramList() 609 results := r.paramList() 610 if n := len(params); n > 0 { 611 params[n-1].SetIsDDD(r.bool()) 612 } 613 t := functypefield(recv, params, results) 614 t.SetPkg(r.currPkg) 615 return t 616 } 617 618 func (r *importReader) paramList() []*types.Field { 619 fs := make([]*types.Field, r.uint64()) 620 for i := range fs { 621 fs[i] = r.param() 622 } 623 return fs 624 } 625 626 func (r *importReader) param() *types.Field { 627 f := types.NewField() 628 f.Pos = r.pos() 629 f.Sym = r.ident() 630 f.Type = r.typ() 631 return f 632 } 633 634 func (r *importReader) bool() bool { 635 return r.uint64() != 0 636 } 637 638 func (r *importReader) int64() int64 { 639 n, err := binary.ReadVarint(r) 640 if err != nil { 641 Fatalf("readVarint: %v", err) 642 } 643 return n 644 } 645 646 func (r *importReader) uint64() uint64 { 647 n, err := binary.ReadUvarint(r) 648 if err != nil { 649 Fatalf("readVarint: %v", err) 650 } 651 return n 652 } 653 654 func (r *importReader) byte() byte { 655 x, err := r.ReadByte() 656 if err != nil { 657 Fatalf("declReader.ReadByte: %v", err) 658 } 659 return x 660 } 661 662 // Compiler-specific extensions. 663 664 func (r *importReader) varExt(n *Node) { 665 r.linkname(n.Sym) 666 } 667 668 func (r *importReader) funcExt(n *Node) { 669 r.linkname(n.Sym) 670 671 // Escape analysis. 672 for _, fs := range types.RecvsParams { 673 for _, f := range fs(n.Type).FieldSlice() { 674 f.Note = r.string() 675 } 676 } 677 678 // Inline body. 679 if u := r.uint64(); u > 0 { 680 n.Func.Inl = &Inline{ 681 Cost: int32(u - 1), 682 } 683 n.Func.Endlineno = r.pos() 684 } 685 } 686 687 func (r *importReader) methExt(m *types.Field) { 688 if r.bool() { 689 m.SetNointerface(true) 690 } 691 r.funcExt(asNode(m.Type.Nname())) 692 } 693 694 func (r *importReader) linkname(s *types.Sym) { 695 s.Linkname = r.string() 696 } 697 698 func (r *importReader) doInline(n *Node) { 699 if len(n.Func.Inl.Body) != 0 { 700 Fatalf("%v already has inline body", n) 701 } 702 703 funchdr(n) 704 body := r.stmtList() 705 funcbody() 706 if body == nil { 707 // 708 // Make sure empty body is not interpreted as 709 // no inlineable body (see also parser.fnbody) 710 // (not doing so can cause significant performance 711 // degradation due to unnecessary calls to empty 712 // functions). 713 body = []*Node{} 714 } 715 n.Func.Inl.Body = body 716 717 importlist = append(importlist, n) 718 719 if Debug['E'] > 0 && Debug['m'] > 2 { 720 if Debug['m'] > 3 { 721 fmt.Printf("inl body for %v %#v: %+v\n", n, n.Type, asNodes(n.Func.Inl.Body)) 722 } else { 723 fmt.Printf("inl body for %v %#v: %v\n", n, n.Type, asNodes(n.Func.Inl.Body)) 724 } 725 } 726 } 727 728 // ---------------------------------------------------------------------------- 729 // Inlined function bodies 730 731 // Approach: Read nodes and use them to create/declare the same data structures 732 // as done originally by the (hidden) parser by closely following the parser's 733 // original code. In other words, "parsing" the import data (which happens to 734 // be encoded in binary rather textual form) is the best way at the moment to 735 // re-establish the syntax tree's invariants. At some future point we might be 736 // able to avoid this round-about way and create the rewritten nodes directly, 737 // possibly avoiding a lot of duplicate work (name resolution, type checking). 738 // 739 // Refined nodes (e.g., ODOTPTR as a refinement of OXDOT) are exported as their 740 // unrefined nodes (since this is what the importer uses). The respective case 741 // entries are unreachable in the importer. 742 743 func (r *importReader) stmtList() []*Node { 744 var list []*Node 745 for { 746 n := r.node() 747 if n == nil { 748 break 749 } 750 // OBLOCK nodes may be created when importing ODCL nodes - unpack them 751 if n.Op == OBLOCK { 752 list = append(list, n.List.Slice()...) 753 } else { 754 list = append(list, n) 755 } 756 757 } 758 return list 759 } 760 761 func (r *importReader) exprList() []*Node { 762 var list []*Node 763 for { 764 n := r.expr() 765 if n == nil { 766 break 767 } 768 list = append(list, n) 769 } 770 return list 771 } 772 773 func (r *importReader) expr() *Node { 774 n := r.node() 775 if n != nil && n.Op == OBLOCK { 776 Fatalf("unexpected block node: %v", n) 777 } 778 return n 779 } 780 781 // TODO(gri) split into expr and stmt 782 func (r *importReader) node() *Node { 783 switch op := r.op(); op { 784 // expressions 785 // case OPAREN: 786 // unreachable - unpacked by exporter 787 788 // case ODDDARG: 789 // unimplemented 790 791 case OLITERAL: 792 pos := r.pos() 793 typ, val := r.value() 794 795 n := npos(pos, nodlit(val)) 796 n.Type = typ 797 return n 798 799 case ONONAME: 800 return mkname(r.qualifiedIdent()) 801 802 case ONAME: 803 return mkname(r.ident()) 804 805 // case OPACK, ONONAME: 806 // unreachable - should have been resolved by typechecking 807 808 case OTYPE: 809 return typenod(r.typ()) 810 811 // case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC: 812 // unreachable - should have been resolved by typechecking 813 814 // case OCLOSURE: 815 // unimplemented 816 817 case OPTRLIT: 818 pos := r.pos() 819 n := npos(pos, r.expr()) 820 if !r.bool() /* !implicit, i.e. '&' operator */ { 821 if n.Op == OCOMPLIT { 822 // Special case for &T{...}: turn into (*T){...}. 823 n.Right = nodl(pos, ODEREF, n.Right, nil) 824 n.Right.SetImplicit(true) 825 } else { 826 n = nodl(pos, OADDR, n, nil) 827 } 828 } 829 return n 830 831 case OSTRUCTLIT: 832 // TODO(mdempsky): Export position information for OSTRUCTKEY nodes. 833 savedlineno := lineno 834 lineno = r.pos() 835 n := nodl(lineno, OCOMPLIT, nil, typenod(r.typ())) 836 n.List.Set(r.elemList()) // special handling of field names 837 lineno = savedlineno 838 return n 839 840 // case OARRAYLIT, OSLICELIT, OMAPLIT: 841 // unreachable - mapped to case OCOMPLIT below by exporter 842 843 case OCOMPLIT: 844 n := nodl(r.pos(), OCOMPLIT, nil, typenod(r.typ())) 845 n.List.Set(r.exprList()) 846 return n 847 848 case OKEY: 849 pos := r.pos() 850 left, right := r.exprsOrNil() 851 return nodl(pos, OKEY, left, right) 852 853 // case OSTRUCTKEY: 854 // unreachable - handled in case OSTRUCTLIT by elemList 855 856 // case OCALLPART: 857 // unimplemented 858 859 // case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH: 860 // unreachable - mapped to case OXDOT below by exporter 861 862 case OXDOT: 863 // see parser.new_dotname 864 return npos(r.pos(), nodSym(OXDOT, r.expr(), r.ident())) 865 866 // case ODOTTYPE, ODOTTYPE2: 867 // unreachable - mapped to case ODOTTYPE below by exporter 868 869 case ODOTTYPE: 870 n := nodl(r.pos(), ODOTTYPE, r.expr(), nil) 871 n.Type = r.typ() 872 return n 873 874 // case OINDEX, OINDEXMAP, OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR: 875 // unreachable - mapped to cases below by exporter 876 877 case OINDEX: 878 return nodl(r.pos(), op, r.expr(), r.expr()) 879 880 case OSLICE, OSLICE3: 881 n := nodl(r.pos(), op, r.expr(), nil) 882 low, high := r.exprsOrNil() 883 var max *Node 884 if n.Op.IsSlice3() { 885 max = r.expr() 886 } 887 n.SetSliceBounds(low, high, max) 888 return n 889 890 // case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, ORUNES2STR, OSTR2BYTES, OSTR2RUNES, ORUNESTR: 891 // unreachable - mapped to OCONV case below by exporter 892 893 case OCONV: 894 n := nodl(r.pos(), OCONV, r.expr(), nil) 895 n.Type = r.typ() 896 return n 897 898 case OCOPY, OCOMPLEX, OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN: 899 n := npos(r.pos(), builtinCall(op)) 900 n.List.Set(r.exprList()) 901 if op == OAPPEND { 902 n.SetIsDDD(r.bool()) 903 } 904 return n 905 906 // case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG: 907 // unreachable - mapped to OCALL case below by exporter 908 909 case OCALL: 910 n := nodl(r.pos(), OCALL, r.expr(), nil) 911 n.List.Set(r.exprList()) 912 n.SetIsDDD(r.bool()) 913 return n 914 915 case OMAKEMAP, OMAKECHAN, OMAKESLICE: 916 n := npos(r.pos(), builtinCall(OMAKE)) 917 n.List.Append(typenod(r.typ())) 918 n.List.Append(r.exprList()...) 919 return n 920 921 // unary expressions 922 case OPLUS, ONEG, OADDR, OBITNOT, ODEREF, ONOT, ORECV: 923 return nodl(r.pos(), op, r.expr(), nil) 924 925 // binary expressions 926 case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, OLT, 927 OLSH, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSEND, OSUB, OXOR: 928 return nodl(r.pos(), op, r.expr(), r.expr()) 929 930 case OADDSTR: 931 pos := r.pos() 932 list := r.exprList() 933 x := npos(pos, list[0]) 934 for _, y := range list[1:] { 935 x = nodl(pos, OADD, x, y) 936 } 937 return x 938 939 // -------------------------------------------------------------------- 940 // statements 941 case ODCL: 942 pos := r.pos() 943 lhs := npos(pos, dclname(r.ident())) 944 typ := typenod(r.typ()) 945 return npos(pos, liststmt(variter([]*Node{lhs}, typ, nil))) // TODO(gri) avoid list creation 946 947 // case ODCLFIELD: 948 // unimplemented 949 950 // case OAS, OASWB: 951 // unreachable - mapped to OAS case below by exporter 952 953 case OAS: 954 return nodl(r.pos(), OAS, r.expr(), r.expr()) 955 956 case OASOP: 957 n := nodl(r.pos(), OASOP, nil, nil) 958 n.SetSubOp(r.op()) 959 n.Left = r.expr() 960 if !r.bool() { 961 n.Right = nodintconst(1) 962 n.SetImplicit(true) 963 } else { 964 n.Right = r.expr() 965 } 966 return n 967 968 // case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV: 969 // unreachable - mapped to OAS2 case below by exporter 970 971 case OAS2: 972 n := nodl(r.pos(), OAS2, nil, nil) 973 n.List.Set(r.exprList()) 974 n.Rlist.Set(r.exprList()) 975 return n 976 977 case ORETURN: 978 n := nodl(r.pos(), ORETURN, nil, nil) 979 n.List.Set(r.exprList()) 980 return n 981 982 // case ORETJMP: 983 // unreachable - generated by compiler for trampolin routines (not exported) 984 985 case OGO, ODEFER: 986 return nodl(r.pos(), op, r.expr(), nil) 987 988 case OIF: 989 n := nodl(r.pos(), OIF, nil, nil) 990 n.Ninit.Set(r.stmtList()) 991 n.Left = r.expr() 992 n.Nbody.Set(r.stmtList()) 993 n.Rlist.Set(r.stmtList()) 994 return n 995 996 case OFOR: 997 n := nodl(r.pos(), OFOR, nil, nil) 998 n.Ninit.Set(r.stmtList()) 999 n.Left, n.Right = r.exprsOrNil() 1000 n.Nbody.Set(r.stmtList()) 1001 return n 1002 1003 case ORANGE: 1004 n := nodl(r.pos(), ORANGE, nil, nil) 1005 n.List.Set(r.stmtList()) 1006 n.Right = r.expr() 1007 n.Nbody.Set(r.stmtList()) 1008 return n 1009 1010 case OSELECT, OSWITCH: 1011 n := nodl(r.pos(), op, nil, nil) 1012 n.Ninit.Set(r.stmtList()) 1013 n.Left, _ = r.exprsOrNil() 1014 n.List.Set(r.stmtList()) 1015 return n 1016 1017 // case OCASE, OXCASE: 1018 // unreachable - mapped to OXCASE case below by exporter 1019 1020 case OXCASE: 1021 n := nodl(r.pos(), OXCASE, nil, nil) 1022 n.List.Set(r.exprList()) 1023 // TODO(gri) eventually we must declare variables for type switch 1024 // statements (type switch statements are not yet exported) 1025 n.Nbody.Set(r.stmtList()) 1026 return n 1027 1028 // case OFALL: 1029 // unreachable - mapped to OXFALL case below by exporter 1030 1031 case OFALL: 1032 n := nodl(r.pos(), OFALL, nil, nil) 1033 return n 1034 1035 case OBREAK, OCONTINUE: 1036 pos := r.pos() 1037 left, _ := r.exprsOrNil() 1038 if left != nil { 1039 left = newname(left.Sym) 1040 } 1041 return nodl(pos, op, left, nil) 1042 1043 // case OEMPTY: 1044 // unreachable - not emitted by exporter 1045 1046 case OGOTO, OLABEL: 1047 n := nodl(r.pos(), op, nil, nil) 1048 n.Sym = lookup(r.string()) 1049 return n 1050 1051 case OEND: 1052 return nil 1053 1054 default: 1055 Fatalf("cannot import %v (%d) node\n"+ 1056 "\t==> please file an issue and assign to gri@", op, int(op)) 1057 panic("unreachable") // satisfy compiler 1058 } 1059 } 1060 1061 func (r *importReader) op() Op { 1062 return Op(r.uint64()) 1063 } 1064 1065 func (r *importReader) elemList() []*Node { 1066 c := r.uint64() 1067 list := make([]*Node, c) 1068 for i := range list { 1069 s := r.ident() 1070 list[i] = nodSym(OSTRUCTKEY, r.expr(), s) 1071 } 1072 return list 1073 } 1074 1075 func (r *importReader) exprsOrNil() (a, b *Node) { 1076 ab := r.uint64() 1077 if ab&1 != 0 { 1078 a = r.expr() 1079 } 1080 if ab&2 != 0 { 1081 b = r.node() 1082 } 1083 return 1084 }