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