github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/gc/reflect.c (about) 1 // Copyright 2009 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 #include <u.h> 6 #include <libc.h> 7 #include "go.h" 8 #include "../../pkg/runtime/mgc0.h" 9 10 /* 11 * runtime interface and reflection data structures 12 */ 13 14 static NodeList* signatlist; 15 static Sym* dtypesym(Type*); 16 static Sym* weaktypesym(Type*); 17 static Sym* dalgsym(Type*); 18 static Sym* dgcsym(Type*); 19 20 static int 21 sigcmp(Sig *a, Sig *b) 22 { 23 int i; 24 25 i = strcmp(a->name, b->name); 26 if(i != 0) 27 return i; 28 if(a->pkg == b->pkg) 29 return 0; 30 if(a->pkg == nil) 31 return -1; 32 if(b->pkg == nil) 33 return +1; 34 return strcmp(a->pkg->path->s, b->pkg->path->s); 35 } 36 37 static Sig* 38 lsort(Sig *l, int(*f)(Sig*, Sig*)) 39 { 40 Sig *l1, *l2, *le; 41 42 if(l == 0 || l->link == 0) 43 return l; 44 45 l1 = l; 46 l2 = l; 47 for(;;) { 48 l2 = l2->link; 49 if(l2 == 0) 50 break; 51 l2 = l2->link; 52 if(l2 == 0) 53 break; 54 l1 = l1->link; 55 } 56 57 l2 = l1->link; 58 l1->link = 0; 59 l1 = lsort(l, f); 60 l2 = lsort(l2, f); 61 62 /* set up lead element */ 63 if((*f)(l1, l2) < 0) { 64 l = l1; 65 l1 = l1->link; 66 } else { 67 l = l2; 68 l2 = l2->link; 69 } 70 le = l; 71 72 for(;;) { 73 if(l1 == 0) { 74 while(l2) { 75 le->link = l2; 76 le = l2; 77 l2 = l2->link; 78 } 79 le->link = 0; 80 break; 81 } 82 if(l2 == 0) { 83 while(l1) { 84 le->link = l1; 85 le = l1; 86 l1 = l1->link; 87 } 88 break; 89 } 90 if((*f)(l1, l2) < 0) { 91 le->link = l1; 92 le = l1; 93 l1 = l1->link; 94 } else { 95 le->link = l2; 96 le = l2; 97 l2 = l2->link; 98 } 99 } 100 le->link = 0; 101 return l; 102 } 103 104 /* 105 * f is method type, with receiver. 106 * return function type, receiver as first argument (or not). 107 */ 108 Type* 109 methodfunc(Type *f, Type *receiver) 110 { 111 NodeList *in, *out; 112 Node *d; 113 Type *t; 114 115 in = nil; 116 if(receiver) { 117 d = nod(ODCLFIELD, N, N); 118 d->type = receiver; 119 in = list(in, d); 120 } 121 for(t=getinargx(f)->type; t; t=t->down) { 122 d = nod(ODCLFIELD, N, N); 123 d->type = t->type; 124 d->isddd = t->isddd; 125 in = list(in, d); 126 } 127 128 out = nil; 129 for(t=getoutargx(f)->type; t; t=t->down) { 130 d = nod(ODCLFIELD, N, N); 131 d->type = t->type; 132 out = list(out, d); 133 } 134 135 t = functype(N, in, out); 136 if(f->nname) { 137 // Link to name of original method function. 138 t->nname = f->nname; 139 } 140 return t; 141 } 142 143 /* 144 * return methods of non-interface type t, sorted by name. 145 * generates stub functions as needed. 146 */ 147 static Sig* 148 methods(Type *t) 149 { 150 Type *f, *mt, *it, *this; 151 Sig *a, *b; 152 Sym *method; 153 154 // method type 155 mt = methtype(t, 0); 156 if(mt == T) 157 return nil; 158 expandmeth(mt); 159 160 // type stored in interface word 161 it = t; 162 if(it->width > widthptr) 163 it = ptrto(t); 164 165 // make list of methods for t, 166 // generating code if necessary. 167 a = nil; 168 for(f=mt->xmethod; f; f=f->down) { 169 if(f->etype != TFIELD) 170 fatal("methods: not field %T", f); 171 if (f->type->etype != TFUNC || f->type->thistuple == 0) 172 fatal("non-method on %T method %S %T\n", mt, f->sym, f); 173 if (!getthisx(f->type)->type) 174 fatal("receiver with no type on %T method %S %T\n", mt, f->sym, f); 175 if(f->nointerface) 176 continue; 177 178 method = f->sym; 179 if(method == nil) 180 continue; 181 182 // get receiver type for this particular method. 183 // if pointer receiver but non-pointer t and 184 // this is not an embedded pointer inside a struct, 185 // method does not apply. 186 this = getthisx(f->type)->type->type; 187 if(isptr[this->etype] && this->type == t) 188 continue; 189 if(isptr[this->etype] && !isptr[t->etype] 190 && f->embedded != 2 && !isifacemethod(f->type)) 191 continue; 192 193 b = mal(sizeof(*b)); 194 b->link = a; 195 a = b; 196 197 a->name = method->name; 198 if(!exportname(method->name)) { 199 if(method->pkg == nil) 200 fatal("methods: missing package"); 201 a->pkg = method->pkg; 202 } 203 a->isym = methodsym(method, it, 1); 204 a->tsym = methodsym(method, t, 0); 205 a->type = methodfunc(f->type, t); 206 a->mtype = methodfunc(f->type, nil); 207 208 if(!(a->isym->flags & SymSiggen)) { 209 a->isym->flags |= SymSiggen; 210 if(!eqtype(this, it) || this->width < types[tptr]->width) { 211 // Is okay to call genwrapper here always, 212 // but we can generate more efficient code 213 // using genembedtramp if all that is necessary 214 // is a pointer adjustment and a JMP. 215 compiling_wrappers = 1; 216 if(isptr[it->etype] && isptr[this->etype] 217 && f->embedded && !isifacemethod(f->type)) 218 genembedtramp(it, f, a->isym, 1); 219 else 220 genwrapper(it, f, a->isym, 1); 221 compiling_wrappers = 0; 222 } 223 } 224 225 if(!(a->tsym->flags & SymSiggen)) { 226 a->tsym->flags |= SymSiggen; 227 if(!eqtype(this, t)) { 228 compiling_wrappers = 1; 229 if(isptr[t->etype] && isptr[this->etype] 230 && f->embedded && !isifacemethod(f->type)) 231 genembedtramp(t, f, a->tsym, 0); 232 else 233 genwrapper(t, f, a->tsym, 0); 234 compiling_wrappers = 0; 235 } 236 } 237 } 238 239 return lsort(a, sigcmp); 240 } 241 242 /* 243 * return methods of interface type t, sorted by name. 244 */ 245 static Sig* 246 imethods(Type *t) 247 { 248 Sig *a, *all, *last; 249 Type *f; 250 Sym *method, *isym; 251 252 all = nil; 253 last = nil; 254 for(f=t->type; f; f=f->down) { 255 if(f->etype != TFIELD) 256 fatal("imethods: not field"); 257 if(f->type->etype != TFUNC || f->sym == nil) 258 continue; 259 method = f->sym; 260 a = mal(sizeof(*a)); 261 a->name = method->name; 262 if(!exportname(method->name)) { 263 if(method->pkg == nil) 264 fatal("imethods: missing package"); 265 a->pkg = method->pkg; 266 } 267 a->mtype = f->type; 268 a->offset = 0; 269 a->type = methodfunc(f->type, nil); 270 271 if(last && sigcmp(last, a) >= 0) 272 fatal("sigcmp vs sortinter %s %s", last->name, a->name); 273 if(last == nil) 274 all = a; 275 else 276 last->link = a; 277 last = a; 278 279 // Compiler can only refer to wrappers for 280 // named interface types. 281 if(t->sym == S) 282 continue; 283 284 // NOTE(rsc): Perhaps an oversight that 285 // IfaceType.Method is not in the reflect data. 286 // Generate the method body, so that compiled 287 // code can refer to it. 288 isym = methodsym(method, t, 0); 289 if(!(isym->flags & SymSiggen)) { 290 isym->flags |= SymSiggen; 291 genwrapper(t, f, isym, 0); 292 } 293 } 294 return all; 295 } 296 297 static void 298 dimportpath(Pkg *p) 299 { 300 static Pkg *gopkg; 301 char *nam; 302 Node *n; 303 304 if(p->pathsym != S) 305 return; 306 307 if(gopkg == nil) { 308 gopkg = mkpkg(strlit("go")); 309 gopkg->name = "go"; 310 } 311 nam = smprint("importpath.%s.", p->prefix); 312 313 n = nod(ONAME, N, N); 314 n->sym = pkglookup(nam, gopkg); 315 free(nam); 316 n->class = PEXTERN; 317 n->xoffset = 0; 318 p->pathsym = n->sym; 319 320 gdatastring(n, p->path); 321 ggloblsym(n->sym, types[TSTRING]->width, 1, 1); 322 } 323 324 static int 325 dgopkgpath(Sym *s, int ot, Pkg *pkg) 326 { 327 if(pkg == nil) 328 return dgostringptr(s, ot, nil); 329 330 // Emit reference to go.importpath.""., which 6l will 331 // rewrite using the correct import path. Every package 332 // that imports this one directly defines the symbol. 333 if(pkg == localpkg) { 334 static Sym *ns; 335 336 if(ns == nil) 337 ns = pkglookup("importpath.\"\".", mkpkg(strlit("go"))); 338 return dsymptr(s, ot, ns, 0); 339 } 340 341 dimportpath(pkg); 342 return dsymptr(s, ot, pkg->pathsym, 0); 343 } 344 345 /* 346 * uncommonType 347 * ../../pkg/runtime/type.go:/uncommonType 348 */ 349 static int 350 dextratype(Sym *sym, int off, Type *t, int ptroff) 351 { 352 int ot, n; 353 Sym *s; 354 Sig *a, *m; 355 356 m = methods(t); 357 if(t->sym == nil && m == nil) 358 return off; 359 360 // fill in *extraType pointer in header 361 dsymptr(sym, ptroff, sym, off); 362 363 n = 0; 364 for(a=m; a; a=a->link) { 365 dtypesym(a->type); 366 n++; 367 } 368 369 ot = off; 370 s = sym; 371 if(t->sym) { 372 ot = dgostringptr(s, ot, t->sym->name); 373 if(t != types[t->etype] && t != errortype) 374 ot = dgopkgpath(s, ot, t->sym->pkg); 375 else 376 ot = dgostringptr(s, ot, nil); 377 } else { 378 ot = dgostringptr(s, ot, nil); 379 ot = dgostringptr(s, ot, nil); 380 } 381 382 // slice header 383 ot = dsymptr(s, ot, s, ot + widthptr + 2*widthint); 384 ot = duintxx(s, ot, n, widthint); 385 ot = duintxx(s, ot, n, widthint); 386 387 // methods 388 for(a=m; a; a=a->link) { 389 // method 390 // ../../pkg/runtime/type.go:/method 391 ot = dgostringptr(s, ot, a->name); 392 ot = dgopkgpath(s, ot, a->pkg); 393 ot = dsymptr(s, ot, dtypesym(a->mtype), 0); 394 ot = dsymptr(s, ot, dtypesym(a->type), 0); 395 if(a->isym) 396 ot = dsymptr(s, ot, a->isym, 0); 397 else 398 ot = duintptr(s, ot, 0); 399 if(a->tsym) 400 ot = dsymptr(s, ot, a->tsym, 0); 401 else 402 ot = duintptr(s, ot, 0); 403 } 404 405 return ot; 406 } 407 408 enum { 409 KindBool = 1, 410 KindInt, 411 KindInt8, 412 KindInt16, 413 KindInt32, 414 KindInt64, 415 KindUint, 416 KindUint8, 417 KindUint16, 418 KindUint32, 419 KindUint64, 420 KindUintptr, 421 KindFloat32, 422 KindFloat64, 423 KindComplex64, 424 KindComplex128, 425 KindArray, 426 KindChan, 427 KindFunc, 428 KindInterface, 429 KindMap, 430 KindPtr, 431 KindSlice, 432 KindString, 433 KindStruct, 434 KindUnsafePointer, 435 436 KindNoPointers = 1<<7, 437 }; 438 439 static int 440 kinds[] = 441 { 442 [TINT] = KindInt, 443 [TUINT] = KindUint, 444 [TINT8] = KindInt8, 445 [TUINT8] = KindUint8, 446 [TINT16] = KindInt16, 447 [TUINT16] = KindUint16, 448 [TINT32] = KindInt32, 449 [TUINT32] = KindUint32, 450 [TINT64] = KindInt64, 451 [TUINT64] = KindUint64, 452 [TUINTPTR] = KindUintptr, 453 [TFLOAT32] = KindFloat32, 454 [TFLOAT64] = KindFloat64, 455 [TBOOL] = KindBool, 456 [TSTRING] = KindString, 457 [TPTR32] = KindPtr, 458 [TPTR64] = KindPtr, 459 [TSTRUCT] = KindStruct, 460 [TINTER] = KindInterface, 461 [TCHAN] = KindChan, 462 [TMAP] = KindMap, 463 [TARRAY] = KindArray, 464 [TFUNC] = KindFunc, 465 [TCOMPLEX64] = KindComplex64, 466 [TCOMPLEX128] = KindComplex128, 467 [TUNSAFEPTR] = KindUnsafePointer, 468 }; 469 470 int 471 haspointers(Type *t) 472 { 473 Type *t1; 474 475 switch(t->etype) { 476 case TINT: 477 case TUINT: 478 case TINT8: 479 case TUINT8: 480 case TINT16: 481 case TUINT16: 482 case TINT32: 483 case TUINT32: 484 case TINT64: 485 case TUINT64: 486 case TUINTPTR: 487 case TFLOAT32: 488 case TFLOAT64: 489 case TBOOL: 490 return 0; 491 case TARRAY: 492 if(t->bound < 0) // slice 493 return 1; 494 return haspointers(t->type); 495 case TSTRUCT: 496 for(t1=t->type; t1!=T; t1=t1->down) 497 if(haspointers(t1->type)) 498 return 1; 499 return 0; 500 case TSTRING: 501 case TPTR32: 502 case TPTR64: 503 case TUNSAFEPTR: 504 case TINTER: 505 case TCHAN: 506 case TMAP: 507 case TFUNC: 508 default: 509 return 1; 510 } 511 } 512 513 /* 514 * commonType 515 * ../../pkg/runtime/type.go:/commonType 516 */ 517 static int 518 dcommontype(Sym *s, int ot, Type *t) 519 { 520 int i, alg, sizeofAlg; 521 Sym *sptr, *algsym; 522 static Sym *algarray; 523 char *p; 524 525 if(ot != 0) 526 fatal("dcommontype %d", ot); 527 528 sizeofAlg = 4*widthptr; 529 if(algarray == nil) 530 algarray = pkglookup("algarray", runtimepkg); 531 alg = algtype(t); 532 algsym = S; 533 if(alg < 0) 534 algsym = dalgsym(t); 535 536 dowidth(t); 537 if(t->sym != nil && !isptr[t->etype]) 538 sptr = dtypesym(ptrto(t)); 539 else 540 sptr = weaktypesym(ptrto(t)); 541 542 // ../../pkg/reflect/type.go:/^type.commonType 543 // actual type structure 544 // type commonType struct { 545 // size uintptr 546 // hash uint32 547 // _ uint8 548 // align uint8 549 // fieldAlign uint8 550 // kind uint8 551 // alg unsafe.Pointer 552 // gc unsafe.Pointer 553 // string *string 554 // *extraType 555 // ptrToThis *Type 556 // } 557 ot = duintptr(s, ot, t->width); 558 ot = duint32(s, ot, typehash(t)); 559 ot = duint8(s, ot, 0); // unused 560 561 // runtime (and common sense) expects alignment to be a power of two. 562 i = t->align; 563 if(i == 0) 564 i = 1; 565 if((i&(i-1)) != 0) 566 fatal("invalid alignment %d for %T", t->align, t); 567 ot = duint8(s, ot, t->align); // align 568 ot = duint8(s, ot, t->align); // fieldAlign 569 570 i = kinds[t->etype]; 571 if(t->etype == TARRAY && t->bound < 0) 572 i = KindSlice; 573 if(!haspointers(t)) 574 i |= KindNoPointers; 575 ot = duint8(s, ot, i); // kind 576 if(alg >= 0) 577 ot = dsymptr(s, ot, algarray, alg*sizeofAlg); 578 else 579 ot = dsymptr(s, ot, algsym, 0); 580 ot = dsymptr(s, ot, dgcsym(t), 0); // gc 581 p = smprint("%-uT", t); 582 //print("dcommontype: %s\n", p); 583 ot = dgostringptr(s, ot, p); // string 584 free(p); 585 586 // skip pointer to extraType, 587 // which follows the rest of this type structure. 588 // caller will fill in if needed. 589 // otherwise linker will assume 0. 590 ot += widthptr; 591 592 ot = dsymptr(s, ot, sptr, 0); // ptrto type 593 return ot; 594 } 595 596 Sym* 597 typesym(Type *t) 598 { 599 char *p; 600 Sym *s; 601 602 p = smprint("%-T", t); 603 s = pkglookup(p, typepkg); 604 //print("typesym: %s -> %+S\n", p, s); 605 free(p); 606 return s; 607 } 608 609 Sym* 610 tracksym(Type *t) 611 { 612 char *p; 613 Sym *s; 614 615 p = smprint("%-T.%s", t->outer, t->sym->name); 616 s = pkglookup(p, trackpkg); 617 free(p); 618 return s; 619 } 620 621 Sym* 622 typelinksym(Type *t) 623 { 624 char *p; 625 Sym *s; 626 627 // %-uT is what the generated Type's string field says. 628 // It uses (ambiguous) package names instead of import paths. 629 // %-T is the complete, unambiguous type name. 630 // We want the types to end up sorted by string field, 631 // so use that first in the name, and then add :%-T to 632 // disambiguate. The names are a little long but they are 633 // discarded by the linker and do not end up in the symbol 634 // table of the final binary. 635 p = smprint("%-uT/%-T", t, t); 636 s = pkglookup(p, typelinkpkg); 637 //print("typelinksym: %s -> %+S\n", p, s); 638 free(p); 639 return s; 640 } 641 642 Sym* 643 typesymprefix(char *prefix, Type *t) 644 { 645 char *p; 646 Sym *s; 647 648 p = smprint("%s.%-T", prefix, t); 649 s = pkglookup(p, typepkg); 650 //print("algsym: %s -> %+S\n", p, s); 651 free(p); 652 return s; 653 } 654 655 Sym* 656 typenamesym(Type *t) 657 { 658 Sym *s; 659 Node *n; 660 661 if(t == T || (isptr[t->etype] && t->type == T) || isideal(t)) 662 fatal("typename %T", t); 663 s = typesym(t); 664 if(s->def == N) { 665 n = nod(ONAME, N, N); 666 n->sym = s; 667 n->type = types[TUINT8]; 668 n->addable = 1; 669 n->ullman = 1; 670 n->class = PEXTERN; 671 n->xoffset = 0; 672 n->typecheck = 1; 673 s->def = n; 674 675 signatlist = list(signatlist, typenod(t)); 676 } 677 return s->def->sym; 678 } 679 680 Node* 681 typename(Type *t) 682 { 683 Sym *s; 684 Node *n; 685 686 s = typenamesym(t); 687 n = nod(OADDR, s->def, N); 688 n->type = ptrto(s->def->type); 689 n->addable = 1; 690 n->ullman = 2; 691 n->typecheck = 1; 692 return n; 693 } 694 695 static Sym* 696 weaktypesym(Type *t) 697 { 698 char *p; 699 Sym *s; 700 701 p = smprint("%-T", t); 702 s = pkglookup(p, weaktypepkg); 703 //print("weaktypesym: %s -> %+S\n", p, s); 704 free(p); 705 return s; 706 } 707 708 static Sym* 709 dtypesym(Type *t) 710 { 711 int ot, xt, n, isddd, dupok; 712 Sym *s, *s1, *s2, *slink; 713 Sig *a, *m; 714 Type *t1, *tbase, *t2; 715 716 // Replace byte, rune aliases with real type. 717 // They've been separate internally to make error messages 718 // better, but we have to merge them in the reflect tables. 719 if(t == bytetype || t == runetype) 720 t = types[t->etype]; 721 722 if(isideal(t)) 723 fatal("dtypesym %T", t); 724 725 s = typesym(t); 726 if(s->flags & SymSiggen) 727 return s; 728 s->flags |= SymSiggen; 729 730 // special case (look for runtime below): 731 // when compiling package runtime, 732 // emit the type structures for int, float, etc. 733 tbase = t; 734 if(isptr[t->etype] && t->sym == S && t->type->sym != S) 735 tbase = t->type; 736 dupok = tbase->sym == S; 737 738 if(compiling_runtime && 739 (tbase == types[tbase->etype] || 740 tbase == bytetype || 741 tbase == runetype || 742 tbase == errortype)) { // int, float, etc 743 goto ok; 744 } 745 746 // named types from other files are defined only by those files 747 if(tbase->sym && !tbase->local) 748 return s; 749 if(isforw[tbase->etype]) 750 return s; 751 752 ok: 753 ot = 0; 754 xt = 0; 755 switch(t->etype) { 756 default: 757 ot = dcommontype(s, ot, t); 758 xt = ot - 2*widthptr; 759 break; 760 761 case TARRAY: 762 if(t->bound >= 0) { 763 // ../../pkg/runtime/type.go:/ArrayType 764 s1 = dtypesym(t->type); 765 t2 = typ(TARRAY); 766 t2->type = t->type; 767 t2->bound = -1; // slice 768 s2 = dtypesym(t2); 769 ot = dcommontype(s, ot, t); 770 xt = ot - 2*widthptr; 771 ot = dsymptr(s, ot, s1, 0); 772 ot = dsymptr(s, ot, s2, 0); 773 ot = duintptr(s, ot, t->bound); 774 } else { 775 // ../../pkg/runtime/type.go:/SliceType 776 s1 = dtypesym(t->type); 777 ot = dcommontype(s, ot, t); 778 xt = ot - 2*widthptr; 779 ot = dsymptr(s, ot, s1, 0); 780 } 781 break; 782 783 case TCHAN: 784 // ../../pkg/runtime/type.go:/ChanType 785 s1 = dtypesym(t->type); 786 ot = dcommontype(s, ot, t); 787 xt = ot - 2*widthptr; 788 ot = dsymptr(s, ot, s1, 0); 789 ot = duintptr(s, ot, t->chan); 790 break; 791 792 case TFUNC: 793 for(t1=getthisx(t)->type; t1; t1=t1->down) 794 dtypesym(t1->type); 795 isddd = 0; 796 for(t1=getinargx(t)->type; t1; t1=t1->down) { 797 isddd = t1->isddd; 798 dtypesym(t1->type); 799 } 800 for(t1=getoutargx(t)->type; t1; t1=t1->down) 801 dtypesym(t1->type); 802 803 ot = dcommontype(s, ot, t); 804 xt = ot - 2*widthptr; 805 ot = duint8(s, ot, isddd); 806 807 // two slice headers: in and out. 808 ot = rnd(ot, widthptr); 809 ot = dsymptr(s, ot, s, ot+2*(widthptr+2*widthint)); 810 n = t->thistuple + t->intuple; 811 ot = duintxx(s, ot, n, widthint); 812 ot = duintxx(s, ot, n, widthint); 813 ot = dsymptr(s, ot, s, ot+1*(widthptr+2*widthint)+n*widthptr); 814 ot = duintxx(s, ot, t->outtuple, widthint); 815 ot = duintxx(s, ot, t->outtuple, widthint); 816 817 // slice data 818 for(t1=getthisx(t)->type; t1; t1=t1->down, n++) 819 ot = dsymptr(s, ot, dtypesym(t1->type), 0); 820 for(t1=getinargx(t)->type; t1; t1=t1->down, n++) 821 ot = dsymptr(s, ot, dtypesym(t1->type), 0); 822 for(t1=getoutargx(t)->type; t1; t1=t1->down, n++) 823 ot = dsymptr(s, ot, dtypesym(t1->type), 0); 824 break; 825 826 case TINTER: 827 m = imethods(t); 828 n = 0; 829 for(a=m; a; a=a->link) { 830 dtypesym(a->type); 831 n++; 832 } 833 834 // ../../pkg/runtime/type.go:/InterfaceType 835 ot = dcommontype(s, ot, t); 836 xt = ot - 2*widthptr; 837 ot = dsymptr(s, ot, s, ot+widthptr+2*widthint); 838 ot = duintxx(s, ot, n, widthint); 839 ot = duintxx(s, ot, n, widthint); 840 for(a=m; a; a=a->link) { 841 // ../../pkg/runtime/type.go:/imethod 842 ot = dgostringptr(s, ot, a->name); 843 ot = dgopkgpath(s, ot, a->pkg); 844 ot = dsymptr(s, ot, dtypesym(a->type), 0); 845 } 846 break; 847 848 case TMAP: 849 // ../../pkg/runtime/type.go:/MapType 850 s1 = dtypesym(t->down); 851 s2 = dtypesym(t->type); 852 ot = dcommontype(s, ot, t); 853 xt = ot - 2*widthptr; 854 ot = dsymptr(s, ot, s1, 0); 855 ot = dsymptr(s, ot, s2, 0); 856 break; 857 858 case TPTR32: 859 case TPTR64: 860 if(t->type->etype == TANY) { 861 // ../../pkg/runtime/type.go:/UnsafePointerType 862 ot = dcommontype(s, ot, t); 863 break; 864 } 865 // ../../pkg/runtime/type.go:/PtrType 866 s1 = dtypesym(t->type); 867 ot = dcommontype(s, ot, t); 868 xt = ot - 2*widthptr; 869 ot = dsymptr(s, ot, s1, 0); 870 break; 871 872 case TSTRUCT: 873 // ../../pkg/runtime/type.go:/StructType 874 // for security, only the exported fields. 875 n = 0; 876 for(t1=t->type; t1!=T; t1=t1->down) { 877 dtypesym(t1->type); 878 n++; 879 } 880 ot = dcommontype(s, ot, t); 881 xt = ot - 2*widthptr; 882 ot = dsymptr(s, ot, s, ot+widthptr+2*widthint); 883 ot = duintxx(s, ot, n, widthint); 884 ot = duintxx(s, ot, n, widthint); 885 for(t1=t->type; t1!=T; t1=t1->down) { 886 // ../../pkg/runtime/type.go:/structField 887 if(t1->sym && !t1->embedded) { 888 ot = dgostringptr(s, ot, t1->sym->name); 889 if(exportname(t1->sym->name)) 890 ot = dgostringptr(s, ot, nil); 891 else 892 ot = dgopkgpath(s, ot, t1->sym->pkg); 893 } else { 894 ot = dgostringptr(s, ot, nil); 895 if(t1->type->sym != S && t1->type->sym->pkg == builtinpkg) 896 ot = dgopkgpath(s, ot, localpkg); 897 else 898 ot = dgostringptr(s, ot, nil); 899 } 900 ot = dsymptr(s, ot, dtypesym(t1->type), 0); 901 ot = dgostrlitptr(s, ot, t1->note); 902 ot = duintptr(s, ot, t1->width); // field offset 903 } 904 break; 905 } 906 ot = dextratype(s, ot, t, xt); 907 ggloblsym(s, ot, dupok, 1); 908 909 // generate typelink.foo pointing at s = type.foo. 910 // The linker will leave a table of all the typelinks for 911 // types in the binary, so reflect can find them. 912 // We only need the link for unnamed composites that 913 // we want be able to find. 914 if(t->sym == S) { 915 switch(t->etype) { 916 case TARRAY: 917 case TCHAN: 918 case TMAP: 919 slink = typelinksym(t); 920 dsymptr(slink, 0, s, 0); 921 ggloblsym(slink, widthptr, dupok, 1); 922 } 923 } 924 925 return s; 926 } 927 928 void 929 dumptypestructs(void) 930 { 931 int i; 932 NodeList *l; 933 Node *n; 934 Type *t; 935 Pkg *p; 936 937 // copy types from externdcl list to signatlist 938 for(l=externdcl; l; l=l->next) { 939 n = l->n; 940 if(n->op != OTYPE) 941 continue; 942 signatlist = list(signatlist, n); 943 } 944 945 // process signatlist 946 for(l=signatlist; l; l=l->next) { 947 n = l->n; 948 if(n->op != OTYPE) 949 continue; 950 t = n->type; 951 dtypesym(t); 952 if(t->sym) 953 dtypesym(ptrto(t)); 954 } 955 956 // generate import strings for imported packages 957 for(i=0; i<nelem(phash); i++) 958 for(p=phash[i]; p; p=p->link) 959 if(p->direct) 960 dimportpath(p); 961 962 // do basic types if compiling package runtime. 963 // they have to be in at least one package, 964 // and runtime is always loaded implicitly, 965 // so this is as good as any. 966 // another possible choice would be package main, 967 // but using runtime means fewer copies in .6 files. 968 if(compiling_runtime) { 969 for(i=1; i<=TBOOL; i++) 970 dtypesym(ptrto(types[i])); 971 dtypesym(ptrto(types[TSTRING])); 972 dtypesym(ptrto(types[TUNSAFEPTR])); 973 974 // emit type structs for error and func(error) string. 975 // The latter is the type of an auto-generated wrapper. 976 dtypesym(ptrto(errortype)); 977 dtypesym(functype(nil, 978 list1(nod(ODCLFIELD, N, typenod(errortype))), 979 list1(nod(ODCLFIELD, N, typenod(types[TSTRING]))))); 980 981 // add paths for runtime and main, which 6l imports implicitly. 982 dimportpath(runtimepkg); 983 if(flag_race) 984 dimportpath(racepkg); 985 dimportpath(mkpkg(strlit("main"))); 986 } 987 } 988 989 static Sym* 990 dalgsym(Type *t) 991 { 992 int ot; 993 Sym *s, *hash, *eq; 994 char buf[100]; 995 996 // dalgsym is only called for a type that needs an algorithm table, 997 // which implies that the type is comparable (or else it would use ANOEQ). 998 999 s = typesymprefix(".alg", t); 1000 hash = typesymprefix(".hash", t); 1001 genhash(hash, t); 1002 eq = typesymprefix(".eq", t); 1003 geneq(eq, t); 1004 1005 // ../../pkg/runtime/runtime.h:/Alg 1006 ot = 0; 1007 ot = dsymptr(s, ot, hash, 0); 1008 ot = dsymptr(s, ot, eq, 0); 1009 ot = dsymptr(s, ot, pkglookup("memprint", runtimepkg), 0); 1010 switch(t->width) { 1011 default: 1012 ot = dsymptr(s, ot, pkglookup("memcopy", runtimepkg), 0); 1013 break; 1014 case 1: 1015 case 2: 1016 case 4: 1017 case 8: 1018 case 16: 1019 snprint(buf, sizeof buf, "memcopy%d", (int)t->width*8); 1020 ot = dsymptr(s, ot, pkglookup(buf, runtimepkg), 0); 1021 break; 1022 } 1023 1024 ggloblsym(s, ot, 1, 1); 1025 return s; 1026 } 1027 1028 static int 1029 gcinline(Type *t) { 1030 switch(t->etype) { 1031 case TARRAY: 1032 if(t->bound == 1) 1033 return 1; 1034 if(t->width <= 4*widthptr) 1035 return 1; 1036 break; 1037 } 1038 return 0; 1039 } 1040 1041 static int 1042 dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size) 1043 { 1044 Type *t1; 1045 vlong o, off2, fieldoffset, i; 1046 1047 if(t->align > 0 && (*off % t->align) != 0) 1048 fatal("dgcsym1: invalid initial alignment, %T", t); 1049 1050 if(t->width == BADWIDTH) 1051 dowidth(t); 1052 1053 switch(t->etype) { 1054 case TINT8: 1055 case TUINT8: 1056 case TINT16: 1057 case TUINT16: 1058 case TINT32: 1059 case TUINT32: 1060 case TINT64: 1061 case TUINT64: 1062 case TINT: 1063 case TUINT: 1064 case TUINTPTR: 1065 case TBOOL: 1066 case TFLOAT32: 1067 case TFLOAT64: 1068 case TCOMPLEX64: 1069 case TCOMPLEX128: 1070 *off += t->width; 1071 break; 1072 1073 case TPTR32: 1074 case TPTR64: 1075 // NOTE: Any changes here need to be made to reflect.PtrTo as well. 1076 if(*off % widthptr != 0) 1077 fatal("dgcsym1: invalid alignment, %T", t); 1078 if(!haspointers(t->type) || t->type->etype == TUINT8) { 1079 ot = duintptr(s, ot, GC_APTR); 1080 ot = duintptr(s, ot, *off); 1081 } else { 1082 ot = duintptr(s, ot, GC_PTR); 1083 ot = duintptr(s, ot, *off); 1084 ot = dsymptr(s, ot, dgcsym(t->type), 0); 1085 } 1086 *off += t->width; 1087 break; 1088 1089 case TUNSAFEPTR: 1090 case TFUNC: 1091 if(*off % widthptr != 0) 1092 fatal("dgcsym1: invalid alignment, %T", t); 1093 ot = duintptr(s, ot, GC_APTR); 1094 ot = duintptr(s, ot, *off); 1095 *off += t->width; 1096 break; 1097 1098 // struct Hchan* 1099 case TCHAN: 1100 // NOTE: Any changes here need to be made to reflect.ChanOf as well. 1101 if(*off % widthptr != 0) 1102 fatal("dgcsym1: invalid alignment, %T", t); 1103 ot = duintptr(s, ot, GC_CHAN_PTR); 1104 ot = duintptr(s, ot, *off); 1105 ot = dsymptr(s, ot, dtypesym(t), 0); 1106 *off += t->width; 1107 break; 1108 1109 // struct Hmap* 1110 case TMAP: 1111 // NOTE: Any changes here need to be made to reflect.MapOf as well. 1112 if(*off % widthptr != 0) 1113 fatal("dgcsym1: invalid alignment, %T", t); 1114 ot = duintptr(s, ot, GC_MAP_PTR); 1115 ot = duintptr(s, ot, *off); 1116 ot = dsymptr(s, ot, dtypesym(t), 0); 1117 *off += t->width; 1118 break; 1119 1120 // struct { byte *str; int32 len; } 1121 case TSTRING: 1122 if(*off % widthptr != 0) 1123 fatal("dgcsym1: invalid alignment, %T", t); 1124 ot = duintptr(s, ot, GC_STRING); 1125 ot = duintptr(s, ot, *off); 1126 *off += t->width; 1127 break; 1128 1129 // struct { Itab* tab; void* data; } 1130 // struct { Type* type; void* data; } // When isnilinter(t)==true 1131 case TINTER: 1132 if(*off % widthptr != 0) 1133 fatal("dgcsym1: invalid alignment, %T", t); 1134 if(isnilinter(t)) { 1135 ot = duintptr(s, ot, GC_EFACE); 1136 ot = duintptr(s, ot, *off); 1137 } else { 1138 ot = duintptr(s, ot, GC_IFACE); 1139 ot = duintptr(s, ot, *off); 1140 } 1141 *off += t->width; 1142 break; 1143 1144 case TARRAY: 1145 if(t->bound < -1) 1146 fatal("dgcsym1: invalid bound, %T", t); 1147 if(t->type->width == BADWIDTH) 1148 dowidth(t->type); 1149 if(isslice(t)) { 1150 // NOTE: Any changes here need to be made to reflect.SliceOf as well. 1151 // struct { byte* array; uint32 len; uint32 cap; } 1152 if(*off % widthptr != 0) 1153 fatal("dgcsym1: invalid alignment, %T", t); 1154 if(t->type->width != 0) { 1155 ot = duintptr(s, ot, GC_SLICE); 1156 ot = duintptr(s, ot, *off); 1157 ot = dsymptr(s, ot, dgcsym(t->type), 0); 1158 } else { 1159 ot = duintptr(s, ot, GC_APTR); 1160 ot = duintptr(s, ot, *off); 1161 } 1162 *off += t->width; 1163 } else { 1164 // NOTE: Any changes here need to be made to reflect.ArrayOf as well, 1165 // at least once ArrayOf's gc info is implemented and ArrayOf is exported. 1166 // struct { byte* array; uint32 len; uint32 cap; } 1167 if(t->bound < 1 || !haspointers(t->type)) { 1168 *off += t->width; 1169 } else if(gcinline(t)) { 1170 for(i=0; i<t->bound; i++) 1171 ot = dgcsym1(s, ot, t->type, off, stack_size); // recursive call of dgcsym1 1172 } else { 1173 if(stack_size < GC_STACK_CAPACITY) { 1174 ot = duintptr(s, ot, GC_ARRAY_START); // a stack push during GC 1175 ot = duintptr(s, ot, *off); 1176 ot = duintptr(s, ot, t->bound); 1177 ot = duintptr(s, ot, t->type->width); 1178 off2 = 0; 1179 ot = dgcsym1(s, ot, t->type, &off2, stack_size+1); // recursive call of dgcsym1 1180 ot = duintptr(s, ot, GC_ARRAY_NEXT); // a stack pop during GC 1181 } else { 1182 ot = duintptr(s, ot, GC_REGION); 1183 ot = duintptr(s, ot, *off); 1184 ot = duintptr(s, ot, t->width); 1185 ot = dsymptr(s, ot, dgcsym(t), 0); 1186 } 1187 *off += t->width; 1188 } 1189 } 1190 break; 1191 1192 case TSTRUCT: 1193 o = 0; 1194 for(t1=t->type; t1!=T; t1=t1->down) { 1195 fieldoffset = t1->width; 1196 *off += fieldoffset - o; 1197 ot = dgcsym1(s, ot, t1->type, off, stack_size); // recursive call of dgcsym1 1198 o = fieldoffset + t1->type->width; 1199 } 1200 *off += t->width - o; 1201 break; 1202 1203 default: 1204 fatal("dgcsym1: unexpected type %T", t); 1205 } 1206 1207 return ot; 1208 } 1209 1210 static Sym* 1211 dgcsym(Type *t) 1212 { 1213 int ot; 1214 vlong off; 1215 Sym *s; 1216 1217 s = typesymprefix(".gc", t); 1218 if(s->flags & SymGcgen) 1219 return s; 1220 s->flags |= SymGcgen; 1221 1222 if(t->width == BADWIDTH) 1223 dowidth(t); 1224 1225 ot = 0; 1226 off = 0; 1227 ot = duintptr(s, ot, t->width); 1228 ot = dgcsym1(s, ot, t, &off, 0); 1229 ot = duintptr(s, ot, GC_END); 1230 ggloblsym(s, ot, 1, 1); 1231 1232 if(t->align > 0) 1233 off = rnd(off, t->align); 1234 if(off != t->width) 1235 fatal("dgcsym: off=%lld, size=%lld, type %T", off, t->width, t); 1236 1237 return s; 1238 }