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