1 /** 2 * Compiler implementation of the 3 * $(LINK2 http://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (C) 1984-1995 by Symantec 6 * Copyright (C) 2000-2020 by The D Language Foundation, All Rights Reserved 7 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 8 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 9 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/dcgcv.d, backend/dcgcv.d) 10 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/backend/dcgcv.d 11 */ 12 13 module dmd.backend.dcgcv; 14 15 version (Windows) 16 { 17 version (SCPP) 18 version = COMPILE; 19 version (MARS) 20 version = COMPILE; 21 } 22 23 version (COMPILE) 24 { 25 26 import core.stdc.stdio; 27 import core.stdc.stdlib; 28 import core.stdc..string; 29 30 import dmd.backend.cc; 31 import dmd.backend.cdef; 32 import dmd.backend.cgcv; 33 import dmd.backend.code; 34 import dmd.backend.code_x86; 35 import dmd.backend.cv4; 36 import dmd.backend.dlist; 37 import dmd.backend.dvec; 38 import dmd.backend.el; 39 import dmd.backend.global; 40 import dmd.backend.mem; 41 import dmd.backend.obj; 42 import dmd.backend.outbuf; 43 import dmd.backend.ty; 44 import dmd.backend.type; 45 46 import dmd.backend.barray; 47 48 version (SCPP) 49 { 50 import cpp; 51 import msgs2; 52 import parser; 53 } 54 version (MARS) 55 { 56 import dmd.backend.dvarstats; 57 } 58 59 extern (C++): 60 61 nothrow: 62 63 enum SYMDEB_TDB = false; 64 65 extern (C) void TOOFFSET(void* p, targ_size_t value) 66 { 67 switch (_tysize[TYnptr]) 68 { 69 case 2: *cast(ushort*)p = cast(ushort)value; break; 70 case 4: *cast(uint*) p = cast(uint) value; break; 71 case 8: *cast(ulong*) p = cast(ulong) value; break; 72 default: 73 assert(0); 74 } 75 } 76 77 extern __gshared char* ftdbname; 78 79 // Convert from SFL protections to CV4 protections 80 uint SFLtoATTR(uint sfl) { return 4 - ((sfl & SFLpmask) >> 5); } 81 82 __gshared 83 { 84 85 /* Dynamic array of debtyp_t's */ 86 private Barray!(debtyp_t*) debtyp; 87 88 private vec_t debtypvec; // vector of used entries 89 enum DEBTYPVECDIM = 16001; //8009 //3001 // dimension of debtypvec (should be prime) 90 91 enum DEBTYPHASHDIM = 1009; 92 private uint[DEBTYPHASHDIM] debtyphash; 93 94 private Outbuffer *reset_symbuf; // Keep pointers to reset symbols 95 96 idx_t DEB_NULL() { return cgcv.deb_offset; } // index of null debug type record 97 98 /* This limitation is because of 4K page sizes 99 * in optlink/cv/cvhashes.asm 100 */ 101 enum CVIDMAX = (0xFF0-20); // the -20 is picked by trial and error 102 103 enum LOCATsegrel = 0xC000; 104 105 /* Unfortunately, the fixup stuff is different for EASY OMF and Microsoft */ 106 enum EASY_LCFDoffset = (LOCATsegrel | 0x1404); 107 enum EASY_LCFDpointer = (LOCATsegrel | 0x1800); 108 109 enum LCFD32offset = (LOCATsegrel | 0x2404); 110 enum LCFD32pointer = (LOCATsegrel | 0x2C00); 111 enum LCFD16pointer = (LOCATsegrel | 0x0C00); 112 113 version (MARS) 114 extern Cgcv cgcv; // already declared in cgcv.d 115 else 116 Cgcv cgcv; 117 118 } 119 120 version (MARS) 121 enum MARS = true; 122 else 123 enum MARS = false; 124 125 /****************************************** 126 * Return number of bytes consumed in OBJ file by a name. 127 */ 128 129 int cv_stringbytes(const(char)* name) 130 { 131 int len = cast(int)strlen(name); 132 if (config.fulltypes == CV8) 133 return len + 1; 134 if (len > CVIDMAX) 135 len = CVIDMAX; 136 return len + ((len > 255) ? 4 : 1); 137 } 138 139 /****************************************** 140 * Stuff a namestring into p. 141 * Returns: 142 * number of bytes consumed 143 */ 144 145 int cv_namestring(ubyte *p, const(char)* name, int length = -1) 146 { 147 size_t len = (length >= 0) ? length : strlen(name); 148 if (config.fulltypes == CV8) 149 { 150 size_t numBytesWritten = len + ((length < 0) ? 1 : 0); 151 memcpy(p, name, numBytesWritten); 152 if(config.flags2 & CFG2gms) 153 { 154 for(int i = 0; i < len; i++) 155 { 156 if(p[i] == '.') 157 p[i] = '@'; 158 } 159 } 160 return cast(int)numBytesWritten; 161 } 162 if (len > 255) 163 { p[0] = 0xFF; 164 p[1] = 0; 165 if (len > CVIDMAX) 166 len = CVIDMAX; 167 TOWORD(p + 2,cast(uint)len); 168 memcpy(p + 4,name,len); 169 len += 4; 170 } 171 else 172 { p[0] = cast(ubyte)len; 173 memcpy(p + 1,name,len); 174 len++; 175 } 176 return cast(int)len; 177 } 178 179 /*********************************** 180 * Compute debug register number for symbol s. 181 * Returns: 182 * 0..7 byte registers 183 * 8..15 word registers 184 * 16..23 dword registers 185 */ 186 187 private int cv_regnum(Symbol *s) 188 { 189 uint reg = s.Sreglsw; 190 if (s.Sclass == SCpseudo) 191 { 192 version (SCPP) 193 reg = pseudoreg[reg]; 194 } 195 else 196 { 197 assert(reg < 8); 198 assert(s.Sfl == FLreg); 199 switch (type_size(s.Stype)) 200 { 201 case LONGSIZE: 202 case 3: reg += 8; 203 goto case; 204 205 case SHORTSIZE: reg += 8; 206 goto case; 207 208 case CHARSIZE: break; 209 210 case LLONGSIZE: 211 reg += (s.Sregmsw << 8) + (16 << 8) + 16; 212 if (config.fulltypes == CV4) 213 reg += (1 << 8); 214 break; 215 216 default: 217 static if (0) 218 { 219 symbol_print(s); 220 type_print(s.Stype); 221 printf("size = %d\n",type_size(s.Stype)); 222 } 223 assert(0); 224 } 225 } 226 if (config.fulltypes == CV4) 227 reg++; 228 return reg; 229 } 230 231 /*********************************** 232 * Allocate a debtyp_t. 233 */ 234 235 debtyp_t * debtyp_alloc(uint length) 236 { 237 debtyp_t *d; 238 uint pad = 0; 239 240 //printf("len = %u, x%x\n", length, length); 241 if (config.fulltypes == CV8) 242 { // length+2 must lie on 4 byte boundary 243 pad = ((length + 2 + 3) & ~3) - (length + 2); 244 length += pad; 245 } 246 247 length < 0x10000 || assert(0); 248 const len = debtyp_t.sizeof - (d.data).sizeof + length; 249 debug 250 { 251 d = cast(debtyp_t *) mem_malloc(len /*+ 1*/); 252 memset(d, 0xAA, len); 253 // (cast(char*)d)[len] = 0x2E; 254 } 255 else 256 { 257 d = cast(debtyp_t *) malloc(debtyp_t.sizeof - (d.data).sizeof + length); 258 } 259 d.length = cast(ushort)length; 260 if (pad) 261 { 262 __gshared const ubyte[3] padx = [0xF3, 0xF2, 0xF1]; 263 memcpy(d.data.ptr + length - pad, padx.ptr + 3 - pad, pad); 264 } 265 //printf("debtyp_alloc(%d) = %p\n", length, d); 266 return d; 267 } 268 269 /*********************************** 270 * Free a debtyp_t. 271 */ 272 273 private void debtyp_free(debtyp_t *d) 274 { 275 //printf("debtyp_free(length = %d, %p)\n", d.length, d); 276 //fflush(stdout); 277 debug 278 { 279 assert(d.length < 0x10000); 280 uint len = debtyp_t.sizeof - (d.data).sizeof + d.length; 281 // assert((cast(char*)d)[len] == 0x2E); 282 memset(d, 0x55, len); 283 mem_free(d); 284 } 285 else 286 { 287 free(d); 288 } 289 } 290 291 static if (0) 292 { 293 void debtyp_check(debtyp_t *d,int linnum) 294 { int i; 295 __gshared char c; 296 297 //printf("linnum = %d\n",linnum); 298 //printf(" length = %d\n",d.length); 299 for (i = 0; i < d.length; i++) 300 c = d.data.ptr[i]; 301 } 302 303 void debtyp_check(debtyp_t* d) { debtyp_check(d,__LINE__); } 304 } 305 else 306 { 307 void debtyp_check(debtyp_t* d) { } 308 } 309 310 /*********************************** 311 * Search for debtyp_t in debtyp[]. If it is there, return the index 312 * of it, and free d. Otherwise, add it. 313 * Returns: 314 * index in debtyp[] 315 */ 316 317 idx_t cv_debtyp(debtyp_t *d) 318 { 319 ushort length; 320 uint hashi; 321 322 assert(d); 323 length = d.length; 324 //printf("length = %3d\n",length); 325 static if (SYMDEB_TDB) 326 { 327 if (config.fulltypes == CVTDB) 328 { 329 idx_t result; 330 331 static if (1) 332 { 333 assert(length); 334 debtyp_check(d); 335 result = tdb_typidx(&d.length); 336 } 337 else 338 { 339 ubyte *buf; 340 341 // Allocate buffer 342 buf = malloc(6 + length); 343 if (!buf) 344 err_nomem(); // out of memory 345 346 // Fill the buffer 347 TOLONG(buf,cgcv.signature); 348 memcpy(buf + 4,cast(char *)d + uint.sizeof,2 + length); 349 350 static if (0) 351 { 352 {int i; 353 for (i=0;i<length;i++) 354 printf("%02x ",buf[6+i]); 355 printf("\n"); 356 } 357 } 358 result = tdb_typidx(buf,6 + length); 359 } 360 //printf("result = x%x\n",result); 361 debtyp_free(d); 362 return result; 363 } 364 } 365 if (length) 366 { uint hash; 367 368 hash = length; 369 if (length >= uint.sizeof) 370 { 371 // Hash consists of the sum of the first 4 bytes with the last 4 bytes 372 union U { ubyte* cp; uint* up; } 373 U un = void; 374 un.cp = d.data.ptr; 375 hash += *un.up; 376 un.cp += length - uint.sizeof; 377 hash += *un.up; 378 } 379 hashi = hash % DEBTYPHASHDIM; 380 hash %= DEBTYPVECDIM; 381 //printf(" hashi = %d", hashi); 382 383 if (vec_testbit(hash,debtypvec)) 384 { 385 //printf(" test"); 386 // Threaded list is much faster 387 for (uint u = debtyphash[hashi]; u; u = debtyp[u].prev) 388 //for (uint u = debtyp.length; u--; ) 389 { 390 if (length == debtyp[u].length && 391 memcmp(d.data.ptr,debtyp[u].data.ptr,length) == 0) 392 { debtyp_free(d); 393 //printf(" match %d\n",u); 394 return u + cgcv.deb_offset; 395 } 396 } 397 } 398 else 399 vec_setbit(hash,debtypvec); 400 } 401 else 402 hashi = 1; 403 //printf(" add %d\n",debtyp.length); 404 d.prev = debtyphash[hashi]; 405 debtyphash[hashi] = cast(uint)debtyp.length; 406 407 /* It's not already in the array, so add it */ 408 debtyp.push(d); 409 version (SCPP) 410 { 411 if (debtyp.length >= 0xE000) 412 err_fatal(EM_2manytypes,0xE000); // too many types 413 } 414 415 return cast(uint)debtyp.length - 1 + cgcv.deb_offset; 416 } 417 418 idx_t cv_numdebtypes() 419 { 420 return cast(idx_t)debtyp.length; 421 } 422 423 /**************************** 424 * Store a null record at DEB_NULL. 425 */ 426 427 void cv_init() 428 { debtyp_t *d; 429 430 //printf("cv_init()\n"); 431 432 // Initialize statics 433 debtyp.setLength(0); 434 if (!ftdbname) 435 ftdbname = cast(char *)"symc.tdb".ptr; 436 437 memset(&cgcv,0,cgcv.sizeof); 438 cgcv.sz_idx = 2; 439 cgcv.LCFDoffset = LCFD32offset; 440 cgcv.LCFDpointer = LCFD16pointer; 441 442 debtypvec = vec_calloc(DEBTYPVECDIM); 443 memset(debtyphash.ptr,0,debtyphash.sizeof); 444 445 if (reset_symbuf) 446 { 447 Symbol **p = cast(Symbol **)reset_symbuf.buf; 448 const size_t n = reset_symbuf.length() / (Symbol *).sizeof; 449 for (size_t i = 0; i < n; ++i) 450 symbol_reset(p[i]); 451 reset_symbuf.reset(); 452 } 453 else 454 { 455 reset_symbuf = cast(Outbuffer*) calloc(1, Outbuffer.sizeof); 456 assert(reset_symbuf); 457 reset_symbuf.reserve(10 * (Symbol*).sizeof); 458 } 459 460 /* Reset for different OBJ file formats */ 461 if (I32 || I64) 462 { 463 // Adjust values in old CV tables for 32 bit ints 464 dttab[TYenum] = dttab[TYlong]; 465 dttab[TYint] = dttab[TYlong]; 466 dttab[TYuint] = dttab[TYulong]; 467 468 // Adjust Codeview 4 values for 32 bit ints and 32 bit pointer offsets 469 dttab4[TYenum] = 0x74; 470 dttab4[TYint] = 0x74; 471 dttab4[TYuint] = 0x75; 472 if (I64) 473 { 474 dttab4[TYptr] = 0x600; 475 dttab4[TYnptr] = 0x600; 476 dttab4[TYsptr] = 0x600; 477 dttab4[TYimmutPtr] = 0x600; 478 dttab4[TYsharePtr] = 0x600; 479 dttab4[TYrestrictPtr] = 0x600; 480 dttab4[TYfgPtr] = 0x600; 481 } 482 else 483 { 484 dttab4[TYptr] = 0x400; 485 dttab4[TYsptr] = 0x400; 486 dttab4[TYnptr] = 0x400; 487 dttab4[TYimmutPtr] = 0x400; 488 dttab4[TYsharePtr] = 0x400; 489 dttab4[TYrestrictPtr] = 0x400; 490 dttab4[TYfgPtr] = 0x400; 491 } 492 dttab4[TYcptr] = 0x400; 493 dttab4[TYfptr] = 0x500; 494 495 if (config.flags & CFGeasyomf) 496 { cgcv.LCFDoffset = EASY_LCFDoffset; 497 cgcv.LCFDpointer = EASY_LCFDpointer; 498 assert(config.fulltypes == CVOLD); 499 } 500 else 501 cgcv.LCFDpointer = LCFD32pointer; 502 503 if (config.exe & EX_flat) 504 cgcv.FD_code = 0x10; 505 } 506 507 if (config.fulltypes >= CV4) 508 { int flags; 509 __gshared ushort[5] memmodel = [0,0x100,0x20,0x120,0x120]; 510 char[1 + (VERSION).sizeof] version_; 511 ubyte[8 + (version_).sizeof] debsym; 512 513 // Put out signature indicating CV4 format 514 switch (config.fulltypes) 515 { 516 case CV4: 517 cgcv.signature = 1; 518 break; 519 520 case CV8: 521 cgcv.signature = 4; 522 break; 523 524 default: 525 { const(char)* x = "1MYS"; 526 cgcv.signature = *cast(int *) x; 527 break; 528 } 529 } 530 531 cgcv.deb_offset = 0x1000; 532 533 if (config.fulltypes == CV8) 534 { cgcv.sz_idx = 4; 535 return; // figure out rest later 536 } 537 538 if (config.fulltypes >= CVSYM) 539 { cgcv.sz_idx = 4; 540 if (!(config.flags2 & CFG2phgen)) 541 cgcv.deb_offset = 0x80000000; 542 } 543 544 objmod.write_bytes(SegData[DEBSYM],4,&cgcv.signature); 545 546 // Allocate an LF_ARGLIST with no arguments 547 if (config.fulltypes == CV4) 548 { d = debtyp_alloc(4); 549 TOWORD(d.data.ptr,LF_ARGLIST); 550 TOWORD(d.data.ptr + 2,0); 551 } 552 else 553 { d = debtyp_alloc(6); 554 TOWORD(d.data.ptr,LF_ARGLIST); 555 TOLONG(d.data.ptr + 2,0); 556 } 557 558 // Put out S_COMPILE record 559 TOWORD(debsym.ptr + 2,S_COMPILE); 560 switch (config.target_cpu) 561 { 562 case TARGET_8086: debsym[4] = 0; break; 563 case TARGET_80286: debsym[4] = 2; break; 564 case TARGET_80386: debsym[4] = 3; break; 565 case TARGET_80486: debsym[4] = 4; break; 566 567 case TARGET_Pentium: 568 case TARGET_PentiumMMX: 569 debsym[4] = 5; break; 570 571 case TARGET_PentiumPro: 572 case TARGET_PentiumII: 573 debsym[4] = 6; break; 574 default: assert(0); 575 } 576 debsym[5] = (CPP != 0); // 0==C, 1==C++ 577 flags = (config.inline8087) ? (0<<3) : (1<<3); 578 if (I32) 579 flags |= 0x80; // 32 bit addresses 580 flags |= memmodel[config.memmodel]; 581 TOWORD(debsym.ptr + 6,flags); 582 version_[0] = 'Z'; 583 strcpy(version_.ptr + 1,VERSION); 584 cv_namestring(debsym.ptr + 8,version_.ptr); 585 TOWORD(debsym.ptr,6 + (version_).sizeof); 586 objmod.write_bytes(SegData[DEBSYM],8 + (version_).sizeof,debsym.ptr); 587 588 static if (SYMDEB_TDB) 589 { 590 // Put out S_TDBNAME record 591 if (config.fulltypes == CVTDB) 592 { 593 ubyte[50] buf = void; 594 595 pstate.STtdbtimestamp = tdb_gettimestamp(); 596 size_t len = cv_stringbytes(ftdbname); 597 ubyte *ds = (8 + len <= buf.sizeof) ? buf : cast(ubyte *) malloc(8 + len); 598 assert(ds); 599 TOWORD(ds,6 + len); 600 TOWORD(ds + 2,S_TDBNAME); 601 TOLONG(ds + 4,pstate.STtdbtimestamp); 602 cv_namestring(ds + 8,ftdbname); 603 objmod.write_bytes(SegData[DEBSYM],8 + len,ds); 604 if (ds != buf) 605 free(ds); 606 } 607 } 608 } 609 else 610 { 611 assert(0); 612 } 613 if (config.fulltypes == CVTDB) 614 cgcv.deb_offset = cv_debtyp(d); 615 else 616 cv_debtyp(d); 617 } 618 619 /////////////////////////// CodeView 4 /////////////////////////////// 620 621 /*********************************** 622 * Return number of bytes required to store a numeric leaf. 623 */ 624 625 uint cv4_numericbytes(uint value) 626 { uint u; 627 628 if (value < 0x8000) 629 u = 2; 630 else if (value < 0x10000) 631 u = 4; 632 else 633 u = 6; 634 return u; 635 } 636 637 /******************************** 638 * Store numeric leaf. 639 * Must use exact same number of bytes as cv4_numericbytes(). 640 */ 641 642 void cv4_storenumeric(ubyte *p, uint value) 643 { 644 if (value < 0x8000) 645 TOWORD(p,value); 646 else if (value < 0x10000) 647 { TOWORD(p,LF_USHORT); 648 p += 2; 649 TOWORD(p,value); 650 } 651 else 652 { TOWORD(p,LF_ULONG); 653 *cast(targ_ulong *)(p + 2) = cast(uint) value; 654 } 655 } 656 657 /*********************************** 658 * Return number of bytes required to store a signed numeric leaf. 659 * Params: 660 * value = value to store 661 * Returns: 662 * number of bytes required for storing value 663 */ 664 uint cv4_signednumericbytes(int value) 665 { 666 uint u; 667 if (value >= 0 && value < 0x8000) 668 u = 2; 669 else if (value == cast(short)value) 670 u = 4; 671 else 672 u = 6; 673 return u; 674 } 675 676 /******************************** 677 * Store signed numeric leaf. 678 * Must use exact same number of bytes as cv4_signednumericbytes(). 679 * Params: 680 * p = address where to store value 681 * value = value to store 682 */ 683 void cv4_storesignednumeric(ubyte *p, int value) 684 { 685 if (value >= 0 && value < 0x8000) 686 TOWORD(p, value); 687 else if (value == cast(short)value) 688 { 689 TOWORD(p, LF_SHORT); 690 TOWORD(p + 2, value); 691 } 692 else 693 { 694 TOWORD(p,LF_LONG); 695 TOLONG(p + 2, value); 696 } 697 } 698 699 /********************************* 700 * Generate a type index for a parameter list. 701 */ 702 703 idx_t cv4_arglist(type *t,uint *pnparam) 704 { uint u; 705 uint nparam; 706 idx_t paramidx; 707 debtyp_t *d; 708 param_t *p; 709 710 // Compute nparam, number of parameters 711 nparam = 0; 712 for (p = t.Tparamtypes; p; p = p.Pnext) 713 nparam++; 714 *pnparam = nparam; 715 716 // Construct an LF_ARGLIST of those parameters 717 if (nparam == 0) 718 { 719 if (config.fulltypes == CV8) 720 { 721 d = debtyp_alloc(2 + 4 + 4); 722 TOWORD(d.data.ptr,LF_ARGLIST_V2); 723 TOLONG(d.data.ptr + 2,1); 724 TOLONG(d.data.ptr + 6,0); 725 paramidx = cv_debtyp(d); 726 } 727 else 728 paramidx = DEB_NULL; 729 } 730 else 731 { 732 switch (config.fulltypes) 733 { 734 case CV8: 735 d = debtyp_alloc(2 + 4 + nparam * 4); 736 TOWORD(d.data.ptr,LF_ARGLIST_V2); 737 TOLONG(d.data.ptr + 2,nparam); 738 739 p = t.Tparamtypes; 740 for (u = 0; u < nparam; u++) 741 { TOLONG(d.data.ptr + 6 + u * 4,cv4_typidx(p.Ptype)); 742 p = p.Pnext; 743 } 744 break; 745 746 case CV4: 747 d = debtyp_alloc(2 + 2 + nparam * 2); 748 TOWORD(d.data.ptr,LF_ARGLIST); 749 TOWORD(d.data.ptr + 2,nparam); 750 751 p = t.Tparamtypes; 752 for (u = 0; u < nparam; u++) 753 { TOWORD(d.data.ptr + 4 + u * 2,cv4_typidx(p.Ptype)); 754 p = p.Pnext; 755 } 756 break; 757 758 default: 759 d = debtyp_alloc(2 + 4 + nparam * 4); 760 TOWORD(d.data.ptr,LF_ARGLIST); 761 TOLONG(d.data.ptr + 2,nparam); 762 763 p = t.Tparamtypes; 764 for (u = 0; u < nparam; u++) 765 { TOLONG(d.data.ptr + 6 + u * 4,cv4_typidx(p.Ptype)); 766 p = p.Pnext; 767 } 768 break; 769 } 770 paramidx = cv_debtyp(d); 771 } 772 return paramidx; 773 } 774 775 /***************************** 776 * Build LF_METHODLIST for overloaded member function. 777 * Output: 778 * *pcount # of entries in method list 779 * Returns: 780 * type index of method list 781 * 0 don't do this one 782 */ 783 784 version (SCPP) 785 { 786 787 private int cv4_methodlist(Symbol *sf,int *pcount) 788 { int count; 789 int mlen; 790 Symbol *s; 791 debtyp_t *d; 792 ubyte *p; 793 ushort attribute; 794 795 symbol_debug(sf); 796 797 // First, compute how big the method list is 798 count = 0; 799 mlen = 2; 800 for (s = sf; s; s = s.Sfunc.Foversym) 801 { 802 if (s.Sclass == SCtypedef || s.Sclass == SCfunctempl) 803 continue; 804 if (s.Sfunc.Fflags & Fnodebug) 805 continue; 806 if (s.Sfunc.Fflags & Fintro) 807 mlen += 4; 808 mlen += cgcv.sz_idx * 2; 809 count++; 810 } 811 812 if (!count) 813 return 0; 814 815 // Allocate and fill it in 816 d = debtyp_alloc(mlen); 817 p = d.data.ptr; 818 TOWORD(p,LF_METHODLIST); 819 p += 2; 820 for (s = sf; s; s = s.Sfunc.Foversym) 821 { 822 if (s.Sclass == SCtypedef || s.Sclass == SCfunctempl) 823 continue; 824 if (s.Sfunc.Fflags & Fnodebug) 825 continue; 826 attribute = cast(ushort)SFLtoATTR(s.Sflags); 827 // Make sure no overlapping bits 828 assert((Fvirtual | Fpure | Fintro | Fstatic) == (Fvirtual ^ Fpure ^ Fintro ^ Fstatic)); 829 switch ((s.Sfunc.Fflags & (Fvirtual | Fstatic)) | 830 (s.Sfunc.Fflags & (Fpure | Fintro))) 831 { 832 // BUG: should we have 0x0C, friend functions? 833 case Fstatic: attribute |= 0x08; break; 834 case Fvirtual: attribute |= 0x04; break; 835 case Fvirtual | Fintro: attribute |= 0x10; break; 836 case Fvirtual | Fpure: attribute |= 0x14; break; 837 case Fvirtual | Fintro | Fpure: attribute |= 0x18; break; 838 839 case 0: 840 break; 841 842 default: 843 symbol_print(s); 844 assert(0); 845 } 846 TOIDX(p,attribute); 847 p += cgcv.sz_idx; 848 TOIDX(p,cv4_symtypidx(s)); 849 p += cgcv.sz_idx; 850 if (s.Sfunc.Fflags & Fintro) 851 { TOLONG(p,cpp_vtbloffset(cast(Classsym *)s.Sscope,s)); 852 p += 4; 853 } 854 } 855 assert(p - d.data.ptr == mlen); 856 857 *pcount = count; 858 return cv_debtyp(d); 859 } 860 861 } 862 863 /********************************** 864 * Pretty-print indentifier for CV4 types. 865 */ 866 867 version (SCPP) 868 { 869 870 private const(char)* cv4_prettyident(Symbol *s) 871 { Symbol *stmp; 872 873 stmp = s.Sscope; 874 s.Sscope = null; // trick cpp_prettyident into leaving off :: 875 const p = cpp_prettyident(s); 876 s.Sscope = cast(Classsym *)stmp; 877 return p; 878 } 879 880 } 881 882 /**************************** 883 * Return type index of struct. 884 * Input: 885 * s struct tag symbol 886 * flags 887 * 0 generate a reference to s 888 * 1 just saw the definition of s 889 * 2 saw key function for class s 890 * 3 no longer have a key function for class s 891 */ 892 893 idx_t cv4_struct(Classsym *s,int flags) 894 { targ_size_t size; 895 debtyp_t* d,dt; 896 uint len; 897 uint nfields,fnamelen; 898 idx_t typidx; 899 type *t; 900 struct_t *st; 901 const(char)* id; 902 version (SCPP) 903 { 904 baseclass_t *b; 905 } 906 uint numidx; 907 uint leaf; 908 uint property; 909 uint attribute; 910 ubyte *p; 911 int refonly; 912 int i; 913 int count; // COUNT field in LF_CLASS 914 915 symbol_debug(s); 916 assert(config.fulltypes >= CV4); 917 st = s.Sstruct; 918 if (st.Sflags & STRanonymous) // if anonymous class/union 919 return 0; 920 921 //printf("cv4_struct(%s,%d)\n",s.Sident.ptr,flags); 922 t = s.Stype; 923 //printf("t = %p, Tflags = x%x\n", t, t.Tflags); 924 type_debug(t); 925 926 // Determine if we should do a reference or a definition 927 refonly = 1; // assume reference only 928 if (MARS || t.Tflags & TFsizeunknown || st.Sflags & STRoutdef) 929 { 930 //printf("ref only\n"); 931 } 932 else 933 { 934 // We have a definition that we have not put out yet 935 switch (flags) 936 { 937 case 0: // reference to s 938 version (SCPP) 939 { 940 if (!CPP || 941 config.flags2 & (CFG2fulltypes | CFG2hdrdebug) || 942 !(st.Sflags & STRvtblext)) 943 refonly = 0; 944 } 945 else 946 { 947 refonly = 0; 948 } 949 break; 950 951 case 1: // saw def of s 952 if (!s.Stypidx) // if not forward referenced 953 return 0; 954 version (SCPP) 955 { 956 if (!CPP || 957 config.flags2 & CFG2fulltypes || 958 !(st.Sflags & STRvtblext)) 959 refonly = 0; 960 } 961 break; 962 963 version (SCPP) 964 { 965 case 2: // saw key func for s 966 if (config.flags2 & CFG2fulltypes) 967 return 0; 968 refonly = 0; 969 break; 970 971 case 3: // no longer have key func for s 972 if (!s.Stypidx || config.flags2 & CFG2fulltypes) 973 return 0; 974 refonly = 0; 975 break; 976 } 977 default: 978 assert(0); 979 } 980 } 981 982 if (MARS || refonly) 983 { 984 if (s.Stypidx) // if reference already generated 985 { //assert(s.Stypidx - cgcv.deb_offset < debtyp.length); 986 return s.Stypidx; // use already existing reference 987 } 988 size = 0; 989 property = 0x80; // class is forward referenced 990 } 991 else 992 { size = type_size(t); 993 st.Sflags |= STRoutdef; 994 property = 0; 995 } 996 997 version (SCPP) 998 { 999 if (CPP) 1000 { 1001 if (s.Sscope) // if class is nested 1002 property |= 8; 1003 if (st.Sctor || st.Sdtor) 1004 property |= 2; // class has ctors and/or dtors 1005 if (st.Sopoverload) 1006 property |= 4; // class has overloaded operators 1007 if (st.Scastoverload) 1008 property |= 0x40; // class has casting methods 1009 if (st.Sopeq && !(st.Sopeq.Sfunc.Fflags & Fnodebug)) 1010 property |= 0x20; // class has overloaded assignment 1011 } 1012 } 1013 id = prettyident(s); 1014 if (config.fulltypes == CV4) 1015 { numidx = (st.Sflags & STRunion) ? 8 : 12; 1016 len = numidx + cv4_numericbytes(cast(uint)size); 1017 d = debtyp_alloc(len + cv_stringbytes(id)); 1018 cv4_storenumeric(d.data.ptr + numidx,cast(uint)size); 1019 } 1020 else 1021 { numidx = (st.Sflags & STRunion) ? 10 : 18; 1022 len = numidx + 4; 1023 d = debtyp_alloc(len + cv_stringbytes(id)); 1024 TOLONG(d.data.ptr + numidx,cast(uint)size); 1025 } 1026 len += cv_namestring(d.data.ptr + len,id); 1027 switch (s.Sclass) 1028 { 1029 case SCstruct: 1030 leaf = LF_STRUCTURE; 1031 if (st.Sflags & STRunion) 1032 { leaf = LF_UNION; 1033 break; 1034 } 1035 if (st.Sflags & STRclass) 1036 leaf = LF_CLASS; 1037 goto L1; 1038 L1: 1039 if (config.fulltypes == CV4) 1040 TOWORD(d.data.ptr + 8,0); // dList 1041 else 1042 TOLONG(d.data.ptr + 10,0); // dList 1043 if (CPP) 1044 { 1045 version (SCPP) 1046 { 1047 debtyp_t *vshape; 1048 ubyte descriptor; 1049 1050 const n = list_nitems(st.Svirtual); 1051 if (n == 0) // if no virtual functions 1052 { 1053 if (config.fulltypes == CV4) 1054 TOWORD(d.data.ptr + 10,0); // vshape is 0 1055 else 1056 TOLONG(d.data.ptr + 14,0); // vshape is 0 1057 } 1058 else 1059 { 1060 vshape = debtyp_alloc(4 + (n + 1) / 2); 1061 TOWORD(vshape.data.ptr,LF_VTSHAPE); 1062 TOWORD(vshape.data.ptr + 2,1); 1063 1064 uint n2 = 0; 1065 descriptor = 0; 1066 foreach (vl; ListRange(st.Svirtual)) 1067 { mptr_t *m; 1068 tym_t ty; 1069 1070 m = list_mptr(vl); 1071 symbol_debug(m.MPf); 1072 ty = tybasic(m.MPf.ty()); 1073 assert(tyfunc(ty)); 1074 if (_tysize[TYint] == 4) 1075 descriptor |= 5; 1076 if (tyfarfunc(ty)) 1077 descriptor++; 1078 vshape.data.ptr[4 + n2 / 2] = descriptor; 1079 descriptor <<= 4; 1080 n2++; 1081 } 1082 if (config.fulltypes == CV4) 1083 TOWORD(d.data.ptr + 10,cv_debtyp(vshape)); // vshape 1084 else 1085 TOLONG(d.data.ptr + 14,cv_debtyp(vshape)); // vshape 1086 } 1087 } 1088 } 1089 else 1090 { 1091 if (config.fulltypes == CV4) 1092 TOWORD(d.data.ptr + 10,0); // vshape 1093 else 1094 TOLONG(d.data.ptr + 14,0); // vshape 1095 } 1096 break; 1097 1098 default: 1099 symbol_print(s); 1100 assert(0); 1101 } 1102 TOWORD(d.data.ptr,leaf); 1103 1104 // Assign a number to prevent infinite recursion if a struct member 1105 // references the same struct. 1106 if (config.fulltypes == CVTDB) 1107 { 1108 static if (SYMDEB_TDB) 1109 { 1110 TOWORD(d.data.ptr + 2,0); // number of fields 1111 TOLONG(d.data.ptr + 6,0); // field list is 0 1112 TOWORD(d.data.ptr + 4,property | 0x80); // set fwd ref bit 1113 static if (0) 1114 { 1115 printf("fwd struct ref\n"); 1116 {int i; 1117 printf("len = %d, length = %d\n",len,d.length); 1118 for (i=0;i<d.length;i++) 1119 printf("%02x ",d.data.ptr[i]); 1120 printf("\n"); 1121 } 1122 } 1123 debtyp_check(d); 1124 s.Stypidx = tdb_typidx(&d.length); // forward reference it 1125 } 1126 } 1127 else 1128 { 1129 d.length = 0; // so cv_debtyp() will allocate new 1130 s.Stypidx = cv_debtyp(d); 1131 d.length = cast(ushort)len; // restore length 1132 } 1133 reset_symbuf.write((&s)[0 .. 1]); 1134 1135 if (refonly) // if reference only 1136 { 1137 //printf("refonly\n"); 1138 TOWORD(d.data.ptr + 2,0); // count: number of fields is 0 1139 if (config.fulltypes == CV4) 1140 { TOWORD(d.data.ptr + 4,0); // field list is 0 1141 TOWORD(d.data.ptr + 6,property); 1142 } 1143 else 1144 { TOLONG(d.data.ptr + 6,0); // field list is 0 1145 TOWORD(d.data.ptr + 4,property); 1146 } 1147 return s.Stypidx; 1148 } 1149 1150 version (MARS) 1151 util_progress(); 1152 else 1153 file_progress(); 1154 1155 // Compute the number of fields, and the length of the fieldlist record 1156 nfields = 0; 1157 fnamelen = 2; 1158 version (SCPP) 1159 { 1160 if (CPP) 1161 { 1162 // Base classes come first 1163 for (b = st.Sbase; b; b = b.BCnext) 1164 { 1165 if (b.BCflags & BCFvirtual) // skip virtual base classes 1166 continue; 1167 nfields++; 1168 fnamelen += ((config.fulltypes == CV4) ? 6 : 8) + 1169 cv4_numericbytes(b.BCoffset); 1170 } 1171 1172 // Now virtual base classes (direct and indirect) 1173 for (b = st.Svirtbase; b; b = b.BCnext) 1174 { 1175 nfields++; 1176 fnamelen += ((config.fulltypes == CV4) ? 8 : 12) + 1177 cv4_numericbytes(st.Svbptr_off) + 1178 cv4_numericbytes(b.BCvbtbloff / _tysize[TYint]); 1179 } 1180 1181 // Now friend classes 1182 i = list_nitems(st.Sfriendclass); 1183 nfields += i; 1184 fnamelen += i * ((config.fulltypes == CV4) ? 4 : 8); 1185 1186 // Now friend functions 1187 foreach (sl; ListRange(st.Sfriendfuncs)) 1188 { Symbol *sf = list_symbol(sl); 1189 1190 symbol_debug(sf); 1191 if (sf.Sclass == SCfunctempl) 1192 continue; 1193 nfields++; 1194 fnamelen += ((config.fulltypes == CV4) ? 4 : 6) + 1195 cv_stringbytes(cpp_unmangleident(sf.Sident.ptr)); 1196 } 1197 } 1198 } 1199 count = nfields; 1200 foreach (sl; ListRange(st.Sfldlst)) 1201 { Symbol *sf = list_symbol(sl); 1202 targ_size_t offset; 1203 1204 symbol_debug(sf); 1205 const(char)* sfid = sf.Sident.ptr; 1206 switch (sf.Sclass) 1207 { 1208 case SCmember: 1209 case SCfield: 1210 if (CPP && sf == s.Sstruct.Svptr) 1211 fnamelen += ((config.fulltypes == CV4) ? 4 : 8); 1212 else 1213 { offset = sf.Smemoff; 1214 fnamelen += ((config.fulltypes == CV4) ? 6 : 8) + 1215 cv4_numericbytes(cast(uint)offset) + cv_stringbytes(sfid); 1216 } 1217 break; 1218 1219 version (SCPP) 1220 { 1221 case SCstruct: 1222 if (sf.Sstruct.Sflags & STRanonymous) 1223 continue; 1224 if (sf.Sstruct.Sflags & STRnotagname) 1225 sfid = cpp_name_none.ptr; 1226 property |= 0x10; // class contains nested classes 1227 goto Lnest2; 1228 1229 case SCenum: 1230 if (sf.Senum.SEflags & SENnotagname) 1231 sfid = cpp_name_none.ptr; 1232 goto Lnest2; 1233 1234 case SCtypedef: 1235 Lnest2: 1236 fnamelen += ((config.fulltypes == CV4) ? 4 : 8) + 1237 cv_stringbytes(sfid); 1238 break; 1239 1240 case SCextern: 1241 case SCcomdef: 1242 case SCglobal: 1243 case SCstatic: 1244 case SCinline: 1245 case SCsinline: 1246 case SCeinline: 1247 case SCcomdat: 1248 if (tyfunc(sf.ty())) 1249 { Symbol *so; 1250 int nfuncs; 1251 1252 nfuncs = 0; 1253 for (so = sf; so; so = so.Sfunc.Foversym) 1254 { 1255 if (so.Sclass == SCtypedef || 1256 so.Sclass == SCfunctempl || 1257 so.Sfunc.Fflags & Fnodebug) // if compiler generated 1258 continue; // skip it 1259 nfuncs++; 1260 } 1261 if (nfuncs == 0) 1262 continue; 1263 1264 if (nfuncs > 1) 1265 count += nfuncs - 1; 1266 1267 sfid = cv4_prettyident(sf); 1268 } 1269 fnamelen += ((config.fulltypes == CV4) ? 6 : 8) + 1270 cv_stringbytes(sfid); 1271 break; 1272 } 1273 1274 default: 1275 continue; 1276 } 1277 nfields++; 1278 count++; 1279 } 1280 1281 TOWORD(d.data.ptr + 2,count); 1282 if (config.fulltypes == CV4) 1283 TOWORD(d.data.ptr + 6,property); 1284 else 1285 TOWORD(d.data.ptr + 4,property); 1286 1287 // Generate fieldlist type record 1288 dt = debtyp_alloc(fnamelen); 1289 p = dt.data.ptr; 1290 TOWORD(p,LF_FIELDLIST); 1291 1292 // And fill it in 1293 p += 2; 1294 version (SCPP) 1295 { 1296 if (CPP) 1297 { 1298 // Put out real base classes 1299 for (b = st.Sbase; b; b = b.BCnext) 1300 { targ_size_t offset; 1301 1302 if (b.BCflags & BCFvirtual) // skip virtual base classes 1303 continue; 1304 offset = b.BCoffset; 1305 typidx = cv4_symtypidx(b.BCbase); 1306 1307 attribute = (b.BCflags & BCFpmask); 1308 if (attribute & 4) 1309 attribute = 1; 1310 else 1311 attribute = 4 - attribute; 1312 1313 TOWORD(p,LF_BCLASS); 1314 if (config.fulltypes == CV4) 1315 { TOWORD(p + 2,typidx); 1316 TOWORD(p + 4,attribute); 1317 p += 6; 1318 } 1319 else 1320 { TOLONG(p + 4,typidx); 1321 TOWORD(p + 2,attribute); 1322 p += 8; 1323 } 1324 1325 cv4_storenumeric(p,offset); 1326 p += cv4_numericbytes(offset); 1327 } 1328 1329 // Now direct followed by indirect virtual base classes 1330 i = LF_VBCLASS; 1331 do 1332 { 1333 for (b = st.Svirtbase; b; b = b.BCnext) 1334 { targ_size_t vbpoff,vboff; 1335 type *vbptype; // type of virtual base pointer 1336 idx_t vbpidx; 1337 1338 if (baseclass_find(st.Sbase,b.BCbase)) // if direct vbase 1339 { if (i == LF_IVBCLASS) 1340 continue; 1341 } 1342 else 1343 { if (i == LF_VBCLASS) 1344 continue; 1345 } 1346 1347 typidx = cv4_symtypidx(b.BCbase); 1348 1349 vbptype = type_allocn(TYarray,tstypes[TYint]); 1350 vbptype.Tflags |= TFsizeunknown; 1351 vbptype = newpointer(vbptype); 1352 vbptype.Tcount++; 1353 vbpidx = cv4_typidx(vbptype); 1354 type_free(vbptype); 1355 1356 attribute = (b.BCflags & BCFpmask); 1357 if (attribute & 4) 1358 attribute = 1; 1359 else 1360 attribute = 4 - attribute; 1361 1362 vbpoff = st.Svbptr_off; 1363 vboff = b.BCvbtbloff / _tysize[TYint]; 1364 1365 if (config.fulltypes == CV4) 1366 { TOWORD(p,i); 1367 TOWORD(p + 2,typidx); 1368 TOWORD(p + 4,vbpidx); 1369 TOWORD(p + 6,attribute); 1370 p += 8; 1371 } 1372 else 1373 { TOWORD(p,i); 1374 TOLONG(p + 4,typidx); // btype 1375 TOLONG(p + 8,vbpidx); // vbtype 1376 TOWORD(p + 2,attribute); 1377 p += 12; 1378 } 1379 1380 cv4_storenumeric(p,vbpoff); 1381 p += cv4_numericbytes(vbpoff); 1382 cv4_storenumeric(p,vboff); 1383 p += cv4_numericbytes(vboff); 1384 } 1385 i ^= LF_VBCLASS ^ LF_IVBCLASS; // toggle between them 1386 } while (i != LF_VBCLASS); 1387 1388 // Now friend classes 1389 foreach (sl; ListRange(s.Sstruct.Sfriendclass)) 1390 { Symbol *sf = list_symbol(sl); 1391 1392 symbol_debug(sf); 1393 typidx = cv4_symtypidx(sf); 1394 if (config.fulltypes == CV4) 1395 { TOWORD(p,LF_FRIENDCLS); 1396 TOWORD(p + 2,typidx); 1397 p += 4; 1398 } 1399 else 1400 { TOLONG(p,LF_FRIENDCLS); 1401 TOLONG(p + 4,typidx); 1402 p += 8; 1403 } 1404 } 1405 1406 // Now friend functions 1407 foreach (sl; ListRange(s.Sstruct.Sfriendfuncs)) 1408 { Symbol *sf = list_symbol(sl); 1409 1410 symbol_debug(sf); 1411 if (sf.Sclass == SCfunctempl) 1412 continue; 1413 typidx = cv4_symtypidx(sf); 1414 TOWORD(p,LF_FRIENDFCN); 1415 if (config.fulltypes == CV4) 1416 { TOWORD(p + 2,typidx); 1417 p += 4; 1418 } 1419 else 1420 { TOLONG(p + 2,typidx); 1421 p += 6; 1422 } 1423 p += cv_namestring(p,cpp_unmangleident(sf.Sident.ptr)); 1424 } 1425 } 1426 } 1427 foreach (sl; ListRange(s.Sstruct.Sfldlst)) 1428 { Symbol *sf = list_symbol(sl); 1429 targ_size_t offset; 1430 1431 symbol_debug(sf); 1432 const(char)* sfid = sf.Sident.ptr; 1433 switch (sf.Sclass) 1434 { 1435 case SCfield: 1436 { debtyp_t *db; 1437 1438 if (config.fulltypes == CV4) 1439 { db = debtyp_alloc(6); 1440 TOWORD(db.data.ptr,LF_BITFIELD); 1441 db.data.ptr[2] = sf.Swidth; 1442 db.data.ptr[3] = sf.Sbit; 1443 TOWORD(db.data.ptr + 4,cv4_symtypidx(sf)); 1444 } 1445 else 1446 { db = debtyp_alloc(8); 1447 TOWORD(db.data.ptr,LF_BITFIELD); 1448 db.data.ptr[6] = sf.Swidth; 1449 db.data.ptr[7] = sf.Sbit; 1450 TOLONG(db.data.ptr + 2,cv4_symtypidx(sf)); 1451 } 1452 typidx = cv_debtyp(db); 1453 goto L3; 1454 } 1455 1456 case SCmember: 1457 typidx = cv4_symtypidx(sf); 1458 L3: 1459 version (SCPP) 1460 { 1461 if (CPP && sf == s.Sstruct.Svptr) 1462 { 1463 if (config.fulltypes == CV4) 1464 { TOWORD(p,LF_VFUNCTAB); 1465 TOWORD(p + 2,typidx); 1466 p += 4; 1467 } 1468 else 1469 { TOLONG(p,LF_VFUNCTAB); // 0 fill 2 bytes 1470 TOLONG(p + 4,typidx); 1471 p += 8; 1472 } 1473 break; 1474 } 1475 } 1476 offset = sf.Smemoff; 1477 TOWORD(p,LF_MEMBER); 1478 version (SCPP) 1479 { 1480 attribute = CPP ? SFLtoATTR(sf.Sflags) : 0; 1481 assert((attribute & ~3) == 0); 1482 } 1483 else 1484 { 1485 attribute = 0; 1486 } 1487 if (config.fulltypes == CV4) 1488 { TOWORD(p + 2,typidx); 1489 TOWORD(p + 4,attribute); 1490 p += 6; 1491 } 1492 else 1493 { TOLONG(p + 4,typidx); 1494 TOWORD(p + 2,attribute); 1495 p += 8; 1496 } 1497 cv4_storenumeric(p,cast(uint)offset); 1498 p += cv4_numericbytes(cast(uint)offset); 1499 p += cv_namestring(p,sfid); 1500 break; 1501 1502 version (SCPP) 1503 { 1504 case SCstruct: 1505 if (sf.Sstruct.Sflags & STRanonymous) 1506 continue; 1507 if (sf.Sstruct.Sflags & STRnotagname) 1508 sfid = cpp_name_none.ptr; 1509 goto Lnest; 1510 1511 case SCenum: 1512 if (sf.Senum.SEflags & SENnotagname) 1513 sfid = cpp_name_none.ptr; 1514 goto Lnest; 1515 1516 case SCtypedef: 1517 Lnest: 1518 TOWORD(p,LF_NESTTYPE); 1519 typidx = cv4_symtypidx(sf); 1520 if (config.fulltypes == CV4) 1521 { TOWORD(p + 2,typidx); 1522 p += 4; 1523 } 1524 else 1525 { TOLONG(p + 4,typidx); 1526 p += 8; 1527 } 1528 L2: 1529 p += cv_namestring(p,sfid); 1530 break; 1531 1532 case SCextern: 1533 case SCcomdef: 1534 case SCglobal: 1535 case SCstatic: 1536 case SCinline: 1537 case SCsinline: 1538 case SCeinline: 1539 case SCcomdat: 1540 if (tyfunc(sf.ty())) 1541 { int count2; 1542 1543 typidx = cv4_methodlist(sf,&count2); 1544 if (!typidx) 1545 break; 1546 sfid = cv4_prettyident(sf); 1547 TOWORD(p,LF_METHOD); 1548 TOWORD(p + 2,count2); 1549 p += 4; 1550 TOIDX(p,typidx); 1551 p += cgcv.sz_idx; 1552 goto L2; 1553 } 1554 else 1555 { 1556 TOWORD(p,LF_STMEMBER); 1557 typidx = cv4_symtypidx(sf); 1558 attribute = SFLtoATTR(sf.Sflags); 1559 if (config.fulltypes == CV4) 1560 { TOWORD(p + 2,typidx); 1561 TOWORD(p + 4,attribute); 1562 p += 6; 1563 } 1564 else 1565 { TOLONG(p + 4,typidx); 1566 TOWORD(p + 2,attribute); 1567 p += 8; 1568 } 1569 goto L2; 1570 } 1571 break; 1572 } 1573 1574 default: 1575 continue; 1576 } 1577 } 1578 //printf("fnamelen = %d, p-dt.data = %d\n",fnamelen,p-dt.data); 1579 assert(p - dt.data.ptr == fnamelen); 1580 if (config.fulltypes == CV4) 1581 TOWORD(d.data.ptr + 4,cv_debtyp(dt)); 1582 else 1583 TOLONG(d.data.ptr + 6,cv_debtyp(dt)); 1584 1585 static if (SYMDEB_TDB) 1586 { 1587 if (config.fulltypes == CVTDB) 1588 { 1589 s.Stypidx = cv_debtyp(d); 1590 reset_symbuf.write(&s, (s).sizeof); 1591 } 1592 } 1593 version (SCPP) 1594 { 1595 if (CPP) 1596 { 1597 symbol_debug(s); 1598 if (st.Sflags & STRglobal) 1599 list_prepend(&cgcv.list,s); 1600 else 1601 cv4_outsym(s); 1602 } 1603 } 1604 return s.Stypidx; 1605 } 1606 1607 /**************************** 1608 * Return type index of enum. 1609 */ 1610 1611 version (SCPP) 1612 { 1613 1614 private uint cv4_enum(Symbol *s) 1615 { 1616 debtyp_t* d,dt; 1617 uint nfields,fnamelen; 1618 uint len; 1619 type *t; 1620 type *tbase; 1621 uint property; 1622 uint attribute; 1623 int i; 1624 char *id; 1625 1626 symbol_debug(s); 1627 if (s.Stypidx) // if already converted 1628 { //assert(s.Stypidx - cgcv.deb_offset < debtyp.length); 1629 return s.Stypidx; 1630 } 1631 1632 //printf("cv4_enum(%s)\n",s.Sident.ptr); 1633 t = s.Stype; 1634 type_debug(t); 1635 tbase = t.Tnext; 1636 property = 0; 1637 if (s.Senum.SEflags & SENforward) 1638 property |= 0x80; // enum is forward referenced 1639 1640 id = s.Sident.ptr; 1641 if (s.Senum.SEflags & SENnotagname) 1642 id = cpp_name_none.ptr; 1643 if (config.fulltypes == CV4) 1644 { len = 10; 1645 d = debtyp_alloc(len + cv_stringbytes(id)); 1646 TOWORD(d.data.ptr,LF_ENUM); 1647 TOWORD(d.data.ptr + 4,cv4_typidx(tbase)); 1648 TOWORD(d.data.ptr + 8,property); 1649 } 1650 else 1651 { len = 14; 1652 d = debtyp_alloc(len + cv_stringbytes(id)); 1653 TOWORD(d.data.ptr,LF_ENUM); 1654 TOLONG(d.data.ptr + 6,cv4_typidx(tbase)); 1655 TOWORD(d.data.ptr + 4,property); 1656 } 1657 len += cv_namestring(d.data.ptr + len,id); 1658 1659 // Assign a number to prevent infinite recursion if an enum member 1660 // references the same enum. 1661 if (config.fulltypes == CVTDB) 1662 { 1663 static if (SYMDEB_TDB) 1664 { 1665 debtyp_t *df; 1666 1667 TOWORD(d.data.ptr + 2,0); 1668 TOWORD(d.data.ptr + 6,0); 1669 debtyp_check(d); 1670 s.Stypidx = tdb_typidx(&d.length); // forward reference it 1671 } 1672 } 1673 else 1674 { 1675 d.length = 0; // so cv_debtyp() will allocate new 1676 s.Stypidx = cv_debtyp(d); 1677 d.length = cast(ushort)len; // restore length 1678 } 1679 reset_symbuf.write((&s)[0 .. 1]); 1680 1681 // Compute the number of fields, and the length of the fieldlist record 1682 nfields = 0; 1683 fnamelen = 2; 1684 foreach (sl; ListRange(s.Senum.SEenumlist)) 1685 { Symbol *sf = list_symbol(sl); 1686 uint value; 1687 1688 symbol_debug(sf); 1689 value = cast(uint)el_tolongt(sf.Svalue); 1690 nfields++; 1691 fnamelen += 4 + cv4_numericbytes(value) + cv_stringbytes(sf.Sident.ptr); 1692 } 1693 1694 TOWORD(d.data.ptr + 2,nfields); 1695 1696 // If forward reference, then field list is 0 1697 if (s.Senum.SEflags & SENforward) 1698 { 1699 TOWORD(d.data.ptr + 6,0); 1700 return s.Stypidx; 1701 } 1702 1703 // Generate fieldlist type record 1704 dt = debtyp_alloc(fnamelen); 1705 TOWORD(dt.data.ptr,LF_FIELDLIST); 1706 1707 // And fill it in 1708 i = 2; 1709 foreach (sl; ListRange(s.Senum.SEenumlist)) 1710 { Symbol *sf = list_symbol(sl); 1711 uint value; 1712 1713 symbol_debug(sf); 1714 value = cast(uint)el_tolongt(sf.Svalue); 1715 TOWORD(dt.data.ptr + i,LF_ENUMERATE); 1716 attribute = SFLtoATTR(sf.Sflags); 1717 TOWORD(dt.data.ptr + i + 2,attribute); 1718 cv4_storenumeric(dt.data.ptr + i + 4,value); 1719 i += 4 + cv4_numericbytes(value); 1720 i += cv_namestring(dt.data.ptr + i,sf.Sident.ptr); 1721 1722 // If enum is not a member of a class, output enum members as constants 1723 if (!isclassmember(s)) 1724 { symbol_debug(sf); 1725 cv4_outsym(sf); 1726 } 1727 } 1728 assert(i == fnamelen); 1729 if (config.fulltypes == CV4) 1730 TOWORD(d.data.ptr + 6,cv_debtyp(dt)); 1731 else 1732 TOLONG(d.data.ptr + 10,cv_debtyp(dt)); 1733 1734 symbol_debug(s); 1735 if (CPP) 1736 cv4_outsym(s); 1737 return s.Stypidx; 1738 } 1739 1740 } 1741 else 1742 { 1743 private uint cv4_fwdenum(type* t) 1744 { 1745 Symbol* s = t.Ttag; 1746 1747 // write a forward reference enum record that is enough for the linker to 1748 // fold with original definition from EnumDeclaration 1749 uint bty = dttab4[tybasic(t.Tnext.Tty)]; 1750 const id = prettyident(s); 1751 uint len = config.fulltypes == CV8 ? 14 : 10; 1752 debtyp_t* d = debtyp_alloc(len + cv_stringbytes(id)); 1753 switch (config.fulltypes) 1754 { 1755 case CV8: 1756 TOWORD(d.data.ptr, LF_ENUM_V3); 1757 TOLONG(d.data.ptr + 2, 0); // count 1758 TOWORD(d.data.ptr + 4, 0x80); // property : forward reference 1759 TOLONG(d.data.ptr + 6, bty); // memtype 1760 TOLONG(d.data.ptr + 10, 0); // fieldlist 1761 break; 1762 1763 case CV4: 1764 TOWORD(d.data.ptr,LF_ENUM); 1765 TOWORD(d.data.ptr + 2, 0); // count 1766 TOWORD(d.data.ptr + 4, bty); // memtype 1767 TOLONG(d.data.ptr + 6, 0); // fieldlist 1768 TOWORD(d.data.ptr + 8, 0x80); // property : forward reference 1769 break; 1770 1771 default: 1772 assert(0); 1773 } 1774 cv_namestring(d.data.ptr + len, id); 1775 s.Stypidx = cv_debtyp(d); 1776 return s.Stypidx; 1777 } 1778 1779 } 1780 /************************************************ 1781 * Return 'calling convention' type of function. 1782 */ 1783 1784 ubyte cv4_callconv(type *t) 1785 { ubyte call; 1786 1787 switch (tybasic(t.Tty)) 1788 { 1789 case TYffunc: call = 1; break; 1790 case TYfpfunc: call = 3; break; 1791 case TYf16func: call = 3; break; 1792 case TYfsfunc: call = 8; break; 1793 case TYnsysfunc: call = 9; break; 1794 case TYfsysfunc: call = 10; break; 1795 case TYnfunc: call = 0; break; 1796 case TYnpfunc: call = 2; break; 1797 case TYnsfunc: call = 7; break; 1798 case TYifunc: call = 1; break; 1799 case TYjfunc: call = 2; break; 1800 case TYmfunc: call = 11; break; // this call 1801 default: 1802 assert(0); 1803 } 1804 return call; 1805 } 1806 1807 /********************************************** 1808 * Return type index for the type of a symbol. 1809 */ 1810 1811 version (MARS) 1812 { 1813 1814 private uint cv4_symtypidx(Symbol *s) 1815 { 1816 return cv4_typidx(s.Stype); 1817 } 1818 1819 } 1820 1821 version (SCPP) 1822 { 1823 1824 private uint cv4_symtypidx(Symbol *s) 1825 { type *t; 1826 debtyp_t *d; 1827 ubyte *p; 1828 1829 if (!CPP) 1830 return cv4_typidx(s.Stype); 1831 symbol_debug(s); 1832 if (isclassmember(s)) 1833 { t = s.Stype; 1834 if (tyfunc(t.Tty)) 1835 { param_t *pa; 1836 uint nparam; 1837 idx_t paramidx; 1838 idx_t thisidx; 1839 uint u; 1840 func_t *f; 1841 ubyte call; 1842 1843 // It's a member function, which gets a special type record 1844 1845 f = s.Sfunc; 1846 if (f.Fflags & Fstatic) 1847 thisidx = dttab4[TYvoid]; 1848 else 1849 { type *tthis = cpp_thistype(s.Stype,cast(Classsym *)s.Sscope); 1850 1851 thisidx = cv4_typidx(tthis); 1852 type_free(tthis); 1853 } 1854 1855 paramidx = cv4_arglist(t,&nparam); 1856 call = cv4_callconv(t); 1857 1858 if (config.fulltypes == CV4) 1859 { 1860 d = debtyp_alloc(18); 1861 p = d.data.ptr; 1862 TOWORD(p,LF_MFUNCTION); 1863 TOWORD(p + 2,cv4_typidx(t.Tnext)); 1864 TOWORD(p + 4,cv4_symtypidx(s.Sscope)); 1865 TOWORD(p + 6,thisidx); 1866 p[8] = call; 1867 p[9] = 0; // reserved 1868 TOWORD(p + 10,nparam); 1869 TOWORD(p + 12,paramidx); 1870 TOLONG(p + 14,0); // thisadjust 1871 } 1872 else 1873 { 1874 d = debtyp_alloc(26); 1875 p = d.data.ptr; 1876 TOWORD(p,LF_MFUNCTION); 1877 TOLONG(p + 2,cv4_typidx(t.Tnext)); 1878 TOLONG(p + 6,cv4_symtypidx(s.Sscope)); 1879 TOLONG(p + 10,thisidx); 1880 p[14] = call; 1881 p[15] = 0; // reserved 1882 TOWORD(p + 16,nparam); 1883 TOLONG(p + 18,paramidx); 1884 TOLONG(p + 22,0); // thisadjust 1885 } 1886 return cv_debtyp(d); 1887 } 1888 } 1889 return cv4_typidx(s.Stype); 1890 } 1891 1892 } 1893 1894 /*********************************** 1895 * Return CV4 type index for a type. 1896 */ 1897 1898 uint cv4_typidx(type *t) 1899 { uint typidx; 1900 uint u; 1901 uint next; 1902 uint key; 1903 debtyp_t *d; 1904 targ_size_t size; 1905 tym_t tym; 1906 tym_t tycv; 1907 tym_t tymnext; 1908 type *tv; 1909 uint dt; 1910 uint attribute; 1911 ubyte call; 1912 1913 //printf("cv4_typidx(%p)\n",t); 1914 if (!t) 1915 return dttab4[TYint]; // assume int 1916 type_debug(t); 1917 next = cv4_typidx(t.Tnext); 1918 tycv = t.Tty; 1919 tym = tybasic(tycv); 1920 tycv &= mTYconst | mTYvolatile | mTYimmutable; 1921 attribute = 0; 1922 L1: 1923 dt = dttab4[tym]; 1924 switch (tym) 1925 { 1926 case TYllong: 1927 if (t.Tnext) 1928 goto Ldelegate; 1929 assert(dt); 1930 typidx = dt; 1931 break; 1932 1933 case TYullong: 1934 if (t.Tnext) 1935 goto Ldarray; 1936 assert(dt); 1937 typidx = dt; 1938 break; 1939 1940 case TYvoid: 1941 case TYchar: 1942 case TYschar: 1943 case TYuchar: 1944 case TYchar16: 1945 case TYshort: 1946 case TYushort: 1947 case TYint: 1948 case TYuint: 1949 case TYulong: 1950 case TYlong: 1951 case TYfloat: 1952 case TYdouble: 1953 case TYdouble_alias: 1954 case TYldouble: 1955 case TYifloat: 1956 case TYidouble: 1957 case TYildouble: 1958 case TYcfloat: 1959 case TYcdouble: 1960 case TYcldouble: 1961 case TYbool: 1962 case TYwchar_t: 1963 case TYdchar: 1964 assert(dt); 1965 typidx = dt; 1966 break; 1967 1968 case TYnptr: 1969 case TYimmutPtr: 1970 case TYsharePtr: 1971 case TYrestrictPtr: 1972 version (MARS) 1973 { 1974 if (t.Tkey) 1975 goto Laarray; 1976 } 1977 goto Lptr; 1978 case TYsptr: 1979 case TYcptr: 1980 case TYfgPtr: 1981 Lptr: 1982 attribute |= I32 ? 10 : 0; goto L2; 1983 1984 case TYfptr: 1985 case TYvptr: attribute |= I32 ? 11 : 1; goto L2; 1986 case TYhptr: attribute |= 2; goto L2; 1987 1988 L2: 1989 if (config.fulltypes == CV4) 1990 { 1991 // This is a hack to duplicate bugs in VC, so that the VC 1992 // debugger will work. 1993 tymnext = t.Tnext ? t.Tnext.Tty : TYint; 1994 if (tymnext & (mTYconst | mTYimmutable | mTYvolatile) && 1995 !tycv && 1996 tyarithmetic(tymnext) && 1997 !(attribute & 0xE0) 1998 ) 1999 { 2000 typidx = dt | dttab4[tybasic(tymnext)]; 2001 break; 2002 } 2003 } 2004 if ((next & 0xFF00) == 0 && !(attribute & 0xE0)) 2005 typidx = next | dt; 2006 else 2007 { 2008 if (tycv & (mTYconst | mTYimmutable)) 2009 attribute |= 0x400; 2010 if (tycv & mTYvolatile) 2011 attribute |= 0x200; 2012 tycv = 0; 2013 switch (config.fulltypes) 2014 { 2015 case CV4: 2016 d = debtyp_alloc(6); 2017 TOWORD(d.data.ptr,LF_POINTER); 2018 TOWORD(d.data.ptr + 2,attribute); 2019 TOWORD(d.data.ptr + 4,next); 2020 break; 2021 2022 case CV8: 2023 d = debtyp_alloc(10); 2024 TOWORD(d.data.ptr,0x1002); 2025 TOLONG(d.data.ptr + 2,next); 2026 // see https://github.com/Microsoft/microsoft-pdb/blob/master/include/cvinfo.h#L1514 2027 // add size and pointer type (PTR_64 or PTR_NEAR32) 2028 attribute |= (I64 ? (8 << 13) | 0xC : (4 << 13) | 0xA); 2029 // convert reference to r-value reference to remove & from type display in debugger 2030 if (attribute & 0x20) 2031 attribute |= 0x80; 2032 TOLONG(d.data.ptr + 6,attribute); 2033 break; 2034 2035 default: 2036 d = debtyp_alloc(10); 2037 TOWORD(d.data.ptr,LF_POINTER); 2038 TOLONG(d.data.ptr + 2,attribute); 2039 TOLONG(d.data.ptr + 6,next); 2040 break; 2041 } 2042 typidx = cv_debtyp(d); 2043 } 2044 break; 2045 2046 Ldarray: 2047 switch (config.fulltypes) 2048 { 2049 version (MARS) 2050 { 2051 case CV8: 2052 { 2053 typidx = cv8_darray(t, next); 2054 break; 2055 } 2056 } 2057 case CV4: 2058 static if (1) 2059 { 2060 d = debtyp_alloc(12); 2061 TOWORD(d.data.ptr, LF_OEM); 2062 TOWORD(d.data.ptr + 2, OEM); 2063 TOWORD(d.data.ptr + 4, 1); // 1 = dynamic array 2064 TOWORD(d.data.ptr + 6, 2); // count of type indices to follow 2065 TOWORD(d.data.ptr + 8, 0x12); // index type, T_LONG 2066 TOWORD(d.data.ptr + 10, next); // element type 2067 } 2068 else 2069 { 2070 d = debtyp_alloc(6); 2071 TOWORD(d.data.ptr,LF_DYN_ARRAY); 2072 TOWORD(d.data.ptr + 2, 0x12); // T_LONG 2073 TOWORD(d.data.ptr + 4, next); 2074 } 2075 typidx = cv_debtyp(d); 2076 break; 2077 2078 default: 2079 assert(0); 2080 } 2081 2082 break; 2083 2084 Laarray: 2085 version (MARS) 2086 { 2087 key = cv4_typidx(t.Tkey); 2088 switch (config.fulltypes) 2089 { 2090 case CV8: 2091 typidx = cv8_daarray(t, key, next); 2092 break; 2093 2094 case CV4: 2095 static if (1) 2096 { 2097 d = debtyp_alloc(12); 2098 TOWORD(d.data.ptr, LF_OEM); 2099 TOWORD(d.data.ptr + 2, OEM); 2100 TOWORD(d.data.ptr + 4, 2); // 2 = associative array 2101 TOWORD(d.data.ptr + 6, 2); // count of type indices to follow 2102 TOWORD(d.data.ptr + 8, key); // key type 2103 TOWORD(d.data.ptr + 10, next); // element type 2104 } 2105 else 2106 { 2107 d = debtyp_alloc(6); 2108 TOWORD(d.data.ptr,LF_ASSOC_ARRAY); 2109 TOWORD(d.data.ptr + 2, key); // key type 2110 TOWORD(d.data.ptr + 4, next); // element type 2111 } 2112 typidx = cv_debtyp(d); 2113 break; 2114 2115 default: 2116 assert(0); 2117 } 2118 } 2119 break; 2120 2121 Ldelegate: 2122 switch (config.fulltypes) 2123 { 2124 version (MARS) 2125 { 2126 case CV8: 2127 typidx = cv8_ddelegate(t, next); 2128 break; 2129 } 2130 2131 case CV4: 2132 tv = type_fake(TYnptr); 2133 tv.Tcount++; 2134 key = cv4_typidx(tv); 2135 type_free(tv); 2136 static if (1) 2137 { 2138 d = debtyp_alloc(12); 2139 TOWORD(d.data.ptr, LF_OEM); 2140 TOWORD(d.data.ptr + 2, OEM); 2141 TOWORD(d.data.ptr + 4, 3); // 3 = delegate 2142 TOWORD(d.data.ptr + 6, 2); // count of type indices to follow 2143 TOWORD(d.data.ptr + 8, key); // type of 'this', which is void* 2144 TOWORD(d.data.ptr + 10, next); // function type 2145 } 2146 else 2147 { 2148 d = debtyp_alloc(6); 2149 TOWORD(d.data.ptr,LF_DELEGATE); 2150 TOWORD(d.data.ptr + 2, key); // type of 'this', which is void* 2151 TOWORD(d.data.ptr + 4, next); // function type 2152 } 2153 typidx = cv_debtyp(d); 2154 break; 2155 2156 default: 2157 assert(0); 2158 } 2159 break; 2160 2161 case TYcent: 2162 if (t.Tnext) 2163 goto Ldelegate; 2164 assert(dt); 2165 typidx = dt; 2166 break; 2167 2168 case TYucent: 2169 if (t.Tnext) 2170 goto Ldarray; 2171 assert(dt); 2172 typidx = dt; 2173 break; 2174 2175 case TYarray: 2176 { if (t.Tflags & TFsizeunknown) 2177 size = 0; // don't complain if don't know size 2178 else 2179 size = type_size(t); 2180 Larray: 2181 u = cv4_numericbytes(cast(uint)size); 2182 uint idxtype = I32 ? 0x12 : 0x11; // T_LONG : T_SHORT 2183 if (I64) 2184 idxtype = 0x23; // T_UQUAD 2185 if(next == dttab4[TYvoid]) // do not encode void[n], this confuses the debugger 2186 next = dttab4[TYuchar]; // use ubyte instead 2187 switch (config.fulltypes) 2188 { 2189 case CV8: 2190 d = debtyp_alloc(10 + u + 1); 2191 TOWORD(d.data.ptr,0x1503); 2192 TOLONG(d.data.ptr + 2,next); 2193 TOLONG(d.data.ptr + 6,idxtype); 2194 d.data.ptr[10 + u] = 0; // no name 2195 cv4_storenumeric(d.data.ptr + 10,cast(uint)size); 2196 break; 2197 2198 case CV4: 2199 d = debtyp_alloc(6 + u + 1); 2200 TOWORD(d.data.ptr,LF_ARRAY); 2201 TOWORD(d.data.ptr + 2,next); 2202 TOWORD(d.data.ptr + 4,idxtype); 2203 d.data.ptr[6 + u] = 0; // no name 2204 cv4_storenumeric(d.data.ptr + 6,cast(uint)size); 2205 break; 2206 2207 default: 2208 d = debtyp_alloc(10 + u + 1); 2209 TOWORD(d.data.ptr,LF_ARRAY); 2210 TOLONG(d.data.ptr + 2,next); 2211 TOLONG(d.data.ptr + 6,idxtype); 2212 d.data.ptr[10 + u] = 0; // no name 2213 cv4_storenumeric(d.data.ptr + 10,cast(uint)size); 2214 break; 2215 } 2216 typidx = cv_debtyp(d); 2217 break; 2218 } 2219 2220 case TYffunc: 2221 case TYfpfunc: 2222 case TYf16func: 2223 case TYfsfunc: 2224 case TYnsysfunc: 2225 case TYfsysfunc: 2226 case TYnfunc: 2227 case TYnpfunc: 2228 case TYnsfunc: 2229 case TYmfunc: 2230 case TYjfunc: 2231 case TYifunc: 2232 { 2233 param_t *p; 2234 uint nparam; 2235 idx_t paramidx; 2236 2237 call = cv4_callconv(t); 2238 paramidx = cv4_arglist(t,&nparam); 2239 2240 // Construct an LF_PROCEDURE 2241 switch (config.fulltypes) 2242 { 2243 case CV8: 2244 d = debtyp_alloc(2 + 4 + 1 + 1 + 2 + 4); 2245 TOWORD(d.data.ptr,LF_PROCEDURE_V2); 2246 TOLONG(d.data.ptr + 2,next); // return type 2247 d.data.ptr[6] = call; 2248 d.data.ptr[7] = 0; // reserved 2249 TOWORD(d.data.ptr + 8,nparam); 2250 TOLONG(d.data.ptr + 10,paramidx); 2251 break; 2252 2253 case CV4: 2254 d = debtyp_alloc(2 + 2 + 1 + 1 + 2 + 2); 2255 TOWORD(d.data.ptr,LF_PROCEDURE); 2256 TOWORD(d.data.ptr + 2,next); // return type 2257 d.data.ptr[4] = call; 2258 d.data.ptr[5] = 0; // reserved 2259 TOWORD(d.data.ptr + 6,nparam); 2260 TOWORD(d.data.ptr + 8,paramidx); 2261 break; 2262 2263 default: 2264 d = debtyp_alloc(2 + 4 + 1 + 1 + 2 + 4); 2265 TOWORD(d.data.ptr,LF_PROCEDURE); 2266 TOLONG(d.data.ptr + 2,next); // return type 2267 d.data.ptr[6] = call; 2268 d.data.ptr[7] = 0; // reserved 2269 TOWORD(d.data.ptr + 8,nparam); 2270 TOLONG(d.data.ptr + 10,paramidx); 2271 break; 2272 } 2273 2274 typidx = cv_debtyp(d); 2275 break; 2276 } 2277 2278 case TYstruct: 2279 { 2280 if (config.fulltypes == CV8) 2281 { 2282 version (MARS) 2283 { 2284 typidx = cv8_fwdref(t.Ttag); 2285 } 2286 } 2287 else 2288 { 2289 int foo = t.Ttag.Stypidx; 2290 typidx = cv4_struct(t.Ttag,0); 2291 //printf("struct '%s' %x %x\n", t.Ttag.Sident.ptr, foo, typidx); 2292 } 2293 break; 2294 } 2295 2296 case TYenum: 2297 if (CPP) 2298 { 2299 version (SCPP) 2300 { 2301 typidx = cv4_enum(t.Ttag); 2302 } 2303 } 2304 else 2305 typidx = cv4_fwdenum(t); 2306 break; 2307 2308 version (SCPP) 2309 { 2310 case TYvtshape: 2311 { uint count; 2312 ubyte *p; 2313 ubyte descriptor; 2314 2315 count = 1 + list_nitems(t.Ttag.Sstruct.Svirtual); 2316 d = debtyp_alloc(4 + ((count + 1) >> 1)); 2317 p = d.data.ptr; 2318 TOWORD(p,LF_VTSHAPE); 2319 TOWORD(p + 2,count); 2320 descriptor = I32 ? 0x55 : (LARGECODE ? 0x11 : 0); 2321 memset(p + 4,descriptor,(count + 1) >> 1); 2322 2323 typidx = cv_debtyp(d); 2324 break; 2325 } 2326 2327 case TYref: 2328 case TYnref: 2329 case TYfref: 2330 attribute |= 0x20; // indicate reference pointer 2331 goto case; 2332 2333 case TYmemptr: 2334 tym = tybasic(tym_conv(t)); // convert to C data type 2335 goto L1; // and try again 2336 } 2337 2338 version (MARS) 2339 { 2340 case TYref: 2341 case TYnref: 2342 attribute |= 0x20; // indicate reference pointer 2343 tym = TYnptr; // convert to C data type 2344 goto L1; // and try again 2345 } 2346 2347 case TYnullptr: 2348 tym = TYnptr; 2349 next = cv4_typidx(tstypes[TYvoid]); // rewrite as void* 2350 t = tspvoid; 2351 goto L1; 2352 2353 // vector types 2354 case TYfloat4: size = 16; next = dttab4[TYfloat]; goto Larray; 2355 case TYdouble2: size = 16; next = dttab4[TYdouble]; goto Larray; 2356 case TYschar16: size = 16; next = dttab4[TYschar]; goto Larray; 2357 case TYuchar16: size = 16; next = dttab4[TYuchar]; goto Larray; 2358 case TYshort8: size = 16; next = dttab4[TYshort]; goto Larray; 2359 case TYushort8: size = 16; next = dttab4[TYushort]; goto Larray; 2360 case TYlong4: size = 16; next = dttab4[TYlong]; goto Larray; 2361 case TYulong4: size = 16; next = dttab4[TYulong]; goto Larray; 2362 case TYllong2: size = 16; next = dttab4[TYllong]; goto Larray; 2363 case TYullong2: size = 16; next = dttab4[TYullong]; goto Larray; 2364 2365 case TYfloat8: size = 32; next = dttab4[TYfloat]; goto Larray; 2366 case TYdouble4: size = 32; next = dttab4[TYdouble]; goto Larray; 2367 case TYschar32: size = 32; next = dttab4[TYschar]; goto Larray; 2368 case TYuchar32: size = 32; next = dttab4[TYuchar]; goto Larray; 2369 case TYshort16: size = 32; next = dttab4[TYshort]; goto Larray; 2370 case TYushort16: size = 32; next = dttab4[TYushort]; goto Larray; 2371 case TYlong8: size = 32; next = dttab4[TYlong]; goto Larray; 2372 case TYulong8: size = 32; next = dttab4[TYulong]; goto Larray; 2373 case TYllong4: size = 32; next = dttab4[TYllong]; goto Larray; 2374 case TYullong4: size = 32; next = dttab4[TYullong]; goto Larray; 2375 2376 case TYfloat16: size = 64; next = dttab4[TYfloat]; goto Larray; 2377 case TYdouble8: size = 64; next = dttab4[TYdouble]; goto Larray; 2378 case TYschar64: size = 64; next = dttab4[TYschar]; goto Larray; 2379 case TYuchar64: size = 64; next = dttab4[TYuchar]; goto Larray; 2380 case TYshort32: size = 64; next = dttab4[TYshort]; goto Larray; 2381 case TYushort32: size = 64; next = dttab4[TYushort]; goto Larray; 2382 case TYlong16: size = 64; next = dttab4[TYlong]; goto Larray; 2383 case TYulong16: size = 64; next = dttab4[TYulong]; goto Larray; 2384 case TYllong8: size = 64; next = dttab4[TYllong]; goto Larray; 2385 case TYullong8: size = 64; next = dttab4[TYullong]; goto Larray; 2386 2387 default: 2388 debug 2389 WRTYxx(tym); 2390 2391 assert(0); 2392 } 2393 2394 // Add in const and/or volatile modifiers 2395 if (tycv & (mTYconst | mTYimmutable | mTYvolatile)) 2396 { uint modifier; 2397 2398 modifier = (tycv & (mTYconst | mTYimmutable)) ? 1 : 0; 2399 modifier |= (tycv & mTYvolatile) ? 2 : 0; 2400 switch (config.fulltypes) 2401 { 2402 case CV8: 2403 d = debtyp_alloc(8); 2404 TOWORD(d.data.ptr,0x1001); 2405 TOLONG(d.data.ptr + 2,typidx); 2406 TOWORD(d.data.ptr + 6,modifier); 2407 break; 2408 2409 case CV4: 2410 d = debtyp_alloc(6); 2411 TOWORD(d.data.ptr,LF_MODIFIER); 2412 TOWORD(d.data.ptr + 2,modifier); 2413 TOWORD(d.data.ptr + 4,typidx); 2414 break; 2415 2416 default: 2417 d = debtyp_alloc(10); 2418 TOWORD(d.data.ptr,LF_MODIFIER); 2419 TOLONG(d.data.ptr + 2,modifier); 2420 TOLONG(d.data.ptr + 6,typidx); 2421 break; 2422 } 2423 typidx = cv_debtyp(d); 2424 } 2425 2426 assert(typidx); 2427 return typidx; 2428 } 2429 2430 /****************************************** 2431 * Write out symbol s. 2432 */ 2433 2434 private void cv4_outsym(Symbol *s) 2435 { 2436 uint len; 2437 type *t; 2438 uint length; 2439 uint u; 2440 tym_t tym; 2441 const(char)* id; 2442 ubyte *debsym = null; 2443 ubyte[64] buf = void; 2444 2445 //printf("cv4_outsym(%s)\n",s.Sident.ptr); 2446 symbol_debug(s); 2447 version (MARS) 2448 { 2449 if (s.Sflags & SFLnodebug) 2450 return; 2451 } 2452 t = s.Stype; 2453 type_debug(t); 2454 tym = tybasic(t.Tty); 2455 if (tyfunc(tym) && s.Sclass != SCtypedef) 2456 { int framedatum,targetdatum,fd; 2457 char idfree; 2458 idx_t typidx; 2459 2460 if (s != funcsym_p) 2461 return; 2462 version (SCPP) 2463 { 2464 if (CPP && isclassmember(s)) // if method 2465 { Outbuffer buf2; 2466 2467 param_tostring(&buf2,s.Stype); 2468 buf2.prependBytes(cpp_prettyident(s)); 2469 char* s2 = buf2.toString(); 2470 const len2 = strlen(s2); 2471 id = cast(char*)alloca(len2 + 1); 2472 assert(id); 2473 memcpy(cast(void*)id, s2, len2 + 1); 2474 } 2475 else 2476 { 2477 id = prettyident(s); 2478 } 2479 } 2480 else 2481 { 2482 id = s.prettyIdent ? s.prettyIdent : s.Sident.ptr; 2483 } 2484 len = cv_stringbytes(id); 2485 2486 // Length of record 2487 length = 2 + 2 + 4 * 3 + _tysize[TYint] * 4 + 2 + cgcv.sz_idx + 1; 2488 debsym = (length + len <= (buf).sizeof) ? buf.ptr : cast(ubyte *) malloc(length + len); 2489 assert(debsym); 2490 memset(debsym,0,length + len); 2491 2492 // Symbol type 2493 u = (s.Sclass == SCstatic) ? S_LPROC16 : S_GPROC16; 2494 if (I32) 2495 u += S_GPROC32 - S_GPROC16; 2496 TOWORD(debsym + 2,u); 2497 2498 if (config.fulltypes == CV4) 2499 { 2500 // Offsets 2501 if (I32) 2502 { TOLONG(debsym + 16,cast(uint)s.Ssize); // proc length 2503 TOLONG(debsym + 20,cast(uint)startoffset); // debug start 2504 TOLONG(debsym + 24,cast(uint)retoffset); // debug end 2505 u = 28; // offset to fixup 2506 } 2507 else 2508 { TOWORD(debsym + 16,cast(uint)s.Ssize); // proc length 2509 TOWORD(debsym + 18,cast(uint)startoffset); // debug start 2510 TOWORD(debsym + 20,cast(uint)retoffset); // debug end 2511 u = 22; // offset to fixup 2512 } 2513 length += cv_namestring(debsym + u + _tysize[TYint] + 2 + cgcv.sz_idx + 1,id); 2514 typidx = cv4_symtypidx(s); 2515 TOIDX(debsym + u + _tysize[TYint] + 2,typidx); // proc type 2516 debsym[u + _tysize[TYint] + 2 + cgcv.sz_idx] = tyfarfunc(tym) ? 4 : 0; 2517 TOWORD(debsym,length - 2); 2518 } 2519 else 2520 { 2521 // Offsets 2522 if (I32) 2523 { TOLONG(debsym + 16 + cgcv.sz_idx,cast(uint)s.Ssize); // proc length 2524 TOLONG(debsym + 20 + cgcv.sz_idx,cast(uint)startoffset); // debug start 2525 TOLONG(debsym + 24 + cgcv.sz_idx,cast(uint)retoffset); // debug end 2526 u = 28; // offset to fixup 2527 } 2528 else 2529 { TOWORD(debsym + 16 + cgcv.sz_idx,cast(uint)s.Ssize); // proc length 2530 TOWORD(debsym + 18 + cgcv.sz_idx,cast(uint)startoffset); // debug start 2531 TOWORD(debsym + 20 + cgcv.sz_idx,cast(uint)retoffset); // debug end 2532 u = 22; // offset to fixup 2533 } 2534 u += cgcv.sz_idx; 2535 length += cv_namestring(debsym + u + _tysize[TYint] + 2 + 1,id); 2536 typidx = cv4_symtypidx(s); 2537 TOIDX(debsym + 16,typidx); // proc type 2538 debsym[u + _tysize[TYint] + 2] = tyfarfunc(tym) ? 4 : 0; 2539 TOWORD(debsym,length - 2); 2540 } 2541 2542 uint soffset = cast(uint)Offset(DEBSYM); 2543 objmod.write_bytes(SegData[DEBSYM],length,debsym); 2544 2545 // Put out fixup for function start offset 2546 objmod.reftoident(DEBSYM,soffset + u,s,0,CFseg | CFoff); 2547 } 2548 else 2549 { targ_size_t base; 2550 int reg; 2551 uint fd; 2552 uint idx1,idx2; 2553 uint value; 2554 uint fixoff; 2555 idx_t typidx; 2556 2557 typidx = cv4_typidx(t); 2558 version (MARS) 2559 { 2560 id = s.prettyIdent ? s.prettyIdent : prettyident(s); 2561 } 2562 else 2563 { 2564 id = prettyident(s); 2565 } 2566 len = cast(uint)strlen(id); 2567 debsym = (39 + IDOHD + len <= (buf).sizeof) ? buf.ptr : cast(ubyte *) malloc(39 + IDOHD + len); 2568 assert(debsym); 2569 switch (s.Sclass) 2570 { 2571 case SCparameter: 2572 case SCregpar: 2573 if (s.Sfl == FLreg) 2574 { 2575 s.Sfl = FLpara; 2576 cv4_outsym(s); 2577 s.Sfl = FLreg; 2578 goto case_register; 2579 } 2580 base = Para.size - BPoff; // cancel out add of BPoff 2581 goto L1; 2582 2583 case SCauto: 2584 if (s.Sfl == FLreg) 2585 goto case_register; 2586 case_auto: 2587 base = Auto.size; 2588 L1: 2589 if (s.Sscope) // local variables moved into the closure cannot be emitted directly 2590 goto Lret; 2591 TOWORD(debsym + 2,I32 ? S_BPREL32 : S_BPREL16); 2592 if (config.fulltypes == CV4) 2593 { TOOFFSET(debsym + 4,s.Soffset + base + BPoff); 2594 TOIDX(debsym + 4 + _tysize[TYint],typidx); 2595 } 2596 else 2597 { TOOFFSET(debsym + 4 + cgcv.sz_idx,s.Soffset + base + BPoff); 2598 TOIDX(debsym + 4,typidx); 2599 } 2600 length = 2 + 2 + _tysize[TYint] + cgcv.sz_idx; 2601 length += cv_namestring(debsym + length,id); 2602 TOWORD(debsym,length - 2); 2603 break; 2604 2605 case SCbprel: 2606 base = -BPoff; 2607 goto L1; 2608 2609 case SCfastpar: 2610 if (s.Sfl != FLreg) 2611 { base = Fast.size; 2612 goto L1; 2613 } 2614 goto case_register; 2615 2616 case SCregister: 2617 if (s.Sfl != FLreg) 2618 goto case_auto; 2619 goto case_register; 2620 2621 case SCpseudo: 2622 case_register: 2623 TOWORD(debsym + 2,S_REGISTER); 2624 reg = cv_regnum(s); 2625 TOIDX(debsym + 4,typidx); 2626 TOWORD(debsym + 4 + cgcv.sz_idx,reg); 2627 length = 2 * 3 + cgcv.sz_idx; 2628 length += 1 + cv_namestring(debsym + length,id); 2629 TOWORD(debsym,length - 2); 2630 break; 2631 2632 case SCextern: 2633 case SCcomdef: 2634 // Common blocks have a non-zero Sxtrnnum and an UNKNOWN seg 2635 if (!(s.Sxtrnnum && s.Sseg == UNKNOWN)) // if it's not really a common block 2636 { 2637 goto Lret; 2638 } 2639 goto case; 2640 case SCglobal: 2641 case SCcomdat: 2642 u = S_GDATA16; 2643 goto L2; 2644 2645 case SCstatic: 2646 case SClocstat: 2647 u = S_LDATA16; 2648 L2: 2649 if (I32) 2650 u += S_GDATA32 - S_GDATA16; 2651 TOWORD(debsym + 2,u); 2652 if (config.fulltypes == CV4) 2653 { 2654 fixoff = 4; 2655 length = 2 + 2 + _tysize[TYint] + 2; 2656 TOOFFSET(debsym + fixoff,s.Soffset); 2657 TOWORD(debsym + fixoff + _tysize[TYint],0); 2658 TOIDX(debsym + length,typidx); 2659 } 2660 else 2661 { 2662 fixoff = 8; 2663 length = 2 + 2 + _tysize[TYint] + 2; 2664 TOOFFSET(debsym + fixoff,s.Soffset); 2665 TOWORD(debsym + fixoff + _tysize[TYint],0); // segment 2666 TOIDX(debsym + 4,typidx); 2667 } 2668 length += cgcv.sz_idx; 2669 length += cv_namestring(debsym + length,id); 2670 TOWORD(debsym,length - 2); 2671 assert(length <= 40 + len); 2672 2673 if (s.Sseg == UNKNOWN || s.Sclass == SCcomdat) // if common block 2674 { 2675 if (config.exe & EX_flat) 2676 { 2677 fd = 0x16; 2678 idx1 = DGROUPIDX; 2679 idx2 = s.Sxtrnnum; 2680 } 2681 else 2682 { 2683 fd = 0x26; 2684 idx1 = idx2 = s.Sxtrnnum; 2685 } 2686 } 2687 else if (s.ty() & (mTYfar | mTYcs)) 2688 { 2689 fd = 0x04; 2690 idx1 = idx2 = SegData[s.Sseg].segidx; 2691 } 2692 else 2693 { fd = 0x14; 2694 idx1 = DGROUPIDX; 2695 idx2 = SegData[s.Sseg].segidx; 2696 } 2697 /* Because of the linker limitations, the length cannot 2698 * exceed 0x1000. 2699 * See optlink\cv\cvhashes.asm 2700 */ 2701 assert(length <= 0x1000); 2702 if (idx2 != 0) 2703 { uint offset = cast(uint)Offset(DEBSYM); 2704 objmod.write_bytes(SegData[DEBSYM],length,debsym); 2705 objmod.write_long(DEBSYM,offset + fixoff,cast(uint)s.Soffset, 2706 cgcv.LCFDpointer + fd,idx1,idx2); 2707 } 2708 goto Lret; 2709 2710 static if (1) 2711 { 2712 case SCtypedef: 2713 s.Stypidx = typidx; 2714 reset_symbuf.write((&s)[0 .. 1]); 2715 goto L4; 2716 2717 case SCstruct: 2718 if (s.Sstruct.Sflags & STRnotagname) 2719 goto Lret; 2720 goto L4; 2721 2722 case SCenum: 2723 version (SCPP) 2724 { 2725 if (CPP && s.Senum.SEflags & SENnotagname) 2726 goto Lret; 2727 } 2728 L4: 2729 // Output a 'user-defined type' for the tag name 2730 TOWORD(debsym + 2,S_UDT); 2731 TOIDX(debsym + 4,typidx); 2732 length = 2 + 2 + cgcv.sz_idx; 2733 length += cv_namestring(debsym + length,id); 2734 TOWORD(debsym,length - 2); 2735 list_subtract(&cgcv.list,s); 2736 break; 2737 2738 case SCconst: 2739 // The only constants are enum members 2740 value = cast(uint)el_tolongt(s.Svalue); 2741 TOWORD(debsym + 2,S_CONST); 2742 TOIDX(debsym + 4,typidx); 2743 length = 4 + cgcv.sz_idx; 2744 cv4_storenumeric(debsym + length,value); 2745 length += cv4_numericbytes(value); 2746 length += cv_namestring(debsym + length,id); 2747 TOWORD(debsym,length - 2); 2748 break; 2749 } 2750 default: 2751 goto Lret; 2752 } 2753 assert(length <= 40 + len); 2754 objmod.write_bytes(SegData[DEBSYM],length,debsym); 2755 } 2756 Lret: 2757 if (debsym != buf.ptr) 2758 free(debsym); 2759 } 2760 2761 /****************************************** 2762 * Write out any deferred symbols. 2763 */ 2764 2765 private void cv_outlist() 2766 { 2767 while (cgcv.list) 2768 cv_outsym(cast(Symbol *) list_pop(&cgcv.list)); 2769 } 2770 2771 /****************************************** 2772 * Write out symbol table for current function. 2773 */ 2774 2775 private void cv4_func(Funcsym *s) 2776 { 2777 SYMIDX si; 2778 int endarg; 2779 2780 cv4_outsym(s); // put out function symbol 2781 version (MARS) 2782 { 2783 __gshared Funcsym* sfunc; 2784 __gshared int cntOpenBlocks; 2785 sfunc = s; 2786 cntOpenBlocks = 0; 2787 2788 struct cv4 2789 { 2790 nothrow: 2791 // record for CV record S_BLOCK32 2792 struct block32_data 2793 { 2794 ushort len; 2795 ushort id; 2796 uint pParent; 2797 uint pEnd; 2798 uint length; 2799 uint offset; 2800 ushort seg; 2801 ubyte[2] name; 2802 } 2803 2804 extern (C++): 2805 2806 static void endArgs() 2807 { 2808 __gshared ushort[2] endargs = [ 2, S_ENDARG ]; 2809 objmod.write_bytes(SegData[DEBSYM],(endargs).sizeof,endargs.ptr); 2810 } 2811 static void beginBlock(int offset, int length) 2812 { 2813 if (++cntOpenBlocks >= 255) 2814 return; // optlink does not like more than 255 scope blocks 2815 2816 uint soffset = cast(uint)Offset(DEBSYM); 2817 // parent and end to be filled by linker 2818 block32_data block32 = { (block32_data).sizeof - 2, S_BLOCK32, 0, 0, length, 0, 0, [ 0, '\0' ] }; 2819 objmod.write_bytes(SegData[DEBSYM], (block32).sizeof, &block32); 2820 size_t offOffset = cast(char*)&block32.offset - cast(char*)&block32; 2821 objmod.reftoident(DEBSYM, soffset + offOffset, sfunc, offset + sfunc.Soffset, CFseg | CFoff); 2822 } 2823 static void endBlock() 2824 { 2825 if (cntOpenBlocks-- >= 255) 2826 return; // optlink does not like more than 255 scope blocks 2827 2828 __gshared ushort[2] endargs = [ 2, S_END ]; 2829 objmod.write_bytes(SegData[DEBSYM],(endargs).sizeof,endargs.ptr); 2830 } 2831 } 2832 2833 varStats_writeSymbolTable(&globsym, &cv4_outsym, &cv4.endArgs, &cv4.beginBlock, &cv4.endBlock); 2834 } 2835 else 2836 { 2837 symtab_t* symtab = &globsym; 2838 2839 // Put out local symbols 2840 endarg = 0; 2841 for (si = 0; si < symtab.top; si++) 2842 { //printf("globsym.tab[%d] = %p\n",si,globsym.tab[si]); 2843 Symbol *sa = symtab.tab[si]; 2844 cv4_outsym(sa); 2845 } 2846 } 2847 2848 // Put out function return record 2849 if (1) 2850 { ubyte[2+2+2+1+1+4] sreturn = void; 2851 ushort flags; 2852 ubyte style; 2853 tym_t ty; 2854 tym_t tyret; 2855 uint u; 2856 2857 u = 2+2+1; 2858 ty = tybasic(s.ty()); 2859 2860 flags = tyrevfunc(ty) ? 0 : 1; 2861 flags |= typfunc(ty) ? 0 : 2; 2862 TOWORD(sreturn.ptr + 4,flags); 2863 2864 tyret = tybasic(s.Stype.Tnext.Tty); 2865 switch (tyret) 2866 { 2867 case TYvoid: 2868 default: 2869 style = 0; 2870 break; 2871 2872 case TYbool: 2873 case TYchar: 2874 case TYschar: 2875 case TYuchar: 2876 sreturn[7] = 1; 2877 sreturn[8] = 1; // AL 2878 goto L1; 2879 2880 case TYwchar_t: 2881 case TYchar16: 2882 case TYshort: 2883 case TYushort: 2884 goto case_ax; 2885 2886 case TYint: 2887 case TYuint: 2888 case TYsptr: 2889 case TYcptr: 2890 case TYnullptr: 2891 case TYnptr: 2892 case TYnref: 2893 if (I32) 2894 goto case_eax; 2895 else 2896 goto case_ax; 2897 2898 case TYfloat: 2899 case TYifloat: 2900 if (config.exe & EX_flat) 2901 goto case_st0; 2902 goto case; 2903 2904 case TYlong: 2905 case TYulong: 2906 case TYdchar: 2907 if (I32) 2908 goto case_eax; 2909 else 2910 goto case_dxax; 2911 2912 case TYfptr: 2913 case TYhptr: 2914 if (I32) 2915 goto case_edxeax; 2916 else 2917 goto case_dxax; 2918 2919 case TYvptr: 2920 if (I32) 2921 goto case_edxebx; 2922 else 2923 goto case_dxbx; 2924 2925 case TYdouble: 2926 case TYidouble: 2927 case TYdouble_alias: 2928 if (config.exe & EX_flat) 2929 goto case_st0; 2930 if (I32) 2931 goto case_edxeax; 2932 else 2933 goto case_axbxcxdx; 2934 2935 case TYllong: 2936 case TYullong: 2937 assert(I32); 2938 goto case_edxeax; 2939 2940 case TYldouble: 2941 case TYildouble: 2942 goto case_st0; 2943 2944 case TYcfloat: 2945 case TYcdouble: 2946 case TYcldouble: 2947 goto case_st01; 2948 2949 case_ax: 2950 sreturn[7] = 1; 2951 sreturn[8] = 9; // AX 2952 goto L1; 2953 2954 case_eax: 2955 sreturn[7] = 1; 2956 sreturn[8] = 17; // EAX 2957 goto L1; 2958 2959 2960 case_dxax: 2961 sreturn[7] = 2; 2962 sreturn[8] = 11; // DX 2963 sreturn[9] = 9; // AX 2964 goto L1; 2965 2966 case_dxbx: 2967 sreturn[7] = 2; 2968 sreturn[8] = 11; // DX 2969 sreturn[9] = 12; // BX 2970 goto L1; 2971 2972 case_axbxcxdx: 2973 sreturn[7] = 4; 2974 sreturn[8] = 9; // AX 2975 sreturn[9] = 12; // BX 2976 sreturn[10] = 10; // CX 2977 sreturn[11] = 11; // DX 2978 goto L1; 2979 2980 case_edxeax: 2981 sreturn[7] = 2; 2982 sreturn[8] = 19; // EDX 2983 sreturn[9] = 17; // EAX 2984 goto L1; 2985 2986 case_edxebx: 2987 sreturn[7] = 2; 2988 sreturn[8] = 19; // EDX 2989 sreturn[9] = 20; // EBX 2990 goto L1; 2991 2992 case_st0: 2993 sreturn[7] = 1; 2994 sreturn[8] = 128; // ST0 2995 goto L1; 2996 2997 case_st01: 2998 sreturn[7] = 2; 2999 sreturn[8] = 128; // ST0 (imaginary) 3000 sreturn[9] = 129; // ST1 (real) 3001 goto L1; 3002 3003 L1: 3004 style = 1; 3005 u += sreturn[7] + 1; 3006 break; 3007 } 3008 sreturn[6] = style; 3009 3010 TOWORD(sreturn.ptr,u); 3011 TOWORD(sreturn.ptr + 2,S_RETURN); 3012 objmod.write_bytes(SegData[DEBSYM],u + 2,sreturn.ptr); 3013 } 3014 3015 // Put out end scope 3016 { __gshared ushort[2] endproc = [ 2,S_END ]; 3017 3018 objmod.write_bytes(SegData[DEBSYM],(endproc).sizeof,endproc.ptr); 3019 } 3020 3021 cv_outlist(); 3022 } 3023 3024 ////////////////////////////////////////////////////////// 3025 3026 /****************************************** 3027 * Write out data to .OBJ file. 3028 */ 3029 3030 void cv_term() 3031 { 3032 //printf("cv_term(): debtyp.length = %d\n",debtyp.length); 3033 3034 segidx_t typeseg = objmod.seg_debugT(); 3035 3036 switch (config.fulltypes) 3037 { 3038 case CV4: 3039 case CVSYM: 3040 cv_outlist(); 3041 goto case; 3042 case CV8: 3043 objmod.write_bytes(SegData[typeseg],4,&cgcv.signature); 3044 if (debtyp.length != 1 || config.fulltypes == CV8) 3045 { 3046 for (uint u = 0; u < debtyp.length; u++) 3047 { debtyp_t *d = debtyp[u]; 3048 3049 objmod.write_bytes(SegData[typeseg],2 + d.length,cast(char *)d + uint.sizeof); 3050 debtyp_free(d); 3051 } 3052 } 3053 else if (debtyp.length) 3054 { 3055 debtyp_free(debtyp[0]); 3056 } 3057 break; 3058 3059 static if (SYMDEB_TDB) 3060 { 3061 case CVTDB: 3062 cv_outlist(); 3063 static if (1) 3064 { 3065 tdb_term(); 3066 } 3067 else 3068 { 3069 { ubyte *buf; 3070 ubyte *p; 3071 size_t len; 3072 3073 // Calculate size of buffer 3074 len = 4; 3075 for (uint u = 0; u < debtyp.length; u++) 3076 { debtyp_t *d = debtyp[u]; 3077 3078 len += 2 + d.length; 3079 } 3080 3081 // Allocate buffer 3082 buf = malloc(len); 3083 if (!buf) 3084 err_nomem(); // out of memory 3085 3086 // Fill the buffer 3087 TOLONG(buf,cgcv.signature); 3088 p = buf + 4; 3089 for (uint u = 0; u < debtyp.length; u++) 3090 { debtyp_t *d = debtyp[u]; 3091 3092 len = 2 + d.length; 3093 memcpy(p,cast(char *)d + uint.sizeof,len); 3094 p += len; 3095 } 3096 3097 tdb_write(buf,len,debtyp.length); 3098 } 3099 } 3100 break; 3101 } 3102 3103 default: 3104 assert(0); 3105 } 3106 3107 // debtyp.dtor(); // save for later 3108 vec_free(debtypvec); 3109 debtypvec = null; 3110 } 3111 3112 /****************************************** 3113 * Write out symbol table for current function. 3114 */ 3115 3116 static if (TARGET_WINDOS) 3117 { 3118 void cv_func(Funcsym *s) 3119 { 3120 version (SCPP) 3121 { 3122 if (errcnt) // if we had any errors 3123 return; // don't bother putting stuff in .OBJ file 3124 } 3125 3126 //printf("cv_func('%s')\n",s.Sident.ptr); 3127 version (MARS) 3128 { 3129 if (s.Sflags & SFLnodebug) 3130 return; 3131 } 3132 else 3133 { 3134 if (CPP && s.Sfunc.Fflags & Fnodebug) // if don't generate debug info 3135 return; 3136 } 3137 switch (config.fulltypes) 3138 { 3139 case CV4: 3140 case CVSYM: 3141 case CVTDB: 3142 cv4_func(s); 3143 break; 3144 3145 default: 3146 assert(0); 3147 } 3148 } 3149 } 3150 3151 /****************************************** 3152 * Write out symbol table for current function. 3153 */ 3154 3155 static if (TARGET_WINDOS) 3156 { 3157 void cv_outsym(Symbol *s) 3158 { 3159 //printf("cv_outsym('%s')\n",s.Sident.ptr); 3160 symbol_debug(s); 3161 version (MARS) 3162 { 3163 if (s.Sflags & SFLnodebug) 3164 return; 3165 } 3166 switch (config.fulltypes) 3167 { 3168 case CV4: 3169 case CVSYM: 3170 case CVTDB: 3171 cv4_outsym(s); 3172 break; 3173 3174 version (MARS) 3175 { 3176 case CV8: 3177 cv8_outsym(s); 3178 break; 3179 } 3180 3181 default: 3182 assert(0); 3183 } 3184 } 3185 } 3186 3187 /****************************************** 3188 * Return cv type index for a type. 3189 */ 3190 3191 uint cv_typidx(type *t) 3192 { uint ti; 3193 3194 //printf("cv_typidx(%p)\n",t); 3195 switch (config.fulltypes) 3196 { 3197 case CV4: 3198 case CVTDB: 3199 case CVSYM: 3200 case CV8: 3201 ti = cv4_typidx(t); 3202 break; 3203 3204 default: 3205 debug 3206 printf("fulltypes = %d\n",config.fulltypes); 3207 3208 assert(0); 3209 } 3210 return ti; 3211 } 3212 3213 }