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