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