github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/src/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 338 // (comment from parser.go) 339 // inl.C's inlnode in on a dotmeth node expects to find the inlineable body as 340 // (dotmeth's type).Nname.Inl, and dotmeth's type has been pulled 341 // out by typecheck's lookdot as this $$.ttype. So by providing 342 // this back link here we avoid special casing there. 343 mtyp.SetNname(asTypesNode(m)) 344 } 345 t.Methods().Set(ms) 346 347 for _, m := range ms { 348 r.methExt(m) 349 } 350 351 case 'V': 352 typ := r.typ() 353 354 importvar(r.p.ipkg, pos, n.Sym, typ) 355 r.varExt(n) 356 357 default: 358 Fatalf("unexpected tag: %v", tag) 359 } 360 } 361 362 func (p *importReader) value() (typ *types.Type, v Val) { 363 typ = p.typ() 364 365 switch constTypeOf(typ) { 366 case CTNIL: 367 v.U = &NilVal{} 368 case CTBOOL: 369 v.U = p.bool() 370 case CTSTR: 371 v.U = p.string() 372 case CTINT: 373 x := new(Mpint) 374 x.Rune = typ == types.Idealrune 375 p.mpint(&x.Val, typ) 376 v.U = x 377 case CTFLT: 378 x := newMpflt() 379 p.float(x, typ) 380 v.U = x 381 case CTCPLX: 382 x := newMpcmplx() 383 p.float(&x.Real, typ) 384 p.float(&x.Imag, typ) 385 v.U = x 386 } 387 388 typ = idealType(typ) 389 return 390 } 391 392 func (p *importReader) mpint(x *big.Int, typ *types.Type) { 393 signed, maxBytes := intSize(typ) 394 395 maxSmall := 256 - maxBytes 396 if signed { 397 maxSmall = 256 - 2*maxBytes 398 } 399 if maxBytes == 1 { 400 maxSmall = 256 401 } 402 403 n, _ := p.ReadByte() 404 if uint(n) < maxSmall { 405 v := int64(n) 406 if signed { 407 v >>= 1 408 if n&1 != 0 { 409 v = ^v 410 } 411 } 412 x.SetInt64(v) 413 return 414 } 415 416 v := -n 417 if signed { 418 v = -(n &^ 1) >> 1 419 } 420 if v < 1 || uint(v) > maxBytes { 421 Fatalf("weird decoding: %v, %v => %v", n, signed, v) 422 } 423 b := make([]byte, v) 424 p.Read(b) 425 x.SetBytes(b) 426 if signed && n&1 != 0 { 427 x.Neg(x) 428 } 429 } 430 431 func (p *importReader) float(x *Mpflt, typ *types.Type) { 432 var mant big.Int 433 p.mpint(&mant, typ) 434 m := x.Val.SetInt(&mant) 435 if m.Sign() == 0 { 436 return 437 } 438 m.SetMantExp(m, int(p.int64())) 439 } 440 441 func (r *importReader) ident() *types.Sym { 442 name := r.string() 443 if name == "" { 444 return nil 445 } 446 pkg := r.currPkg 447 if types.IsExported(name) { 448 pkg = localpkg 449 } 450 return pkg.Lookup(name) 451 } 452 453 func (r *importReader) qualifiedIdent() *types.Sym { 454 name := r.string() 455 pkg := r.pkg() 456 return pkg.Lookup(name) 457 } 458 459 func (r *importReader) pos() src.XPos { 460 delta := r.int64() 461 if delta != deltaNewFile { 462 r.prevLine += delta 463 } else if l := r.int64(); l == -1 { 464 r.prevLine += deltaNewFile 465 } else { 466 r.prevBase = r.posBase() 467 r.prevLine = l 468 } 469 470 if (r.prevBase == nil || r.prevBase.AbsFilename() == "") && r.prevLine == 0 { 471 // TODO(mdempsky): Remove once we reliably write 472 // position information for all nodes. 473 return src.NoXPos 474 } 475 476 if r.prevBase == nil { 477 Fatalf("missing posbase") 478 } 479 pos := src.MakePos(r.prevBase, uint(r.prevLine), 0) 480 return Ctxt.PosTable.XPos(pos) 481 } 482 483 func (r *importReader) typ() *types.Type { 484 return r.p.typAt(r.uint64()) 485 } 486 487 func (p *iimporter) typAt(off uint64) *types.Type { 488 t, ok := p.typCache[off] 489 if !ok { 490 if off < predeclReserved { 491 Fatalf("predeclared type missing from cache: %d", off) 492 } 493 t = p.newReader(off-predeclReserved, nil).typ1() 494 p.typCache[off] = t 495 } 496 return t 497 } 498 499 func (r *importReader) typ1() *types.Type { 500 switch k := r.kind(); k { 501 default: 502 Fatalf("unexpected kind tag in %q: %v", r.p.ipkg.Path, k) 503 return nil 504 505 case definedType: 506 // We might be called from within doInline, in which 507 // case Sym.Def can point to declared parameters 508 // instead of the top-level types. Also, we don't 509 // support inlining functions with local defined 510 // types. Therefore, this must be a package-scope 511 // type. 512 n := asNode(r.qualifiedIdent().PkgDef()) 513 if n.Op == ONONAME { 514 expandDecl(n) 515 } 516 if n.Op != OTYPE { 517 Fatalf("expected OTYPE, got %v: %v, %v", n.Op, n.Sym, n) 518 } 519 return n.Type 520 case pointerType: 521 return types.NewPtr(r.typ()) 522 case sliceType: 523 return types.NewSlice(r.typ()) 524 case arrayType: 525 n := r.uint64() 526 return types.NewArray(r.typ(), int64(n)) 527 case chanType: 528 dir := types.ChanDir(r.uint64()) 529 return types.NewChan(r.typ(), dir) 530 case mapType: 531 return types.NewMap(r.typ(), r.typ()) 532 533 case signatureType: 534 r.setPkg() 535 return r.signature(nil) 536 537 case structType: 538 r.setPkg() 539 540 fs := make([]*types.Field, r.uint64()) 541 for i := range fs { 542 pos := r.pos() 543 sym := r.ident() 544 typ := r.typ() 545 emb := r.bool() 546 note := r.string() 547 548 f := types.NewField() 549 f.Pos = pos 550 f.Sym = sym 551 f.Type = typ 552 if emb { 553 f.Embedded = 1 554 } 555 f.Note = note 556 fs[i] = f 557 } 558 559 t := types.New(TSTRUCT) 560 t.SetPkg(r.currPkg) 561 t.SetFields(fs) 562 return t 563 564 case interfaceType: 565 r.setPkg() 566 567 embeddeds := make([]*types.Field, r.uint64()) 568 for i := range embeddeds { 569 pos := r.pos() 570 typ := r.typ() 571 572 f := types.NewField() 573 f.Pos = pos 574 f.Type = typ 575 embeddeds[i] = f 576 } 577 578 methods := make([]*types.Field, r.uint64()) 579 for i := range methods { 580 pos := r.pos() 581 sym := r.ident() 582 typ := r.signature(fakeRecvField()) 583 584 f := types.NewField() 585 f.Pos = pos 586 f.Sym = sym 587 f.Type = typ 588 methods[i] = f 589 } 590 591 t := types.New(TINTER) 592 t.SetPkg(r.currPkg) 593 t.SetInterface(append(embeddeds, methods...)) 594 595 // Ensure we expand the interface in the frontend (#25055). 596 checkwidth(t) 597 598 return t 599 } 600 } 601 602 func (r *importReader) kind() itag { 603 return itag(r.uint64()) 604 } 605 606 func (r *importReader) signature(recv *types.Field) *types.Type { 607 params := r.paramList() 608 results := r.paramList() 609 if n := len(params); n > 0 { 610 params[n-1].SetIsddd(r.bool()) 611 } 612 t := functypefield(recv, params, results) 613 t.SetPkg(r.currPkg) 614 return t 615 } 616 617 func (r *importReader) paramList() []*types.Field { 618 fs := make([]*types.Field, r.uint64()) 619 for i := range fs { 620 fs[i] = r.param() 621 } 622 return fs 623 } 624 625 func (r *importReader) param() *types.Field { 626 f := types.NewField() 627 f.Pos = r.pos() 628 f.Sym = r.ident() 629 f.Type = r.typ() 630 return f 631 } 632 633 func (r *importReader) bool() bool { 634 return r.uint64() != 0 635 } 636 637 func (r *importReader) int64() int64 { 638 n, err := binary.ReadVarint(r) 639 if err != nil { 640 Fatalf("readVarint: %v", err) 641 } 642 return n 643 } 644 645 func (r *importReader) uint64() uint64 { 646 n, err := binary.ReadUvarint(r) 647 if err != nil { 648 Fatalf("readVarint: %v", err) 649 } 650 return n 651 } 652 653 func (r *importReader) byte() byte { 654 x, err := r.ReadByte() 655 if err != nil { 656 Fatalf("declReader.ReadByte: %v", err) 657 } 658 return x 659 } 660 661 // Compiler-specific extensions. 662 663 func (r *importReader) varExt(n *Node) { 664 r.linkname(n.Sym) 665 } 666 667 func (r *importReader) funcExt(n *Node) { 668 r.linkname(n.Sym) 669 670 // Escape analysis. 671 for _, fs := range types.RecvsParams { 672 for _, f := range fs(n.Type).FieldSlice() { 673 f.Note = r.string() 674 } 675 } 676 677 // Inline body. 678 if u := r.uint64(); u > 0 { 679 n.Func.Inl = &Inline{ 680 Cost: int32(u - 1), 681 } 682 n.Func.Endlineno = r.pos() 683 } 684 } 685 686 func (r *importReader) methExt(m *types.Field) { 687 if r.bool() { 688 m.SetNointerface(true) 689 } 690 r.funcExt(asNode(m.Type.Nname())) 691 } 692 693 func (r *importReader) linkname(s *types.Sym) { 694 s.Linkname = r.string() 695 } 696 697 func (r *importReader) doInline(n *Node) { 698 if len(n.Func.Inl.Body) != 0 { 699 Fatalf("%v already has inline body", n) 700 } 701 702 funchdr(n) 703 body := r.stmtList() 704 funcbody() 705 if body == nil { 706 // 707 // Make sure empty body is not interpreted as 708 // no inlineable body (see also parser.fnbody) 709 // (not doing so can cause significant performance 710 // degradation due to unnecessary calls to empty 711 // functions). 712 body = []*Node{} 713 } 714 n.Func.Inl.Body = body 715 716 importlist = append(importlist, n) 717 718 if Debug['E'] > 0 && Debug['m'] > 2 { 719 if Debug['m'] > 3 { 720 fmt.Printf("inl body for %v %#v: %+v\n", n, n.Type, asNodes(n.Func.Inl.Body)) 721 } else { 722 fmt.Printf("inl body for %v %#v: %v\n", n, n.Type, asNodes(n.Func.Inl.Body)) 723 } 724 } 725 } 726 727 // ---------------------------------------------------------------------------- 728 // Inlined function bodies 729 730 // Approach: Read nodes and use them to create/declare the same data structures 731 // as done originally by the (hidden) parser by closely following the parser's 732 // original code. In other words, "parsing" the import data (which happens to 733 // be encoded in binary rather textual form) is the best way at the moment to 734 // re-establish the syntax tree's invariants. At some future point we might be 735 // able to avoid this round-about way and create the rewritten nodes directly, 736 // possibly avoiding a lot of duplicate work (name resolution, type checking). 737 // 738 // Refined nodes (e.g., ODOTPTR as a refinement of OXDOT) are exported as their 739 // unrefined nodes (since this is what the importer uses). The respective case 740 // entries are unreachable in the importer. 741 742 func (r *importReader) stmtList() []*Node { 743 var list []*Node 744 for { 745 n := r.node() 746 if n == nil { 747 break 748 } 749 // OBLOCK nodes may be created when importing ODCL nodes - unpack them 750 if n.Op == OBLOCK { 751 list = append(list, n.List.Slice()...) 752 } else { 753 list = append(list, n) 754 } 755 756 } 757 return list 758 } 759 760 func (r *importReader) exprList() []*Node { 761 var list []*Node 762 for { 763 n := r.expr() 764 if n == nil { 765 break 766 } 767 list = append(list, n) 768 } 769 return list 770 } 771 772 func (r *importReader) expr() *Node { 773 n := r.node() 774 if n != nil && n.Op == OBLOCK { 775 Fatalf("unexpected block node: %v", n) 776 } 777 return n 778 } 779 780 // TODO(gri) split into expr and stmt 781 func (r *importReader) node() *Node { 782 switch op := r.op(); op { 783 // expressions 784 // case OPAREN: 785 // unreachable - unpacked by exporter 786 787 // case ODDDARG: 788 // unimplemented 789 790 case OLITERAL: 791 pos := r.pos() 792 typ, val := r.value() 793 794 n := npos(pos, nodlit(val)) 795 n.Type = typ 796 return n 797 798 case ONONAME: 799 return mkname(r.qualifiedIdent()) 800 801 case ONAME: 802 return mkname(r.ident()) 803 804 // case OPACK, ONONAME: 805 // unreachable - should have been resolved by typechecking 806 807 case OTYPE: 808 return typenod(r.typ()) 809 810 // case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC: 811 // unreachable - should have been resolved by typechecking 812 813 // case OCLOSURE: 814 // unimplemented 815 816 case OPTRLIT: 817 pos := r.pos() 818 n := npos(pos, r.expr()) 819 if !r.bool() /* !implicit, i.e. '&' operator */ { 820 if n.Op == OCOMPLIT { 821 // Special case for &T{...}: turn into (*T){...}. 822 n.Right = nodl(pos, OIND, n.Right, nil) 823 n.Right.SetImplicit(true) 824 } else { 825 n = nodl(pos, OADDR, n, nil) 826 } 827 } 828 return n 829 830 case OSTRUCTLIT: 831 // TODO(mdempsky): Export position information for OSTRUCTKEY nodes. 832 savedlineno := lineno 833 lineno = r.pos() 834 n := nodl(lineno, OCOMPLIT, nil, typenod(r.typ())) 835 n.List.Set(r.elemList()) // special handling of field names 836 lineno = savedlineno 837 return n 838 839 // case OARRAYLIT, OSLICELIT, OMAPLIT: 840 // unreachable - mapped to case OCOMPLIT below by exporter 841 842 case OCOMPLIT: 843 n := nodl(r.pos(), OCOMPLIT, nil, typenod(r.typ())) 844 n.List.Set(r.exprList()) 845 return n 846 847 case OKEY: 848 pos := r.pos() 849 left, right := r.exprsOrNil() 850 return nodl(pos, OKEY, left, right) 851 852 // case OSTRUCTKEY: 853 // unreachable - handled in case OSTRUCTLIT by elemList 854 855 // case OCALLPART: 856 // unimplemented 857 858 // case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH: 859 // unreachable - mapped to case OXDOT below by exporter 860 861 case OXDOT: 862 // see parser.new_dotname 863 return npos(r.pos(), nodSym(OXDOT, r.expr(), r.ident())) 864 865 // case ODOTTYPE, ODOTTYPE2: 866 // unreachable - mapped to case ODOTTYPE below by exporter 867 868 case ODOTTYPE: 869 n := nodl(r.pos(), ODOTTYPE, r.expr(), nil) 870 n.Type = r.typ() 871 return n 872 873 // case OINDEX, OINDEXMAP, OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR: 874 // unreachable - mapped to cases below by exporter 875 876 case OINDEX: 877 return nodl(r.pos(), op, r.expr(), r.expr()) 878 879 case OSLICE, OSLICE3: 880 n := nodl(r.pos(), op, r.expr(), nil) 881 low, high := r.exprsOrNil() 882 var max *Node 883 if n.Op.IsSlice3() { 884 max = r.expr() 885 } 886 n.SetSliceBounds(low, high, max) 887 return n 888 889 // case OCONV, OCONVIFACE, OCONVNOP, OARRAYBYTESTR, OARRAYRUNESTR, OSTRARRAYBYTE, OSTRARRAYRUNE, ORUNESTR: 890 // unreachable - mapped to OCONV case below by exporter 891 892 case OCONV: 893 n := nodl(r.pos(), OCONV, r.expr(), nil) 894 n.Type = r.typ() 895 return n 896 897 case OCOPY, OCOMPLEX, OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN: 898 n := npos(r.pos(), builtinCall(op)) 899 n.List.Set(r.exprList()) 900 if op == OAPPEND { 901 n.SetIsddd(r.bool()) 902 } 903 return n 904 905 // case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG: 906 // unreachable - mapped to OCALL case below by exporter 907 908 case OCALL: 909 n := nodl(r.pos(), OCALL, r.expr(), nil) 910 n.List.Set(r.exprList()) 911 n.SetIsddd(r.bool()) 912 return n 913 914 case OMAKEMAP, OMAKECHAN, OMAKESLICE: 915 n := npos(r.pos(), builtinCall(OMAKE)) 916 n.List.Append(typenod(r.typ())) 917 n.List.Append(r.exprList()...) 918 return n 919 920 // unary expressions 921 case OPLUS, OMINUS, OADDR, OCOM, OIND, ONOT, ORECV: 922 return nodl(r.pos(), op, r.expr(), nil) 923 924 // binary expressions 925 case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, OLT, 926 OLSH, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSEND, OSUB, OXOR: 927 return nodl(r.pos(), op, r.expr(), r.expr()) 928 929 case OADDSTR: 930 pos := r.pos() 931 list := r.exprList() 932 x := npos(pos, list[0]) 933 for _, y := range list[1:] { 934 x = nodl(pos, OADD, x, y) 935 } 936 return x 937 938 // -------------------------------------------------------------------- 939 // statements 940 case ODCL: 941 pos := r.pos() 942 lhs := npos(pos, dclname(r.ident())) 943 typ := typenod(r.typ()) 944 return npos(pos, liststmt(variter([]*Node{lhs}, typ, nil))) // TODO(gri) avoid list creation 945 946 // case ODCLFIELD: 947 // unimplemented 948 949 // case OAS, OASWB: 950 // unreachable - mapped to OAS case below by exporter 951 952 case OAS: 953 return nodl(r.pos(), OAS, r.expr(), r.expr()) 954 955 case OASOP: 956 n := nodl(r.pos(), OASOP, nil, nil) 957 n.SetSubOp(r.op()) 958 n.Left = r.expr() 959 if !r.bool() { 960 n.Right = nodintconst(1) 961 n.SetImplicit(true) 962 } else { 963 n.Right = r.expr() 964 } 965 return n 966 967 // case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV: 968 // unreachable - mapped to OAS2 case below by exporter 969 970 case OAS2: 971 n := nodl(r.pos(), OAS2, nil, nil) 972 n.List.Set(r.exprList()) 973 n.Rlist.Set(r.exprList()) 974 return n 975 976 case ORETURN: 977 n := nodl(r.pos(), ORETURN, nil, nil) 978 n.List.Set(r.exprList()) 979 return n 980 981 // case ORETJMP: 982 // unreachable - generated by compiler for trampolin routines (not exported) 983 984 case OPROC, ODEFER: 985 return nodl(r.pos(), op, r.expr(), nil) 986 987 case OIF: 988 n := nodl(r.pos(), OIF, nil, nil) 989 n.Ninit.Set(r.stmtList()) 990 n.Left = r.expr() 991 n.Nbody.Set(r.stmtList()) 992 n.Rlist.Set(r.stmtList()) 993 return n 994 995 case OFOR: 996 n := nodl(r.pos(), OFOR, nil, nil) 997 n.Ninit.Set(r.stmtList()) 998 n.Left, n.Right = r.exprsOrNil() 999 n.Nbody.Set(r.stmtList()) 1000 return n 1001 1002 case ORANGE: 1003 n := nodl(r.pos(), ORANGE, nil, nil) 1004 n.List.Set(r.stmtList()) 1005 n.Right = r.expr() 1006 n.Nbody.Set(r.stmtList()) 1007 return n 1008 1009 case OSELECT, OSWITCH: 1010 n := nodl(r.pos(), op, nil, nil) 1011 n.Ninit.Set(r.stmtList()) 1012 n.Left, _ = r.exprsOrNil() 1013 n.List.Set(r.stmtList()) 1014 return n 1015 1016 // case OCASE, OXCASE: 1017 // unreachable - mapped to OXCASE case below by exporter 1018 1019 case OXCASE: 1020 n := nodl(r.pos(), OXCASE, nil, nil) 1021 n.List.Set(r.exprList()) 1022 // TODO(gri) eventually we must declare variables for type switch 1023 // statements (type switch statements are not yet exported) 1024 n.Nbody.Set(r.stmtList()) 1025 return n 1026 1027 // case OFALL: 1028 // unreachable - mapped to OXFALL case below by exporter 1029 1030 case OFALL: 1031 n := nodl(r.pos(), OFALL, nil, nil) 1032 return n 1033 1034 case OBREAK, OCONTINUE: 1035 pos := r.pos() 1036 left, _ := r.exprsOrNil() 1037 if left != nil { 1038 left = newname(left.Sym) 1039 } 1040 return nodl(pos, op, left, nil) 1041 1042 // case OEMPTY: 1043 // unreachable - not emitted by exporter 1044 1045 case OGOTO, OLABEL: 1046 return nodl(r.pos(), op, newname(r.expr().Sym), nil) 1047 1048 case OEND: 1049 return nil 1050 1051 default: 1052 Fatalf("cannot import %v (%d) node\n"+ 1053 "==> please file an issue and assign to gri@\n", op, int(op)) 1054 panic("unreachable") // satisfy compiler 1055 } 1056 } 1057 1058 func (r *importReader) op() Op { 1059 return Op(r.uint64()) 1060 } 1061 1062 func (r *importReader) elemList() []*Node { 1063 c := r.uint64() 1064 list := make([]*Node, c) 1065 for i := range list { 1066 s := r.ident() 1067 list[i] = nodSym(OSTRUCTKEY, r.expr(), s) 1068 } 1069 return list 1070 } 1071 1072 func (r *importReader) exprsOrNil() (a, b *Node) { 1073 ab := r.uint64() 1074 if ab&1 != 0 { 1075 a = r.expr() 1076 } 1077 if ab&2 != 0 { 1078 b = r.node() 1079 } 1080 return 1081 }