github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/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 "../ld/textflag.h" 9 #include "../../runtime/mgc0.h" 10 #include "../../runtime/typekind.h" 11 12 /* 13 * runtime interface and reflection data structures 14 */ 15 16 static NodeList* signatlist; 17 static Sym* dtypesym(Type*); 18 static Sym* weaktypesym(Type*); 19 static Sym* dalgsym(Type*); 20 static int usegcprog(Type*); 21 static void gengcprog(Type*, Sym**, Sym**); 22 static void gengcmask(Type*, uint8[16]); 23 24 static int 25 sigcmp(Sig *a, Sig *b) 26 { 27 int i; 28 29 i = strcmp(a->name, b->name); 30 if(i != 0) 31 return i; 32 if(a->pkg == b->pkg) 33 return 0; 34 if(a->pkg == nil) 35 return -1; 36 if(b->pkg == nil) 37 return +1; 38 return strcmp(a->pkg->path->s, b->pkg->path->s); 39 } 40 41 static Sig* 42 lsort(Sig *l, int(*f)(Sig*, Sig*)) 43 { 44 Sig *l1, *l2, *le; 45 46 if(l == 0 || l->link == 0) 47 return l; 48 49 l1 = l; 50 l2 = l; 51 for(;;) { 52 l2 = l2->link; 53 if(l2 == 0) 54 break; 55 l2 = l2->link; 56 if(l2 == 0) 57 break; 58 l1 = l1->link; 59 } 60 61 l2 = l1->link; 62 l1->link = 0; 63 l1 = lsort(l, f); 64 l2 = lsort(l2, f); 65 66 /* set up lead element */ 67 if((*f)(l1, l2) < 0) { 68 l = l1; 69 l1 = l1->link; 70 } else { 71 l = l2; 72 l2 = l2->link; 73 } 74 le = l; 75 76 for(;;) { 77 if(l1 == 0) { 78 while(l2) { 79 le->link = l2; 80 le = l2; 81 l2 = l2->link; 82 } 83 le->link = 0; 84 break; 85 } 86 if(l2 == 0) { 87 while(l1) { 88 le->link = l1; 89 le = l1; 90 l1 = l1->link; 91 } 92 break; 93 } 94 if((*f)(l1, l2) < 0) { 95 le->link = l1; 96 le = l1; 97 l1 = l1->link; 98 } else { 99 le->link = l2; 100 le = l2; 101 l2 = l2->link; 102 } 103 } 104 le->link = 0; 105 return l; 106 } 107 108 // Builds a type respresenting a Bucket structure for 109 // the given map type. This type is not visible to users - 110 // we include only enough information to generate a correct GC 111 // program for it. 112 // Make sure this stays in sync with ../../runtime/hashmap.c! 113 enum { 114 BUCKETSIZE = 8, 115 MAXKEYSIZE = 128, 116 MAXVALSIZE = 128, 117 }; 118 119 static Type* 120 mapbucket(Type *t) 121 { 122 Type *keytype, *valtype; 123 Type *bucket; 124 Type *overflowfield, *keysfield, *valuesfield; 125 int32 offset; 126 127 if(t->bucket != T) 128 return t->bucket; 129 130 keytype = t->down; 131 valtype = t->type; 132 dowidth(keytype); 133 dowidth(valtype); 134 if(keytype->width > MAXKEYSIZE) 135 keytype = ptrto(keytype); 136 if(valtype->width > MAXVALSIZE) 137 valtype = ptrto(valtype); 138 139 bucket = typ(TSTRUCT); 140 bucket->noalg = 1; 141 142 // The first field is: uint8 topbits[BUCKETSIZE]. 143 // We don't need to encode it as GC doesn't care about it. 144 offset = BUCKETSIZE * 1; 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 overflowfield = typ(TFIELD); 167 overflowfield->type = ptrto(bucket); 168 overflowfield->width = offset; // "width" is offset in structure 169 overflowfield->sym = mal(sizeof(Sym)); // not important but needs to be set to give this type a name 170 overflowfield->sym->name = "overflow"; 171 offset += widthptr; 172 173 // Pad to the native integer alignment. 174 // This is usually the same as widthptr; the exception (as usual) is nacl/amd64. 175 if(widthreg > widthptr) 176 offset += widthreg - widthptr; 177 178 // link up fields 179 bucket->type = keysfield; 180 keysfield->down = valuesfield; 181 valuesfield->down = overflowfield; 182 overflowfield->down = T; 183 184 bucket->width = offset; 185 bucket->local = t->local; 186 t->bucket = bucket; 187 bucket->map = t; 188 return bucket; 189 } 190 191 // Builds a type respresenting a Hmap structure for 192 // the given map type. This type is not visible to users - 193 // we include only enough information to generate a correct GC 194 // program for it. 195 // Make sure this stays in sync with ../../runtime/hashmap.go! 196 static Type* 197 hmap(Type *t) 198 { 199 Type *h, *bucket; 200 Type *bucketsfield, *oldbucketsfield; 201 int32 offset; 202 203 if(t->hmap != T) 204 return t->hmap; 205 206 bucket = mapbucket(t); 207 h = typ(TSTRUCT); 208 h->noalg = 1; 209 210 offset = widthint; // count 211 offset += 4; // flags 212 offset += 4; // hash0 213 offset += 1; // B 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 ../../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(!isdirectiface(it)) 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, DUPOK|RODATA); 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 * ../../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 off = rnd(off, widthptr); 568 dsymptr(sym, ptroff, sym, off); 569 570 n = 0; 571 for(a=m; a; a=a->link) { 572 dtypesym(a->type); 573 n++; 574 } 575 576 ot = off; 577 s = sym; 578 if(t->sym) { 579 ot = dgostringptr(s, ot, t->sym->name); 580 if(t != types[t->etype] && t != errortype) 581 ot = dgopkgpath(s, ot, t->sym->pkg); 582 else 583 ot = dgostringptr(s, ot, nil); 584 } else { 585 ot = dgostringptr(s, ot, nil); 586 ot = dgostringptr(s, ot, nil); 587 } 588 589 // slice header 590 ot = dsymptr(s, ot, s, ot + widthptr + 2*widthint); 591 ot = duintxx(s, ot, n, widthint); 592 ot = duintxx(s, ot, n, widthint); 593 594 // methods 595 for(a=m; a; a=a->link) { 596 // method 597 // ../../runtime/type.go:/method 598 ot = dgostringptr(s, ot, a->name); 599 ot = dgopkgpath(s, ot, a->pkg); 600 ot = dsymptr(s, ot, dtypesym(a->mtype), 0); 601 ot = dsymptr(s, ot, dtypesym(a->type), 0); 602 if(a->isym) 603 ot = dsymptr(s, ot, a->isym, 0); 604 else 605 ot = duintptr(s, ot, 0); 606 if(a->tsym) 607 ot = dsymptr(s, ot, a->tsym, 0); 608 else 609 ot = duintptr(s, ot, 0); 610 } 611 612 return ot; 613 } 614 615 static int 616 kinds[] = 617 { 618 [TINT] = KindInt, 619 [TUINT] = KindUint, 620 [TINT8] = KindInt8, 621 [TUINT8] = KindUint8, 622 [TINT16] = KindInt16, 623 [TUINT16] = KindUint16, 624 [TINT32] = KindInt32, 625 [TUINT32] = KindUint32, 626 [TINT64] = KindInt64, 627 [TUINT64] = KindUint64, 628 [TUINTPTR] = KindUintptr, 629 [TFLOAT32] = KindFloat32, 630 [TFLOAT64] = KindFloat64, 631 [TBOOL] = KindBool, 632 [TSTRING] = KindString, 633 [TPTR32] = KindPtr, 634 [TPTR64] = KindPtr, 635 [TSTRUCT] = KindStruct, 636 [TINTER] = KindInterface, 637 [TCHAN] = KindChan, 638 [TMAP] = KindMap, 639 [TARRAY] = KindArray, 640 [TFUNC] = KindFunc, 641 [TCOMPLEX64] = KindComplex64, 642 [TCOMPLEX128] = KindComplex128, 643 [TUNSAFEPTR] = KindUnsafePointer, 644 }; 645 646 int 647 haspointers(Type *t) 648 { 649 Type *t1; 650 int ret; 651 652 if(t->haspointers != 0) 653 return t->haspointers - 1; 654 655 switch(t->etype) { 656 case TINT: 657 case TUINT: 658 case TINT8: 659 case TUINT8: 660 case TINT16: 661 case TUINT16: 662 case TINT32: 663 case TUINT32: 664 case TINT64: 665 case TUINT64: 666 case TUINTPTR: 667 case TFLOAT32: 668 case TFLOAT64: 669 case TCOMPLEX64: 670 case TCOMPLEX128: 671 case TBOOL: 672 ret = 0; 673 break; 674 case TARRAY: 675 if(t->bound < 0) { // slice 676 ret = 1; 677 break; 678 } 679 if(t->bound == 0) { // empty array 680 ret = 0; 681 break; 682 } 683 ret = haspointers(t->type); 684 break; 685 case TSTRUCT: 686 ret = 0; 687 for(t1=t->type; t1!=T; t1=t1->down) { 688 if(haspointers(t1->type)) { 689 ret = 1; 690 break; 691 } 692 } 693 break; 694 case TSTRING: 695 case TPTR32: 696 case TPTR64: 697 case TUNSAFEPTR: 698 case TINTER: 699 case TCHAN: 700 case TMAP: 701 case TFUNC: 702 default: 703 ret = 1; 704 break; 705 } 706 707 t->haspointers = 1+ret; 708 return ret; 709 } 710 711 /* 712 * commonType 713 * ../../runtime/type.go:/commonType 714 */ 715 static int 716 dcommontype(Sym *s, int ot, Type *t) 717 { 718 int i, alg, sizeofAlg, gcprog; 719 Sym *sptr, *algsym, *zero, *gcprog0, *gcprog1, *sbits; 720 uint8 gcmask[16]; 721 static Sym *algarray; 722 uint64 x1, x2; 723 char *p; 724 725 if(ot != 0) 726 fatal("dcommontype %d", ot); 727 728 sizeofAlg = 2*widthptr; 729 if(algarray == nil) 730 algarray = pkglookup("algarray", runtimepkg); 731 dowidth(t); 732 alg = algtype(t); 733 algsym = S; 734 if(alg < 0) 735 algsym = dalgsym(t); 736 737 if(t->sym != nil && !isptr[t->etype]) 738 sptr = dtypesym(ptrto(t)); 739 else 740 sptr = weaktypesym(ptrto(t)); 741 742 // All (non-reflect-allocated) Types share the same zero object. 743 // Each place in the compiler where a pointer to the zero object 744 // might be returned by a runtime call (map access return value, 745 // 2-arg type cast) declares the size of the zerovalue it needs. 746 // The linker magically takes the max of all the sizes. 747 zero = pkglookup("zerovalue", runtimepkg); 748 749 // We use size 0 here so we get the pointer to the zero value, 750 // but don't allocate space for the zero value unless we need it. 751 // TODO: how do we get this symbol into bss? We really want 752 // a read-only bss, but I don't think such a thing exists. 753 754 // ../../pkg/reflect/type.go:/^type.commonType 755 // actual type structure 756 // type commonType struct { 757 // size uintptr 758 // hash uint32 759 // _ uint8 760 // align uint8 761 // fieldAlign uint8 762 // kind uint8 763 // alg unsafe.Pointer 764 // gc unsafe.Pointer 765 // string *string 766 // *extraType 767 // ptrToThis *Type 768 // zero unsafe.Pointer 769 // } 770 ot = duintptr(s, ot, t->width); 771 ot = duint32(s, ot, typehash(t)); 772 ot = duint8(s, ot, 0); // unused 773 774 // runtime (and common sense) expects alignment to be a power of two. 775 i = t->align; 776 if(i == 0) 777 i = 1; 778 if((i&(i-1)) != 0) 779 fatal("invalid alignment %d for %T", t->align, t); 780 ot = duint8(s, ot, t->align); // align 781 ot = duint8(s, ot, t->align); // fieldAlign 782 783 gcprog = usegcprog(t); 784 i = kinds[t->etype]; 785 if(t->etype == TARRAY && t->bound < 0) 786 i = KindSlice; 787 if(!haspointers(t)) 788 i |= KindNoPointers; 789 if(isdirectiface(t)) 790 i |= KindDirectIface; 791 if(gcprog) 792 i |= KindGCProg; 793 ot = duint8(s, ot, i); // kind 794 if(alg >= 0) 795 ot = dsymptr(s, ot, algarray, alg*sizeofAlg); 796 else 797 ot = dsymptr(s, ot, algsym, 0); 798 // gc 799 if(gcprog) { 800 gengcprog(t, &gcprog0, &gcprog1); 801 if(gcprog0 != S) 802 ot = dsymptr(s, ot, gcprog0, 0); 803 else 804 ot = duintptr(s, ot, 0); 805 ot = dsymptr(s, ot, gcprog1, 0); 806 } else { 807 gengcmask(t, gcmask); 808 x1 = 0; 809 for(i=0; i<8; i++) 810 x1 = x1<<8 | gcmask[i]; 811 if(widthptr == 4) { 812 p = smprint("gcbits.%#016llux", x1); 813 } else { 814 x2 = 0; 815 for(i=0; i<8; i++) 816 x2 = x2<<8 | gcmask[i+8]; 817 p = smprint("gcbits.%#016llux%016llux", x1, x2); 818 } 819 sbits = pkglookup(p, runtimepkg); 820 if((sbits->flags & SymUniq) == 0) { 821 sbits->flags |= SymUniq; 822 for(i = 0; i < 2*widthptr; i++) 823 duint8(sbits, i, gcmask[i]); 824 ggloblsym(sbits, 2*widthptr, DUPOK|RODATA); 825 } 826 ot = dsymptr(s, ot, sbits, 0); 827 ot = duintptr(s, ot, 0); 828 } 829 p = smprint("%-uT", t); 830 //print("dcommontype: %s\n", p); 831 ot = dgostringptr(s, ot, p); // string 832 free(p); 833 834 // skip pointer to extraType, 835 // which follows the rest of this type structure. 836 // caller will fill in if needed. 837 // otherwise linker will assume 0. 838 ot += widthptr; 839 840 ot = dsymptr(s, ot, sptr, 0); // ptrto type 841 ot = dsymptr(s, ot, zero, 0); // ptr to zero value 842 return ot; 843 } 844 845 Sym* 846 typesym(Type *t) 847 { 848 char *p; 849 Sym *s; 850 851 p = smprint("%-T", t); 852 s = pkglookup(p, typepkg); 853 //print("typesym: %s -> %+S\n", p, s); 854 free(p); 855 return s; 856 } 857 858 Sym* 859 tracksym(Type *t) 860 { 861 char *p; 862 Sym *s; 863 864 p = smprint("%-T.%s", t->outer, t->sym->name); 865 s = pkglookup(p, trackpkg); 866 free(p); 867 return s; 868 } 869 870 Sym* 871 typelinksym(Type *t) 872 { 873 char *p; 874 Sym *s; 875 876 // %-uT is what the generated Type's string field says. 877 // It uses (ambiguous) package names instead of import paths. 878 // %-T is the complete, unambiguous type name. 879 // We want the types to end up sorted by string field, 880 // so use that first in the name, and then add :%-T to 881 // disambiguate. The names are a little long but they are 882 // discarded by the linker and do not end up in the symbol 883 // table of the final binary. 884 p = smprint("%-uT/%-T", t, t); 885 s = pkglookup(p, typelinkpkg); 886 //print("typelinksym: %s -> %+S\n", p, s); 887 free(p); 888 return s; 889 } 890 891 Sym* 892 typesymprefix(char *prefix, Type *t) 893 { 894 char *p; 895 Sym *s; 896 897 p = smprint("%s.%-T", prefix, t); 898 s = pkglookup(p, typepkg); 899 //print("algsym: %s -> %+S\n", p, s); 900 free(p); 901 return s; 902 } 903 904 Sym* 905 typenamesym(Type *t) 906 { 907 Sym *s; 908 Node *n; 909 910 if(t == T || (isptr[t->etype] && t->type == T) || isideal(t)) 911 fatal("typename %T", t); 912 s = typesym(t); 913 if(s->def == N) { 914 n = nod(ONAME, N, N); 915 n->sym = s; 916 n->type = types[TUINT8]; 917 n->addable = 1; 918 n->ullman = 1; 919 n->class = PEXTERN; 920 n->xoffset = 0; 921 n->typecheck = 1; 922 s->def = n; 923 924 signatlist = list(signatlist, typenod(t)); 925 } 926 return s->def->sym; 927 } 928 929 Node* 930 typename(Type *t) 931 { 932 Sym *s; 933 Node *n; 934 935 s = typenamesym(t); 936 n = nod(OADDR, s->def, N); 937 n->type = ptrto(s->def->type); 938 n->addable = 1; 939 n->ullman = 2; 940 n->typecheck = 1; 941 return n; 942 } 943 944 static Sym* 945 weaktypesym(Type *t) 946 { 947 char *p; 948 Sym *s; 949 950 p = smprint("%-T", t); 951 s = pkglookup(p, weaktypepkg); 952 //print("weaktypesym: %s -> %+S\n", p, s); 953 free(p); 954 return s; 955 } 956 957 /* 958 * Returns 1 if t has a reflexive equality operator. 959 * That is, if x==x for all x of type t. 960 */ 961 static int 962 isreflexive(Type *t) 963 { 964 Type *t1; 965 switch(t->etype) { 966 case TBOOL: 967 case TINT: 968 case TUINT: 969 case TINT8: 970 case TUINT8: 971 case TINT16: 972 case TUINT16: 973 case TINT32: 974 case TUINT32: 975 case TINT64: 976 case TUINT64: 977 case TUINTPTR: 978 case TPTR32: 979 case TPTR64: 980 case TUNSAFEPTR: 981 case TSTRING: 982 case TCHAN: 983 return 1; 984 case TFLOAT32: 985 case TFLOAT64: 986 case TCOMPLEX64: 987 case TCOMPLEX128: 988 case TINTER: 989 return 0; 990 case TARRAY: 991 if(isslice(t)) 992 fatal("slice can't be a map key: %T", t); 993 return isreflexive(t->type); 994 case TSTRUCT: 995 for(t1=t->type; t1!=T; t1=t1->down) { 996 if(!isreflexive(t1->type)) 997 return 0; 998 } 999 return 1; 1000 default: 1001 fatal("bad type for map key: %T", t); 1002 return 0; 1003 } 1004 } 1005 1006 static Sym* 1007 dtypesym(Type *t) 1008 { 1009 int ot, xt, n, isddd, dupok; 1010 Sym *s, *s1, *s2, *s3, *s4, *slink; 1011 Sig *a, *m; 1012 Type *t1, *tbase, *t2; 1013 1014 // Replace byte, rune aliases with real type. 1015 // They've been separate internally to make error messages 1016 // better, but we have to merge them in the reflect tables. 1017 if(t == bytetype || t == runetype) 1018 t = types[t->etype]; 1019 1020 if(isideal(t)) 1021 fatal("dtypesym %T", t); 1022 1023 s = typesym(t); 1024 if(s->flags & SymSiggen) 1025 return s; 1026 s->flags |= SymSiggen; 1027 1028 // special case (look for runtime below): 1029 // when compiling package runtime, 1030 // emit the type structures for int, float, etc. 1031 tbase = t; 1032 if(isptr[t->etype] && t->sym == S && t->type->sym != S) 1033 tbase = t->type; 1034 dupok = 0; 1035 if(tbase->sym == S) 1036 dupok = DUPOK; 1037 1038 if(compiling_runtime && 1039 (tbase == types[tbase->etype] || 1040 tbase == bytetype || 1041 tbase == runetype || 1042 tbase == errortype)) { // int, float, etc 1043 goto ok; 1044 } 1045 1046 // named types from other files are defined only by those files 1047 if(tbase->sym && !tbase->local) 1048 return s; 1049 if(isforw[tbase->etype]) 1050 return s; 1051 1052 ok: 1053 ot = 0; 1054 xt = 0; 1055 switch(t->etype) { 1056 default: 1057 ot = dcommontype(s, ot, t); 1058 xt = ot - 3*widthptr; 1059 break; 1060 1061 case TARRAY: 1062 if(t->bound >= 0) { 1063 // ../../runtime/type.go:/ArrayType 1064 s1 = dtypesym(t->type); 1065 t2 = typ(TARRAY); 1066 t2->type = t->type; 1067 t2->bound = -1; // slice 1068 s2 = dtypesym(t2); 1069 ot = dcommontype(s, ot, t); 1070 xt = ot - 3*widthptr; 1071 ot = dsymptr(s, ot, s1, 0); 1072 ot = dsymptr(s, ot, s2, 0); 1073 ot = duintptr(s, ot, t->bound); 1074 } else { 1075 // ../../runtime/type.go:/SliceType 1076 s1 = dtypesym(t->type); 1077 ot = dcommontype(s, ot, t); 1078 xt = ot - 3*widthptr; 1079 ot = dsymptr(s, ot, s1, 0); 1080 } 1081 break; 1082 1083 case TCHAN: 1084 // ../../runtime/type.go:/ChanType 1085 s1 = dtypesym(t->type); 1086 ot = dcommontype(s, ot, t); 1087 xt = ot - 3*widthptr; 1088 ot = dsymptr(s, ot, s1, 0); 1089 ot = duintptr(s, ot, t->chan); 1090 break; 1091 1092 case TFUNC: 1093 for(t1=getthisx(t)->type; t1; t1=t1->down) 1094 dtypesym(t1->type); 1095 isddd = 0; 1096 for(t1=getinargx(t)->type; t1; t1=t1->down) { 1097 isddd = t1->isddd; 1098 dtypesym(t1->type); 1099 } 1100 for(t1=getoutargx(t)->type; t1; t1=t1->down) 1101 dtypesym(t1->type); 1102 1103 ot = dcommontype(s, ot, t); 1104 xt = ot - 3*widthptr; 1105 ot = duint8(s, ot, isddd); 1106 1107 // two slice headers: in and out. 1108 ot = rnd(ot, widthptr); 1109 ot = dsymptr(s, ot, s, ot+2*(widthptr+2*widthint)); 1110 n = t->thistuple + t->intuple; 1111 ot = duintxx(s, ot, n, widthint); 1112 ot = duintxx(s, ot, n, widthint); 1113 ot = dsymptr(s, ot, s, ot+1*(widthptr+2*widthint)+n*widthptr); 1114 ot = duintxx(s, ot, t->outtuple, widthint); 1115 ot = duintxx(s, ot, t->outtuple, widthint); 1116 1117 // slice data 1118 for(t1=getthisx(t)->type; t1; t1=t1->down, n++) 1119 ot = dsymptr(s, ot, dtypesym(t1->type), 0); 1120 for(t1=getinargx(t)->type; t1; t1=t1->down, n++) 1121 ot = dsymptr(s, ot, dtypesym(t1->type), 0); 1122 for(t1=getoutargx(t)->type; t1; t1=t1->down, n++) 1123 ot = dsymptr(s, ot, dtypesym(t1->type), 0); 1124 break; 1125 1126 case TINTER: 1127 m = imethods(t); 1128 n = 0; 1129 for(a=m; a; a=a->link) { 1130 dtypesym(a->type); 1131 n++; 1132 } 1133 1134 // ../../runtime/type.go:/InterfaceType 1135 ot = dcommontype(s, ot, t); 1136 xt = ot - 3*widthptr; 1137 ot = dsymptr(s, ot, s, ot+widthptr+2*widthint); 1138 ot = duintxx(s, ot, n, widthint); 1139 ot = duintxx(s, ot, n, widthint); 1140 for(a=m; a; a=a->link) { 1141 // ../../runtime/type.go:/imethod 1142 ot = dgostringptr(s, ot, a->name); 1143 ot = dgopkgpath(s, ot, a->pkg); 1144 ot = dsymptr(s, ot, dtypesym(a->type), 0); 1145 } 1146 break; 1147 1148 case TMAP: 1149 // ../../runtime/type.go:/MapType 1150 s1 = dtypesym(t->down); 1151 s2 = dtypesym(t->type); 1152 s3 = dtypesym(mapbucket(t)); 1153 s4 = dtypesym(hmap(t)); 1154 ot = dcommontype(s, ot, t); 1155 xt = ot - 3*widthptr; 1156 ot = dsymptr(s, ot, s1, 0); 1157 ot = dsymptr(s, ot, s2, 0); 1158 ot = dsymptr(s, ot, s3, 0); 1159 ot = dsymptr(s, ot, s4, 0); 1160 if(t->down->width > MAXKEYSIZE) { 1161 ot = duint8(s, ot, widthptr); 1162 ot = duint8(s, ot, 1); // indirect 1163 } else { 1164 ot = duint8(s, ot, t->down->width); 1165 ot = duint8(s, ot, 0); // not indirect 1166 } 1167 if(t->type->width > MAXVALSIZE) { 1168 ot = duint8(s, ot, widthptr); 1169 ot = duint8(s, ot, 1); // indirect 1170 } else { 1171 ot = duint8(s, ot, t->type->width); 1172 ot = duint8(s, ot, 0); // not indirect 1173 } 1174 ot = duint16(s, ot, mapbucket(t)->width); 1175 ot = duint8(s, ot, isreflexive(t->down)); 1176 break; 1177 1178 case TPTR32: 1179 case TPTR64: 1180 if(t->type->etype == TANY) { 1181 // ../../runtime/type.go:/UnsafePointerType 1182 ot = dcommontype(s, ot, t); 1183 break; 1184 } 1185 // ../../runtime/type.go:/PtrType 1186 s1 = dtypesym(t->type); 1187 ot = dcommontype(s, ot, t); 1188 xt = ot - 3*widthptr; 1189 ot = dsymptr(s, ot, s1, 0); 1190 break; 1191 1192 case TSTRUCT: 1193 // ../../runtime/type.go:/StructType 1194 // for security, only the exported fields. 1195 n = 0; 1196 for(t1=t->type; t1!=T; t1=t1->down) { 1197 dtypesym(t1->type); 1198 n++; 1199 } 1200 ot = dcommontype(s, ot, t); 1201 xt = ot - 3*widthptr; 1202 ot = dsymptr(s, ot, s, ot+widthptr+2*widthint); 1203 ot = duintxx(s, ot, n, widthint); 1204 ot = duintxx(s, ot, n, widthint); 1205 for(t1=t->type; t1!=T; t1=t1->down) { 1206 // ../../runtime/type.go:/structField 1207 if(t1->sym && !t1->embedded) { 1208 ot = dgostringptr(s, ot, t1->sym->name); 1209 if(exportname(t1->sym->name)) 1210 ot = dgostringptr(s, ot, nil); 1211 else 1212 ot = dgopkgpath(s, ot, t1->sym->pkg); 1213 } else { 1214 ot = dgostringptr(s, ot, nil); 1215 if(t1->type->sym != S && t1->type->sym->pkg == builtinpkg) 1216 ot = dgopkgpath(s, ot, localpkg); 1217 else 1218 ot = dgostringptr(s, ot, nil); 1219 } 1220 ot = dsymptr(s, ot, dtypesym(t1->type), 0); 1221 ot = dgostrlitptr(s, ot, t1->note); 1222 ot = duintptr(s, ot, t1->width); // field offset 1223 } 1224 break; 1225 } 1226 ot = dextratype(s, ot, t, xt); 1227 ggloblsym(s, ot, dupok|RODATA); 1228 1229 // generate typelink.foo pointing at s = type.foo. 1230 // The linker will leave a table of all the typelinks for 1231 // types in the binary, so reflect can find them. 1232 // We only need the link for unnamed composites that 1233 // we want be able to find. 1234 if(t->sym == S) { 1235 switch(t->etype) { 1236 case TARRAY: 1237 case TCHAN: 1238 case TMAP: 1239 slink = typelinksym(t); 1240 dsymptr(slink, 0, s, 0); 1241 ggloblsym(slink, widthptr, dupok|RODATA); 1242 } 1243 } 1244 1245 return s; 1246 } 1247 1248 void 1249 dumptypestructs(void) 1250 { 1251 int i; 1252 NodeList *l; 1253 Node *n; 1254 Type *t; 1255 Pkg *p; 1256 1257 // copy types from externdcl list to signatlist 1258 for(l=externdcl; l; l=l->next) { 1259 n = l->n; 1260 if(n->op != OTYPE) 1261 continue; 1262 signatlist = list(signatlist, n); 1263 } 1264 1265 // process signatlist 1266 for(l=signatlist; l; l=l->next) { 1267 n = l->n; 1268 if(n->op != OTYPE) 1269 continue; 1270 t = n->type; 1271 dtypesym(t); 1272 if(t->sym) 1273 dtypesym(ptrto(t)); 1274 } 1275 1276 // generate import strings for imported packages 1277 for(i=0; i<nelem(phash); i++) 1278 for(p=phash[i]; p; p=p->link) 1279 if(p->direct) 1280 dimportpath(p); 1281 1282 // do basic types if compiling package runtime. 1283 // they have to be in at least one package, 1284 // and runtime is always loaded implicitly, 1285 // so this is as good as any. 1286 // another possible choice would be package main, 1287 // but using runtime means fewer copies in .6 files. 1288 if(compiling_runtime) { 1289 for(i=1; i<=TBOOL; i++) 1290 dtypesym(ptrto(types[i])); 1291 dtypesym(ptrto(types[TSTRING])); 1292 dtypesym(ptrto(types[TUNSAFEPTR])); 1293 1294 // emit type structs for error and func(error) string. 1295 // The latter is the type of an auto-generated wrapper. 1296 dtypesym(ptrto(errortype)); 1297 dtypesym(functype(nil, 1298 list1(nod(ODCLFIELD, N, typenod(errortype))), 1299 list1(nod(ODCLFIELD, N, typenod(types[TSTRING]))))); 1300 1301 // add paths for runtime and main, which 6l imports implicitly. 1302 dimportpath(runtimepkg); 1303 if(flag_race) 1304 dimportpath(racepkg); 1305 dimportpath(mkpkg(strlit("main"))); 1306 } 1307 } 1308 1309 static Sym* 1310 dalgsym(Type *t) 1311 { 1312 int ot; 1313 Sym *s, *hash, *hashfunc, *eq, *eqfunc; 1314 1315 // dalgsym is only called for a type that needs an algorithm table, 1316 // which implies that the type is comparable (or else it would use ANOEQ). 1317 1318 s = typesymprefix(".alg", t); 1319 hash = typesymprefix(".hash", t); 1320 genhash(hash, t); 1321 eq = typesymprefix(".eq", t); 1322 geneq(eq, t); 1323 1324 // make Go funcs (closures) for calling hash and equal from Go 1325 hashfunc = typesymprefix(".hashfunc", t); 1326 dsymptr(hashfunc, 0, hash, 0); 1327 ggloblsym(hashfunc, widthptr, DUPOK|RODATA); 1328 eqfunc = typesymprefix(".eqfunc", t); 1329 dsymptr(eqfunc, 0, eq, 0); 1330 ggloblsym(eqfunc, widthptr, DUPOK|RODATA); 1331 1332 // ../../runtime/alg.go:/typeAlg 1333 ot = 0; 1334 ot = dsymptr(s, ot, hashfunc, 0); 1335 ot = dsymptr(s, ot, eqfunc, 0); 1336 1337 ggloblsym(s, ot, DUPOK|RODATA); 1338 return s; 1339 } 1340 1341 static int 1342 usegcprog(Type *t) 1343 { 1344 vlong size, nptr; 1345 1346 if(!haspointers(t)) 1347 return 0; 1348 if(t->width == BADWIDTH) 1349 dowidth(t); 1350 // Calculate size of the unrolled GC mask. 1351 nptr = (t->width+widthptr-1)/widthptr; 1352 size = nptr; 1353 if(size%2) 1354 size *= 2; // repeated 1355 size = size*gcBits/8; // 4 bits per word 1356 // Decide whether to use unrolled GC mask or GC program. 1357 // We could use a more elaborate condition, but this seems to work well in practice. 1358 // For small objects GC program can't give significant reduction. 1359 // While large objects usually contain arrays; and even if it don't 1360 // the program uses 2-bits per word while mask uses 4-bits per word, 1361 // so the program is still smaller. 1362 return size > 2*widthptr; 1363 } 1364 1365 // Generates sparse GC bitmask (4 bits per word). 1366 static void 1367 gengcmask(Type *t, uint8 gcmask[16]) 1368 { 1369 Bvec *vec; 1370 vlong xoffset, nptr, i, j; 1371 int half; 1372 uint8 bits, *pos; 1373 1374 memset(gcmask, 0, 16); 1375 if(!haspointers(t)) 1376 return; 1377 1378 // Generate compact mask as stacks use. 1379 xoffset = 0; 1380 vec = bvalloc(2*widthptr*8); 1381 twobitwalktype1(t, &xoffset, vec); 1382 1383 // Unfold the mask for the GC bitmap format: 1384 // 4 bits per word, 2 high bits encode pointer info. 1385 pos = (uint8*)gcmask; 1386 nptr = (t->width+widthptr-1)/widthptr; 1387 half = 0; 1388 // If number of words is odd, repeat the mask. 1389 // This makes simpler handling of arrays in runtime. 1390 for(j=0; j<=(nptr%2); j++) { 1391 for(i=0; i<nptr; i++) { 1392 bits = bvget(vec, i*BitsPerPointer) | bvget(vec, i*BitsPerPointer+1)<<1; 1393 // Some fake types (e.g. Hmap) has missing fileds. 1394 // twobitwalktype1 generates BitsDead for that holes, 1395 // replace BitsDead with BitsScalar. 1396 if(bits == BitsDead) 1397 bits = BitsScalar; 1398 bits <<= 2; 1399 if(half) 1400 bits <<= 4; 1401 *pos |= bits; 1402 half = !half; 1403 if(!half) 1404 pos++; 1405 } 1406 } 1407 } 1408 1409 // Helper object for generation of GC programs. 1410 typedef struct ProgGen ProgGen; 1411 struct ProgGen 1412 { 1413 Sym* s; 1414 int32 datasize; 1415 uint8 data[256/PointersPerByte]; 1416 vlong ot; 1417 }; 1418 1419 static void 1420 proggeninit(ProgGen *g, Sym *s) 1421 { 1422 g->s = s; 1423 g->datasize = 0; 1424 g->ot = 0; 1425 memset(g->data, 0, sizeof(g->data)); 1426 } 1427 1428 static void 1429 proggenemit(ProgGen *g, uint8 v) 1430 { 1431 g->ot = duint8(g->s, g->ot, v); 1432 } 1433 1434 // Emits insData block from g->data. 1435 static void 1436 proggendataflush(ProgGen *g) 1437 { 1438 int32 i, s; 1439 1440 if(g->datasize == 0) 1441 return; 1442 proggenemit(g, insData); 1443 proggenemit(g, g->datasize); 1444 s = (g->datasize + PointersPerByte - 1)/PointersPerByte; 1445 for(i = 0; i < s; i++) 1446 proggenemit(g, g->data[i]); 1447 g->datasize = 0; 1448 memset(g->data, 0, sizeof(g->data)); 1449 } 1450 1451 static void 1452 proggendata(ProgGen *g, uint8 d) 1453 { 1454 g->data[g->datasize/PointersPerByte] |= d << ((g->datasize%PointersPerByte)*BitsPerPointer); 1455 g->datasize++; 1456 if(g->datasize == 255) 1457 proggendataflush(g); 1458 } 1459 1460 // Skip v bytes due to alignment, etc. 1461 static void 1462 proggenskip(ProgGen *g, vlong off, vlong v) 1463 { 1464 vlong i; 1465 1466 for(i = off; i < off+v; i++) { 1467 if((i%widthptr) == 0) 1468 proggendata(g, BitsScalar); 1469 } 1470 } 1471 1472 // Emit insArray instruction. 1473 static void 1474 proggenarray(ProgGen *g, vlong len) 1475 { 1476 int32 i; 1477 1478 proggendataflush(g); 1479 proggenemit(g, insArray); 1480 for(i = 0; i < widthptr; i++, len >>= 8) 1481 proggenemit(g, len); 1482 } 1483 1484 static void 1485 proggenarrayend(ProgGen *g) 1486 { 1487 proggendataflush(g); 1488 proggenemit(g, insArrayEnd); 1489 } 1490 1491 static vlong 1492 proggenfini(ProgGen *g) 1493 { 1494 proggendataflush(g); 1495 proggenemit(g, insEnd); 1496 return g->ot; 1497 } 1498 1499 static void gengcprog1(ProgGen *g, Type *t, vlong *xoffset); 1500 1501 // Generates GC program for large types. 1502 static void 1503 gengcprog(Type *t, Sym **pgc0, Sym **pgc1) 1504 { 1505 Sym *gc0, *gc1; 1506 vlong nptr, size, ot, xoffset; 1507 ProgGen g; 1508 1509 nptr = (t->width+widthptr-1)/widthptr; 1510 size = nptr; 1511 if(size%2) 1512 size *= 2; // repeated twice 1513 size = size*PointersPerByte/8; // 4 bits per word 1514 size++; // unroll flag in the beginning, used by runtime (see runtime.markallocated) 1515 // emity space in BSS for unrolled program 1516 *pgc0 = S; 1517 // Don't generate it if it's too large, runtime will unroll directly into GC bitmap. 1518 if(size <= MaxGCMask) { 1519 gc0 = typesymprefix(".gc", t); 1520 ggloblsym(gc0, size, DUPOK|NOPTR); 1521 *pgc0 = gc0; 1522 } 1523 1524 // program in RODATA 1525 gc1 = typesymprefix(".gcprog", t); 1526 proggeninit(&g, gc1); 1527 xoffset = 0; 1528 gengcprog1(&g, t, &xoffset); 1529 ot = proggenfini(&g); 1530 ggloblsym(gc1, ot, DUPOK|RODATA); 1531 *pgc1 = gc1; 1532 } 1533 1534 // Recursively walks type t and writes GC program into g. 1535 static void 1536 gengcprog1(ProgGen *g, Type *t, vlong *xoffset) 1537 { 1538 vlong fieldoffset, i, o, n; 1539 Type *t1; 1540 1541 switch(t->etype) { 1542 case TINT8: 1543 case TUINT8: 1544 case TINT16: 1545 case TUINT16: 1546 case TINT32: 1547 case TUINT32: 1548 case TINT64: 1549 case TUINT64: 1550 case TINT: 1551 case TUINT: 1552 case TUINTPTR: 1553 case TBOOL: 1554 case TFLOAT32: 1555 case TFLOAT64: 1556 case TCOMPLEX64: 1557 case TCOMPLEX128: 1558 proggenskip(g, *xoffset, t->width); 1559 *xoffset += t->width; 1560 break; 1561 case TPTR32: 1562 case TPTR64: 1563 case TUNSAFEPTR: 1564 case TFUNC: 1565 case TCHAN: 1566 case TMAP: 1567 proggendata(g, BitsPointer); 1568 *xoffset += t->width; 1569 break; 1570 case TSTRING: 1571 proggendata(g, BitsPointer); 1572 proggendata(g, BitsScalar); 1573 *xoffset += t->width; 1574 break; 1575 case TINTER: 1576 // Assuming IfacePointerOnly=1. 1577 proggendata(g, BitsPointer); 1578 proggendata(g, BitsPointer); 1579 *xoffset += t->width; 1580 break; 1581 case TARRAY: 1582 if(isslice(t)) { 1583 proggendata(g, BitsPointer); 1584 proggendata(g, BitsScalar); 1585 proggendata(g, BitsScalar); 1586 } else { 1587 t1 = t->type; 1588 if(t1->width == 0) { 1589 // ignore 1590 } if(t->bound <= 1 || t->bound*t1->width < 32*widthptr) { 1591 for(i = 0; i < t->bound; i++) 1592 gengcprog1(g, t1, xoffset); 1593 } else if(!haspointers(t1)) { 1594 n = t->width; 1595 n -= -*xoffset&(widthptr-1); // skip to next ptr boundary 1596 proggenarray(g, (n+widthptr-1)/widthptr); 1597 proggendata(g, BitsScalar); 1598 proggenarrayend(g); 1599 *xoffset -= (n+widthptr-1)/widthptr*widthptr - t->width; 1600 } else { 1601 proggenarray(g, t->bound); 1602 gengcprog1(g, t1, xoffset); 1603 *xoffset += (t->bound-1)*t1->width; 1604 proggenarrayend(g); 1605 } 1606 } 1607 break; 1608 case TSTRUCT: 1609 o = 0; 1610 for(t1 = t->type; t1 != T; t1 = t1->down) { 1611 fieldoffset = t1->width; 1612 proggenskip(g, *xoffset, fieldoffset - o); 1613 *xoffset += fieldoffset - o; 1614 gengcprog1(g, t1->type, xoffset); 1615 o = fieldoffset + t1->type->width; 1616 } 1617 proggenskip(g, *xoffset, t->width - o); 1618 *xoffset += t->width - o; 1619 break; 1620 default: 1621 fatal("gengcprog1: unexpected type, %T", t); 1622 } 1623 }