1 /** 2 * CodeView 4 symbolic debug info generation 3 * 4 * Compiler implementation of the 5 * $(LINK2 https://www.dlang.org, D programming language). 6 * 7 * Copyright: Copyright (C) 1984-1995 by Symantec 8 * Copyright (C) 2000-2023 by The D Language Foundation, All Rights Reserved 9 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 10 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 11 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/dcgcv.d, backend/dcgcv.d) 12 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/backend/dcgcv.d 13 */ 14 15 module dmd.backend.dcgcv; 16 17 import core.stdc.stdio; 18 import core.stdc.stdlib; 19 import core.stdc.string; 20 21 import dmd.backend.cc; 22 import dmd.backend.cdef; 23 import dmd.backend.cgcv; 24 import dmd.backend.code; 25 import dmd.backend.code_x86; 26 import dmd.backend.cv4; 27 import dmd.backend.dlist; 28 import dmd.backend.dvec; 29 import dmd.backend.el; 30 import dmd.backend.global; 31 import dmd.backend.mem; 32 import dmd.backend.obj; 33 import dmd.backend.symtab; 34 import dmd.backend.ty; 35 import dmd.backend.type; 36 37 import dmd.backend.barray; 38 39 import dmd.common.outbuffer; 40 41 import dmd.backend.dvarstats; 42 43 44 nothrow: 45 @safe: 46 47 @trusted 48 extern (C) void TOOFFSET(void* p, targ_size_t value) 49 { 50 switch (_tysize[TYnptr]) 51 { 52 case 2: *cast(ushort*)p = cast(ushort)value; break; 53 case 4: *cast(uint*) p = cast(uint) value; break; 54 case 8: *cast(ulong*) p = cast(ulong) value; break; 55 default: 56 assert(0); 57 } 58 } 59 60 import dmd.backend.var : ftdbname; 61 62 // Convert from SFL visibilities to CV4 protections 63 uint SFLtoATTR(uint sfl) { return 4 - ((sfl & SFLpmask) >> 5); } 64 65 __gshared 66 { 67 68 /* Dynamic array of debtyp_t's */ 69 private Barray!(debtyp_t*) debtyp; 70 71 private vec_t debtypvec; // vector of used entries 72 enum DEBTYPVECDIM = 16_001; //8009 //3001 // dimension of debtypvec (should be prime) 73 74 enum DEBTYPHASHDIM = 1009; 75 private uint[DEBTYPHASHDIM] debtyphash; 76 77 private OutBuffer *reset_symbuf; // Keep pointers to reset symbols 78 79 @trusted 80 idx_t DEB_NULL() { return cgcv.deb_offset; } // index of null debug type record 81 82 /* This limitation is because of 4K page sizes 83 * in optlink/cv/cvhashes.asm 84 */ 85 enum CVIDMAX = (0xFF0-20); // the -20 is picked by trial and error 86 87 enum LOCATsegrel = 0xC000; 88 89 /* Unfortunately, the fixup stuff is different for EASY OMF and Microsoft */ 90 enum EASY_LCFDoffset = (LOCATsegrel | 0x1404); 91 enum EASY_LCFDpointer = (LOCATsegrel | 0x1800); 92 93 enum LCFD32offset = (LOCATsegrel | 0x2404); 94 enum LCFD32pointer = (LOCATsegrel | 0x2C00); 95 enum LCFD16pointer = (LOCATsegrel | 0x0C00); 96 } 97 98 enum MARS = true; 99 100 /****************************************** 101 * Return number of bytes consumed in OBJ file by a name. 102 */ 103 104 @trusted 105 int cv_stringbytes(const(char)* name) 106 { 107 int len = cast(int)strlen(name); 108 if (config.fulltypes == CV8) 109 return len + 1; 110 if (len > CVIDMAX) 111 len = CVIDMAX; 112 return len + ((len > 255) ? 4 : 1); 113 } 114 115 /****************************************** 116 * Stuff a namestring into p. 117 * Returns: 118 * number of bytes consumed 119 */ 120 121 @trusted 122 int cv_namestring(ubyte *p, const(char)* name, int length = -1) 123 { 124 size_t len = (length >= 0) ? length : strlen(name); 125 if (config.fulltypes == CV8) 126 { 127 size_t numBytesWritten = len + ((length < 0) ? 1 : 0); 128 memcpy(p, name, numBytesWritten); 129 if(config.flags2 & CFG2gms) 130 { 131 for(int i = 0; i < len; i++) 132 { 133 if(p[i] == '.') 134 p[i] = '@'; 135 } 136 } 137 return cast(int)numBytesWritten; 138 } 139 if (len > 255) 140 { p[0] = 0xFF; 141 p[1] = 0; 142 if (len > CVIDMAX) 143 len = CVIDMAX; 144 TOWORD(p + 2,cast(uint)len); 145 memcpy(p + 4,name,len); 146 len += 4; 147 } 148 else 149 { p[0] = cast(ubyte)len; 150 memcpy(p + 1,name,len); 151 len++; 152 } 153 return cast(int)len; 154 } 155 156 /*********************************** 157 * Compute debug register number for symbol s. 158 * Returns: 159 * 0..7 byte registers 160 * 8..15 word registers 161 * 16..23 dword registers 162 */ 163 164 @trusted 165 private int cv_regnum(Symbol *s) 166 { 167 uint reg = s.Sreglsw; 168 if (s.Sclass == SC.pseudo) 169 { 170 } 171 else 172 { 173 assert(reg < 8); 174 assert(s.Sfl == FLreg); 175 switch (type_size(s.Stype)) 176 { 177 case LONGSIZE: 178 case 3: reg += 8; 179 goto case; 180 181 case SHORTSIZE: reg += 8; 182 goto case; 183 184 case CHARSIZE: break; 185 186 case LLONGSIZE: 187 reg += (s.Sregmsw << 8) + (16 << 8) + 16; 188 if (config.fulltypes == CV4) 189 reg += (1 << 8); 190 break; 191 192 default: 193 static if (0) 194 { 195 symbol_print(s); 196 type_print(s.Stype); 197 printf("size = %d\n",type_size(s.Stype)); 198 } 199 assert(0); 200 } 201 } 202 if (config.fulltypes == CV4) 203 reg++; 204 return reg; 205 } 206 207 /*********************************** 208 * Allocate a debtyp_t. 209 */ 210 @trusted 211 debtyp_t * debtyp_alloc(uint length) 212 { 213 debtyp_t *d; 214 uint pad = 0; 215 216 //printf("len = %u, x%x\n", length, length); 217 if (config.fulltypes == CV8) 218 { // length+2 must lie on 4 byte boundary 219 pad = ((length + 2 + 3) & ~3) - (length + 2); 220 length += pad; 221 } 222 223 if (length > ushort.max) 224 err_nomem(); 225 226 const len = debtyp_t.sizeof - (d.data).sizeof + length; 227 debug 228 { 229 d = cast(debtyp_t *) mem_malloc(len /*+ 1*/); 230 memset(d, 0xAA, len); 231 // (cast(char*)d)[len] = 0x2E; 232 } 233 else 234 { 235 d = cast(debtyp_t *) malloc(debtyp_t.sizeof - (d.data).sizeof + length); 236 if (!d) 237 err_nomem(); 238 } 239 d.length = cast(ushort)length; 240 if (pad) 241 { 242 __gshared const ubyte[3] padx = [0xF3, 0xF2, 0xF1]; 243 memcpy(d.data.ptr + length - pad, padx.ptr + 3 - pad, pad); 244 } 245 //printf("debtyp_alloc(%d) = %p\n", length, d); 246 return d; 247 } 248 249 /*********************************** 250 * Free a debtyp_t. 251 */ 252 253 @trusted 254 private void debtyp_free(debtyp_t *d) 255 { 256 //printf("debtyp_free(length = %d, %p)\n", d.length, d); 257 //fflush(stdout); 258 debug 259 { 260 assert(d.length <= ushort.max); 261 uint len = debtyp_t.sizeof - (d.data).sizeof + d.length; 262 // assert((cast(char*)d)[len] == 0x2E); 263 memset(d, 0x55, len); 264 mem_free(d); 265 } 266 else 267 { 268 free(d); 269 } 270 } 271 272 static if (0) 273 { 274 void debtyp_check(debtyp_t *d,int linnum) 275 { int i; 276 __gshared char c; 277 278 //printf("linnum = %d\n",linnum); 279 //printf(" length = %d\n",d.length); 280 for (i = 0; i < d.length; i++) 281 c = d.data.ptr[i]; 282 } 283 284 void debtyp_check(debtyp_t* d) { debtyp_check(d,__LINE__); } 285 } 286 else 287 { 288 void debtyp_check(debtyp_t* d) { } 289 } 290 291 /*********************************** 292 * Search for debtyp_t in debtyp[]. If it is there, return the index 293 * of it, and free d. Otherwise, add it. 294 * Returns: 295 * index in debtyp[] 296 */ 297 298 @trusted 299 idx_t cv_debtyp(debtyp_t *d) 300 { 301 uint hashi; 302 303 assert(d); 304 const length = d.length; 305 //printf("length = %3d\n",length); 306 if (length) 307 { 308 uint hash = length; 309 if (length >= uint.sizeof) 310 { 311 // Hash consists of the sum of the first 4 bytes with the last 4 bytes 312 union U { ubyte* cp; uint* up; } 313 U un = void; 314 un.cp = d.data.ptr; 315 hash += *un.up; 316 un.cp += length - uint.sizeof; 317 hash += *un.up; 318 } 319 hashi = hash % DEBTYPHASHDIM; 320 hash %= DEBTYPVECDIM; 321 //printf(" hashi = %d", hashi); 322 323 if (vec_testbit(hash,debtypvec)) 324 { 325 //printf(" test"); 326 // Threaded list is much faster 327 for (uint u = debtyphash[hashi]; u; u = debtyp[u].prev) 328 //for (uint u = debtyp.length; u--; ) 329 { 330 if (length == debtyp[u].length && 331 memcmp(d.data.ptr,debtyp[u].data.ptr,length) == 0) 332 { debtyp_free(d); 333 //printf(" match %d\n",u); 334 return u + cgcv.deb_offset; 335 } 336 } 337 } 338 else 339 vec_setbit(hash,debtypvec); 340 } 341 else 342 hashi = 1; 343 //printf(" add %d\n",debtyp.length); 344 d.prev = debtyphash[hashi]; 345 debtyphash[hashi] = cast(uint)debtyp.length; 346 347 /* It's not already in the array, so add it */ 348 debtyp.push(d); 349 350 return cast(uint)debtyp.length - 1 + cgcv.deb_offset; 351 } 352 353 @trusted 354 idx_t cv_numdebtypes() 355 { 356 return cast(idx_t)debtyp.length; 357 } 358 359 /**************************** 360 * Store a null record at DEB_NULL. 361 */ 362 363 @trusted 364 void cv_init() 365 { debtyp_t *d; 366 367 //printf("cv_init()\n"); 368 369 // Initialize statics 370 debtyp.setLength(0); 371 if (!ftdbname) 372 ftdbname = cast(char *)"symc.tdb".ptr; 373 374 memset(&cgcv,0,cgcv.sizeof); 375 cgcv.sz_idx = 2; 376 cgcv.LCFDoffset = LCFD32offset; 377 cgcv.LCFDpointer = LCFD16pointer; 378 379 debtypvec = vec_calloc(DEBTYPVECDIM); 380 memset(debtyphash.ptr,0,debtyphash.sizeof); 381 382 if (reset_symbuf) 383 { 384 Symbol **p = cast(Symbol **)reset_symbuf.buf; 385 const size_t n = reset_symbuf.length() / (Symbol *).sizeof; 386 for (size_t i = 0; i < n; ++i) 387 symbol_reset(p[i]); 388 reset_symbuf.reset(); 389 } 390 else 391 { 392 reset_symbuf = cast(OutBuffer*) calloc(1, OutBuffer.sizeof); 393 if (!reset_symbuf) 394 err_nomem(); 395 reset_symbuf.reserve(10 * (Symbol*).sizeof); 396 } 397 398 /* Reset for different OBJ file formats */ 399 if (I32 || I64) 400 { 401 // Adjust values in old CV tables for 32 bit ints 402 dttab[TYenum] = dttab[TYlong]; 403 dttab[TYint] = dttab[TYlong]; 404 dttab[TYuint] = dttab[TYulong]; 405 406 // Adjust Codeview 4 values for 32 bit ints and 32 bit pointer offsets 407 dttab4[TYenum] = 0x74; 408 dttab4[TYint] = 0x74; 409 dttab4[TYuint] = 0x75; 410 if (I64) 411 { 412 dttab4[TYptr] = 0x600; 413 dttab4[TYnptr] = 0x600; 414 dttab4[TYsptr] = 0x600; 415 dttab4[TYimmutPtr] = 0x600; 416 dttab4[TYsharePtr] = 0x600; 417 dttab4[TYrestrictPtr] = 0x600; 418 dttab4[TYfgPtr] = 0x600; 419 } 420 else 421 { 422 dttab4[TYptr] = 0x400; 423 dttab4[TYsptr] = 0x400; 424 dttab4[TYnptr] = 0x400; 425 dttab4[TYimmutPtr] = 0x400; 426 dttab4[TYsharePtr] = 0x400; 427 dttab4[TYrestrictPtr] = 0x400; 428 dttab4[TYfgPtr] = 0x400; 429 } 430 dttab4[TYcptr] = 0x400; 431 dttab4[TYfptr] = 0x500; 432 433 if (config.flags & CFGeasyomf) 434 { cgcv.LCFDoffset = EASY_LCFDoffset; 435 cgcv.LCFDpointer = EASY_LCFDpointer; 436 assert(config.fulltypes == CVOLD); 437 } 438 else 439 cgcv.LCFDpointer = LCFD32pointer; 440 441 if (config.exe & EX_flat) 442 cgcv.FD_code = 0x10; 443 } 444 445 if (config.fulltypes >= CV4) 446 { int flags; 447 __gshared ushort[5] memmodel = [0,0x100,0x20,0x120,0x120]; 448 char[1 + (VERSION).sizeof] version_; 449 ubyte[8 + (version_).sizeof] debsym; 450 451 // Put out signature indicating CV4 format 452 switch (config.fulltypes) 453 { 454 case CV4: 455 cgcv.signature = 1; 456 break; 457 458 case CV8: 459 cgcv.signature = 4; 460 break; 461 462 default: 463 { const(char)* x = "1MYS"; 464 cgcv.signature = *cast(int *) x; 465 break; 466 } 467 } 468 469 cgcv.deb_offset = 0x1000; 470 471 if (config.fulltypes == CV8) 472 { cgcv.sz_idx = 4; 473 return; // figure out rest later 474 } 475 476 if (config.fulltypes >= CVSYM) 477 { cgcv.sz_idx = 4; 478 if (!(config.flags2 & CFG2phgen)) 479 cgcv.deb_offset = 0x80000000; 480 } 481 482 objmod.write_bytes(SegData[DEBSYM],(&cgcv.signature)[0 .. 1]); 483 484 // Allocate an LF_ARGLIST with no arguments 485 if (config.fulltypes == CV4) 486 { d = debtyp_alloc(4); 487 TOWORD(d.data.ptr,LF_ARGLIST); 488 TOWORD(d.data.ptr + 2,0); 489 } 490 else 491 { d = debtyp_alloc(6); 492 TOWORD(d.data.ptr,LF_ARGLIST); 493 TOLONG(d.data.ptr + 2,0); 494 } 495 496 // Put out S_COMPILE record 497 TOWORD(debsym.ptr + 2,S_COMPILE); 498 switch (config.target_cpu) 499 { 500 case TARGET_8086: debsym[4] = 0; break; 501 case TARGET_80286: debsym[4] = 2; break; 502 case TARGET_80386: debsym[4] = 3; break; 503 case TARGET_80486: debsym[4] = 4; break; 504 505 case TARGET_Pentium: 506 case TARGET_PentiumMMX: 507 debsym[4] = 5; break; 508 509 case TARGET_PentiumPro: 510 case TARGET_PentiumII: 511 debsym[4] = 6; break; 512 default: assert(0); 513 } 514 debsym[5] = (CPP != 0); // 0==C, 1==C++ 515 flags = (config.inline8087) ? (0<<3) : (1<<3); 516 if (I32) 517 flags |= 0x80; // 32 bit addresses 518 flags |= memmodel[config.memmodel]; 519 TOWORD(debsym.ptr + 6,flags); 520 version_[0] = 'Z'; 521 strcpy(version_.ptr + 1,VERSION); 522 cv_namestring(debsym.ptr + 8,version_.ptr); 523 TOWORD(debsym.ptr,6 + (version_).sizeof); 524 objmod.write_bytes(SegData[DEBSYM], debsym[0 .. 8 + (version_).sizeof]); 525 526 } 527 else 528 { 529 assert(0); 530 } 531 if (config.fulltypes == CVTDB) 532 cgcv.deb_offset = cv_debtyp(d); 533 else 534 cv_debtyp(d); 535 } 536 537 /////////////////////////// CodeView 4 /////////////////////////////// 538 539 /*********************************** 540 * Return number of bytes required to store a numeric leaf. 541 */ 542 543 uint cv4_numericbytes(uint value) 544 { uint u; 545 546 if (value < 0x8000) 547 u = 2; 548 else if (value < 0x10000) 549 u = 4; 550 else 551 u = 6; 552 return u; 553 } 554 555 /******************************** 556 * Store numeric leaf. 557 * Must use exact same number of bytes as cv4_numericbytes(). 558 */ 559 560 @trusted 561 void cv4_storenumeric(ubyte *p, uint value) 562 { 563 if (value < 0x8000) 564 TOWORD(p,value); 565 else if (value < 0x10000) 566 { TOWORD(p,LF_USHORT); 567 p += 2; 568 TOWORD(p,value); 569 } 570 else 571 { TOWORD(p,LF_ULONG); 572 *cast(targ_ulong *)(p + 2) = cast(uint) value; 573 } 574 } 575 576 /*********************************** 577 * Return number of bytes required to store a signed numeric leaf. 578 * Params: 579 * value = value to store 580 * Returns: 581 * number of bytes required for storing value 582 */ 583 uint cv4_signednumericbytes(int value) 584 { 585 uint u; 586 if (value >= 0 && value < 0x8000) 587 u = 2; 588 else if (value == cast(short)value) 589 u = 4; 590 else 591 u = 6; 592 return u; 593 } 594 595 /******************************** 596 * Store signed numeric leaf. 597 * Must use exact same number of bytes as cv4_signednumericbytes(). 598 * Params: 599 * p = address where to store value 600 * value = value to store 601 */ 602 @trusted 603 void cv4_storesignednumeric(ubyte *p, int value) 604 { 605 if (value >= 0 && value < 0x8000) 606 TOWORD(p, value); 607 else if (value == cast(short)value) 608 { 609 TOWORD(p, LF_SHORT); 610 TOWORD(p + 2, value); 611 } 612 else 613 { 614 TOWORD(p,LF_LONG); 615 TOLONG(p + 2, value); 616 } 617 } 618 619 /********************************* 620 * Generate a type index for a parameter list. 621 */ 622 623 @trusted 624 idx_t cv4_arglist(type *t,uint *pnparam) 625 { uint u; 626 uint nparam; 627 idx_t paramidx; 628 debtyp_t *d; 629 param_t *p; 630 631 // Compute nparam, number of parameters 632 nparam = 0; 633 for (p = t.Tparamtypes; p; p = p.Pnext) 634 nparam++; 635 *pnparam = nparam; 636 637 // Construct an LF_ARGLIST of those parameters 638 if (nparam == 0) 639 { 640 if (config.fulltypes == CV8) 641 { 642 d = debtyp_alloc(2 + 4 + 4); 643 TOWORD(d.data.ptr,LF_ARGLIST_V2); 644 TOLONG(d.data.ptr + 2,1); 645 TOLONG(d.data.ptr + 6,0); 646 paramidx = cv_debtyp(d); 647 } 648 else 649 paramidx = DEB_NULL; 650 } 651 else 652 { 653 switch (config.fulltypes) 654 { 655 case CV8: 656 d = debtyp_alloc(2 + 4 + nparam * 4); 657 TOWORD(d.data.ptr,LF_ARGLIST_V2); 658 TOLONG(d.data.ptr + 2,nparam); 659 660 p = t.Tparamtypes; 661 for (u = 0; u < nparam; u++) 662 { TOLONG(d.data.ptr + 6 + u * 4,cv4_typidx(p.Ptype)); 663 p = p.Pnext; 664 } 665 break; 666 667 case CV4: 668 d = debtyp_alloc(2 + 2 + nparam * 2); 669 TOWORD(d.data.ptr,LF_ARGLIST); 670 TOWORD(d.data.ptr + 2,nparam); 671 672 p = t.Tparamtypes; 673 for (u = 0; u < nparam; u++) 674 { TOWORD(d.data.ptr + 4 + u * 2,cv4_typidx(p.Ptype)); 675 p = p.Pnext; 676 } 677 break; 678 679 default: 680 d = debtyp_alloc(2 + 4 + nparam * 4); 681 TOWORD(d.data.ptr,LF_ARGLIST); 682 TOLONG(d.data.ptr + 2,nparam); 683 684 p = t.Tparamtypes; 685 for (u = 0; u < nparam; u++) 686 { TOLONG(d.data.ptr + 6 + u * 4,cv4_typidx(p.Ptype)); 687 p = p.Pnext; 688 } 689 break; 690 } 691 paramidx = cv_debtyp(d); 692 } 693 return paramidx; 694 } 695 696 /**************************** 697 * Return type index of struct. 698 * Input: 699 * s struct tag symbol 700 * flags 701 * 0 generate a reference to s 702 * 1 just saw the definition of s 703 * 2 saw key function for class s 704 * 3 no longer have a key function for class s 705 */ 706 707 @trusted 708 idx_t cv4_struct(Classsym *s,int flags) 709 { targ_size_t size; 710 debtyp_t* d,dt; 711 uint len; 712 uint nfields,fnamelen; 713 idx_t typidx; 714 type *t; 715 struct_t *st; 716 const(char)* id; 717 uint numidx; 718 uint leaf; 719 uint property; 720 uint attribute; 721 ubyte *p; 722 int refonly; 723 int i; 724 int count; // COUNT field in LF_CLASS 725 726 symbol_debug(s); 727 assert(config.fulltypes >= CV4); 728 st = s.Sstruct; 729 if (st.Sflags & STRanonymous) // if anonymous class/union 730 return 0; 731 732 //printf("cv4_struct(%s,%d)\n",s.Sident.ptr,flags); 733 t = s.Stype; 734 //printf("t = %p, Tflags = x%x\n", t, t.Tflags); 735 type_debug(t); 736 737 // Determine if we should do a reference or a definition 738 refonly = 1; // assume reference only 739 if (MARS || t.Tflags & TFsizeunknown || st.Sflags & STRoutdef) 740 { 741 //printf("ref only\n"); 742 } 743 else 744 { 745 // We have a definition that we have not put out yet 746 switch (flags) 747 { 748 case 0: // reference to s 749 refonly = 0; 750 break; 751 752 case 1: // saw def of s 753 if (!s.Stypidx) // if not forward referenced 754 return 0; 755 break; 756 757 default: 758 assert(0); 759 } 760 } 761 762 if (MARS || refonly) 763 { 764 if (s.Stypidx) // if reference already generated 765 { //assert(s.Stypidx - cgcv.deb_offset < debtyp.length); 766 return s.Stypidx; // use already existing reference 767 } 768 size = 0; 769 property = 0x80; // class is forward referenced 770 } 771 else 772 { size = type_size(t); 773 st.Sflags |= STRoutdef; 774 property = 0; 775 } 776 777 id = prettyident(s); 778 if (config.fulltypes == CV4) 779 { numidx = (st.Sflags & STRunion) ? 8 : 12; 780 len = numidx + cv4_numericbytes(cast(uint)size); 781 d = debtyp_alloc(len + cv_stringbytes(id)); 782 cv4_storenumeric(d.data.ptr + numidx,cast(uint)size); 783 } 784 else 785 { numidx = (st.Sflags & STRunion) ? 10 : 18; 786 len = numidx + 4; 787 d = debtyp_alloc(len + cv_stringbytes(id)); 788 TOLONG(d.data.ptr + numidx,cast(uint)size); 789 } 790 len += cv_namestring(d.data.ptr + len,id); 791 switch (s.Sclass) 792 { 793 case SC.struct_: 794 leaf = LF_STRUCTURE; 795 if (st.Sflags & STRunion) 796 { leaf = LF_UNION; 797 break; 798 } 799 if (st.Sflags & STRclass) 800 leaf = LF_CLASS; 801 goto L1; 802 L1: 803 if (config.fulltypes == CV4) 804 TOWORD(d.data.ptr + 8,0); // dList 805 else 806 TOLONG(d.data.ptr + 10,0); // dList 807 if (CPP) 808 { 809 } 810 else 811 { 812 if (config.fulltypes == CV4) 813 TOWORD(d.data.ptr + 10,0); // vshape 814 else 815 TOLONG(d.data.ptr + 14,0); // vshape 816 } 817 break; 818 819 default: 820 symbol_print(s); 821 assert(0); 822 } 823 TOWORD(d.data.ptr,leaf); 824 825 // Assign a number to prevent infinite recursion if a struct member 826 // references the same struct. 827 if (config.fulltypes == CVTDB) 828 { 829 } 830 else 831 { 832 d.length = 0; // so cv_debtyp() will allocate new 833 s.Stypidx = cv_debtyp(d); 834 d.length = cast(ushort)len; // restore length 835 } 836 reset_symbuf.write((&s)[0 .. 1]); 837 838 if (refonly) // if reference only 839 { 840 //printf("refonly\n"); 841 TOWORD(d.data.ptr + 2,0); // count: number of fields is 0 842 if (config.fulltypes == CV4) 843 { TOWORD(d.data.ptr + 4,0); // field list is 0 844 TOWORD(d.data.ptr + 6,property); 845 } 846 else 847 { TOLONG(d.data.ptr + 6,0); // field list is 0 848 TOWORD(d.data.ptr + 4,property); 849 } 850 return s.Stypidx; 851 } 852 853 // Compute the number of fields, and the length of the fieldlist record 854 nfields = 0; 855 fnamelen = 2; 856 count = nfields; 857 foreach (sl; ListRange(st.Sfldlst)) 858 { Symbol *sf = list_symbol(sl); 859 targ_size_t offset; 860 861 symbol_debug(sf); 862 const(char)* sfid = sf.Sident.ptr; 863 switch (sf.Sclass) 864 { 865 case SC.member: 866 case SC.field: 867 if (CPP && sf == s.Sstruct.Svptr) 868 fnamelen += ((config.fulltypes == CV4) ? 4 : 8); 869 else 870 { offset = sf.Smemoff; 871 fnamelen += ((config.fulltypes == CV4) ? 6 : 8) + 872 cv4_numericbytes(cast(uint)offset) + cv_stringbytes(sfid); 873 } 874 break; 875 876 default: 877 continue; 878 } 879 nfields++; 880 count++; 881 } 882 883 TOWORD(d.data.ptr + 2,count); 884 if (config.fulltypes == CV4) 885 TOWORD(d.data.ptr + 6,property); 886 else 887 TOWORD(d.data.ptr + 4,property); 888 889 // Generate fieldlist type record 890 dt = debtyp_alloc(fnamelen); 891 p = dt.data.ptr; 892 TOWORD(p,LF_FIELDLIST); 893 894 // And fill it in 895 p += 2; 896 foreach (sl; ListRange(s.Sstruct.Sfldlst)) 897 { Symbol *sf = list_symbol(sl); 898 targ_size_t offset; 899 900 symbol_debug(sf); 901 const(char)* sfid = sf.Sident.ptr; 902 switch (sf.Sclass) 903 { 904 case SC.field: 905 { debtyp_t *db; 906 907 if (config.fulltypes == CV4) 908 { db = debtyp_alloc(6); 909 TOWORD(db.data.ptr,LF_BITFIELD); 910 db.data.ptr[2] = sf.Swidth; 911 db.data.ptr[3] = sf.Sbit; 912 TOWORD(db.data.ptr + 4,cv4_symtypidx(sf)); 913 } 914 else 915 { db = debtyp_alloc(8); 916 TOWORD(db.data.ptr,LF_BITFIELD); 917 db.data.ptr[6] = sf.Swidth; 918 db.data.ptr[7] = sf.Sbit; 919 TOLONG(db.data.ptr + 2,cv4_symtypidx(sf)); 920 } 921 typidx = cv_debtyp(db); 922 goto L3; 923 } 924 925 case SC.member: 926 typidx = cv4_symtypidx(sf); 927 L3: 928 offset = sf.Smemoff; 929 TOWORD(p,LF_MEMBER); 930 attribute = 0; 931 if (config.fulltypes == CV4) 932 { TOWORD(p + 2,typidx); 933 TOWORD(p + 4,attribute); 934 p += 6; 935 } 936 else 937 { TOLONG(p + 4,typidx); 938 TOWORD(p + 2,attribute); 939 p += 8; 940 } 941 cv4_storenumeric(p,cast(uint)offset); 942 p += cv4_numericbytes(cast(uint)offset); 943 p += cv_namestring(p,sfid); 944 break; 945 946 default: 947 continue; 948 } 949 } 950 //printf("fnamelen = %d, p-dt.data = %d\n",fnamelen,p-dt.data); 951 assert(p - dt.data.ptr == fnamelen); 952 if (config.fulltypes == CV4) 953 TOWORD(d.data.ptr + 4,cv_debtyp(dt)); 954 else 955 TOLONG(d.data.ptr + 6,cv_debtyp(dt)); 956 957 return s.Stypidx; 958 } 959 960 @trusted 961 private uint cv4_fwdenum(type* t) 962 { 963 Symbol* s = t.Ttag; 964 965 // write a forward reference enum record that is enough for the linker to 966 // fold with original definition from EnumDeclaration 967 uint bty = dttab4[tybasic(t.Tnext.Tty)]; 968 const id = prettyident(s); 969 uint len = config.fulltypes == CV8 ? 14 : 10; 970 debtyp_t* d = debtyp_alloc(len + cv_stringbytes(id)); 971 switch (config.fulltypes) 972 { 973 case CV8: 974 TOWORD(d.data.ptr, LF_ENUM_V3); 975 TOLONG(d.data.ptr + 2, 0); // count 976 TOWORD(d.data.ptr + 4, 0x80); // property : forward reference 977 TOLONG(d.data.ptr + 6, bty); // memtype 978 TOLONG(d.data.ptr + 10, 0); // fieldlist 979 break; 980 981 case CV4: 982 TOWORD(d.data.ptr,LF_ENUM); 983 TOWORD(d.data.ptr + 2, 0); // count 984 TOWORD(d.data.ptr + 4, bty); // memtype 985 TOLONG(d.data.ptr + 6, 0); // fieldlist 986 TOWORD(d.data.ptr + 8, 0x80); // property : forward reference 987 break; 988 989 default: 990 assert(0); 991 } 992 cv_namestring(d.data.ptr + len, id); 993 s.Stypidx = cv_debtyp(d); 994 return s.Stypidx; 995 } 996 997 /************************************************ 998 * Return 'calling convention' type of function. 999 */ 1000 1001 ubyte cv4_callconv(type *t) 1002 { ubyte call; 1003 1004 switch (tybasic(t.Tty)) 1005 { 1006 case TYffunc: call = 1; break; 1007 case TYfpfunc: call = 3; break; 1008 case TYf16func: call = 3; break; 1009 case TYfsfunc: call = 8; break; 1010 case TYnsysfunc: call = 9; break; 1011 case TYfsysfunc: call = 10; break; 1012 case TYnfunc: call = 0; break; 1013 case TYnpfunc: call = 2; break; 1014 case TYnsfunc: call = 7; break; 1015 case TYifunc: call = 1; break; 1016 case TYjfunc: call = 2; break; 1017 case TYmfunc: call = 11; break; // this call 1018 default: 1019 assert(0); 1020 } 1021 return call; 1022 } 1023 1024 /********************************************** 1025 * Return type index for the type of a symbol. 1026 */ 1027 private uint cv4_symtypidx(Symbol *s) 1028 { 1029 return cv4_typidx(s.Stype); 1030 } 1031 1032 /*********************************** 1033 * Return CV4 type index for a type. 1034 */ 1035 1036 @trusted 1037 uint cv4_typidx(type *t) 1038 { uint typidx; 1039 uint u; 1040 uint next; 1041 uint key; 1042 debtyp_t *d; 1043 targ_size_t size; 1044 tym_t tym; 1045 tym_t tycv; 1046 tym_t tymnext; 1047 type *tv; 1048 uint dt; 1049 uint attribute; 1050 ubyte call; 1051 1052 //printf("cv4_typidx(%p)\n",t); 1053 if (!t) 1054 return dttab4[TYint]; // assume int 1055 type_debug(t); 1056 next = cv4_typidx(t.Tnext); 1057 tycv = t.Tty; 1058 tym = tybasic(tycv); 1059 tycv &= mTYconst | mTYvolatile | mTYimmutable; 1060 attribute = 0; 1061 L1: 1062 dt = dttab4[tym]; 1063 switch (tym) 1064 { 1065 case TYllong: 1066 if (t.Tnext) 1067 goto Ldelegate; 1068 assert(dt); 1069 typidx = dt; 1070 break; 1071 1072 case TYullong: 1073 if (t.Tnext) 1074 goto Ldarray; 1075 assert(dt); 1076 typidx = dt; 1077 break; 1078 1079 case TYvoid: 1080 case TYnoreturn: 1081 case TYchar: 1082 case TYschar: 1083 case TYuchar: 1084 case TYchar16: 1085 case TYshort: 1086 case TYushort: 1087 case TYint: 1088 case TYuint: 1089 case TYulong: 1090 case TYlong: 1091 case TYfloat: 1092 case TYdouble: 1093 case TYdouble_alias: 1094 case TYldouble: 1095 case TYifloat: 1096 case TYidouble: 1097 case TYildouble: 1098 case TYcfloat: 1099 case TYcdouble: 1100 case TYcldouble: 1101 case TYbool: 1102 case TYwchar_t: 1103 case TYdchar: 1104 assert(dt); 1105 typidx = dt; 1106 break; 1107 1108 case TYnptr: 1109 case TYimmutPtr: 1110 case TYsharePtr: 1111 case TYrestrictPtr: 1112 if (t.Tkey) 1113 goto Laarray; 1114 goto Lptr; 1115 case TYsptr: 1116 case TYcptr: 1117 case TYfgPtr: 1118 Lptr: 1119 attribute |= I32 ? 10 : 0; goto L2; 1120 1121 case TYfptr: 1122 case TYvptr: attribute |= I32 ? 11 : 1; goto L2; 1123 case TYhptr: attribute |= 2; goto L2; 1124 1125 L2: 1126 if (config.fulltypes == CV4) 1127 { 1128 // This is a hack to duplicate bugs in VC, so that the VC 1129 // debugger will work. 1130 tymnext = t.Tnext ? t.Tnext.Tty : TYint; 1131 if (tymnext & (mTYconst | mTYimmutable | mTYvolatile) && 1132 !tycv && 1133 tyarithmetic(tymnext) && 1134 !(attribute & 0xE0) 1135 ) 1136 { 1137 typidx = dt | dttab4[tybasic(tymnext)]; 1138 break; 1139 } 1140 } 1141 if ((next & 0xFF00) == 0 && !(attribute & 0xE0)) 1142 typidx = next | dt; 1143 else 1144 { 1145 if (tycv & (mTYconst | mTYimmutable)) 1146 attribute |= 0x400; 1147 if (tycv & mTYvolatile) 1148 attribute |= 0x200; 1149 tycv = 0; 1150 switch (config.fulltypes) 1151 { 1152 case CV4: 1153 d = debtyp_alloc(6); 1154 TOWORD(d.data.ptr,LF_POINTER); 1155 TOWORD(d.data.ptr + 2,attribute); 1156 TOWORD(d.data.ptr + 4,next); 1157 break; 1158 1159 case CV8: 1160 d = debtyp_alloc(10); 1161 TOWORD(d.data.ptr,0x1002); 1162 TOLONG(d.data.ptr + 2,next); 1163 // see https://github.com/Microsoft/microsoft-pdb/blob/master/include/cvinfo.h#L1514 1164 // add size and pointer type (PTR_64 or PTR_NEAR32) 1165 attribute |= (I64 ? (8 << 13) | 0xC : (4 << 13) | 0xA); 1166 // convert reference to r-value reference to remove & from type display in debugger 1167 if (attribute & 0x20) 1168 attribute |= 0x80; 1169 TOLONG(d.data.ptr + 6,attribute); 1170 break; 1171 1172 default: 1173 d = debtyp_alloc(10); 1174 TOWORD(d.data.ptr,LF_POINTER); 1175 TOLONG(d.data.ptr + 2,attribute); 1176 TOLONG(d.data.ptr + 6,next); 1177 break; 1178 } 1179 typidx = cv_debtyp(d); 1180 } 1181 break; 1182 1183 Ldarray: 1184 switch (config.fulltypes) 1185 { 1186 case CV8: 1187 { 1188 typidx = cv8_darray(t, next); 1189 break; 1190 } 1191 case CV4: 1192 static if (1) 1193 { 1194 d = debtyp_alloc(12); 1195 TOWORD(d.data.ptr, LF_OEM); 1196 TOWORD(d.data.ptr + 2, OEM); 1197 TOWORD(d.data.ptr + 4, 1); // 1 = dynamic array 1198 TOWORD(d.data.ptr + 6, 2); // count of type indices to follow 1199 TOWORD(d.data.ptr + 8, 0x12); // index type, T_LONG 1200 TOWORD(d.data.ptr + 10, next); // element type 1201 } 1202 else 1203 { 1204 d = debtyp_alloc(6); 1205 TOWORD(d.data.ptr,LF_DYN_ARRAY); 1206 TOWORD(d.data.ptr + 2, 0x12); // T_LONG 1207 TOWORD(d.data.ptr + 4, next); 1208 } 1209 typidx = cv_debtyp(d); 1210 break; 1211 1212 default: 1213 assert(0); 1214 } 1215 1216 break; 1217 1218 Laarray: 1219 key = cv4_typidx(t.Tkey); 1220 switch (config.fulltypes) 1221 { 1222 case CV8: 1223 typidx = cv8_daarray(t, key, next); 1224 break; 1225 1226 case CV4: 1227 static if (1) 1228 { 1229 d = debtyp_alloc(12); 1230 TOWORD(d.data.ptr, LF_OEM); 1231 TOWORD(d.data.ptr + 2, OEM); 1232 TOWORD(d.data.ptr + 4, 2); // 2 = associative array 1233 TOWORD(d.data.ptr + 6, 2); // count of type indices to follow 1234 TOWORD(d.data.ptr + 8, key); // key type 1235 TOWORD(d.data.ptr + 10, next); // element type 1236 } 1237 else 1238 { 1239 d = debtyp_alloc(6); 1240 TOWORD(d.data.ptr,LF_ASSOC_ARRAY); 1241 TOWORD(d.data.ptr + 2, key); // key type 1242 TOWORD(d.data.ptr + 4, next); // element type 1243 } 1244 typidx = cv_debtyp(d); 1245 break; 1246 1247 default: 1248 assert(0); 1249 } 1250 break; 1251 1252 Ldelegate: 1253 switch (config.fulltypes) 1254 { 1255 case CV8: 1256 typidx = cv8_ddelegate(t, next); 1257 break; 1258 1259 case CV4: 1260 tv = type_fake(TYnptr); 1261 tv.Tcount++; 1262 key = cv4_typidx(tv); 1263 type_free(tv); 1264 static if (1) 1265 { 1266 d = debtyp_alloc(12); 1267 TOWORD(d.data.ptr, LF_OEM); 1268 TOWORD(d.data.ptr + 2, OEM); 1269 TOWORD(d.data.ptr + 4, 3); // 3 = delegate 1270 TOWORD(d.data.ptr + 6, 2); // count of type indices to follow 1271 TOWORD(d.data.ptr + 8, key); // type of 'this', which is void* 1272 TOWORD(d.data.ptr + 10, next); // function type 1273 } 1274 else 1275 { 1276 d = debtyp_alloc(6); 1277 TOWORD(d.data.ptr,LF_DELEGATE); 1278 TOWORD(d.data.ptr + 2, key); // type of 'this', which is void* 1279 TOWORD(d.data.ptr + 4, next); // function type 1280 } 1281 typidx = cv_debtyp(d); 1282 break; 1283 1284 default: 1285 assert(0); 1286 } 1287 break; 1288 1289 case TYcent: 1290 if (t.Tnext) 1291 goto Ldelegate; 1292 assert(dt); 1293 typidx = dt; 1294 break; 1295 1296 case TYucent: 1297 if (t.Tnext) 1298 goto Ldarray; 1299 assert(dt); 1300 typidx = dt; 1301 break; 1302 1303 case TYarray: 1304 { if (t.Tflags & TFsizeunknown) 1305 size = 0; // don't complain if don't know size 1306 else 1307 size = type_size(t); 1308 Larray: 1309 u = cv4_numericbytes(cast(uint)size); 1310 uint idxtype = I32 ? 0x12 : 0x11; // T_LONG : T_SHORT 1311 if (I64) 1312 idxtype = 0x23; // T_UQUAD 1313 if(next == dttab4[TYvoid]) // do not encode void[n], this confuses the debugger 1314 next = dttab4[TYuchar]; // use ubyte instead 1315 switch (config.fulltypes) 1316 { 1317 case CV8: 1318 d = debtyp_alloc(10 + u + 1); 1319 TOWORD(d.data.ptr,0x1503); 1320 TOLONG(d.data.ptr + 2,next); 1321 TOLONG(d.data.ptr + 6,idxtype); 1322 d.data.ptr[10 + u] = 0; // no name 1323 cv4_storenumeric(d.data.ptr + 10,cast(uint)size); 1324 break; 1325 1326 case CV4: 1327 d = debtyp_alloc(6 + u + 1); 1328 TOWORD(d.data.ptr,LF_ARRAY); 1329 TOWORD(d.data.ptr + 2,next); 1330 TOWORD(d.data.ptr + 4,idxtype); 1331 d.data.ptr[6 + u] = 0; // no name 1332 cv4_storenumeric(d.data.ptr + 6,cast(uint)size); 1333 break; 1334 1335 default: 1336 d = debtyp_alloc(10 + u + 1); 1337 TOWORD(d.data.ptr,LF_ARRAY); 1338 TOLONG(d.data.ptr + 2,next); 1339 TOLONG(d.data.ptr + 6,idxtype); 1340 d.data.ptr[10 + u] = 0; // no name 1341 cv4_storenumeric(d.data.ptr + 10,cast(uint)size); 1342 break; 1343 } 1344 typidx = cv_debtyp(d); 1345 break; 1346 } 1347 1348 case TYffunc: 1349 case TYfpfunc: 1350 case TYf16func: 1351 case TYfsfunc: 1352 case TYnsysfunc: 1353 case TYfsysfunc: 1354 case TYnfunc: 1355 case TYnpfunc: 1356 case TYnsfunc: 1357 case TYmfunc: 1358 case TYjfunc: 1359 case TYifunc: 1360 { 1361 param_t *p; 1362 uint nparam; 1363 idx_t paramidx; 1364 1365 call = cv4_callconv(t); 1366 paramidx = cv4_arglist(t,&nparam); 1367 1368 // Construct an LF_PROCEDURE 1369 switch (config.fulltypes) 1370 { 1371 case CV8: 1372 d = debtyp_alloc(2 + 4 + 1 + 1 + 2 + 4); 1373 TOWORD(d.data.ptr,LF_PROCEDURE_V2); 1374 TOLONG(d.data.ptr + 2,next); // return type 1375 d.data.ptr[6] = call; 1376 d.data.ptr[7] = 0; // reserved 1377 TOWORD(d.data.ptr + 8,nparam); 1378 TOLONG(d.data.ptr + 10,paramidx); 1379 break; 1380 1381 case CV4: 1382 d = debtyp_alloc(2 + 2 + 1 + 1 + 2 + 2); 1383 TOWORD(d.data.ptr,LF_PROCEDURE); 1384 TOWORD(d.data.ptr + 2,next); // return type 1385 d.data.ptr[4] = call; 1386 d.data.ptr[5] = 0; // reserved 1387 TOWORD(d.data.ptr + 6,nparam); 1388 TOWORD(d.data.ptr + 8,paramidx); 1389 break; 1390 1391 default: 1392 d = debtyp_alloc(2 + 4 + 1 + 1 + 2 + 4); 1393 TOWORD(d.data.ptr,LF_PROCEDURE); 1394 TOLONG(d.data.ptr + 2,next); // return type 1395 d.data.ptr[6] = call; 1396 d.data.ptr[7] = 0; // reserved 1397 TOWORD(d.data.ptr + 8,nparam); 1398 TOLONG(d.data.ptr + 10,paramidx); 1399 break; 1400 } 1401 1402 typidx = cv_debtyp(d); 1403 break; 1404 } 1405 1406 case TYstruct: 1407 { 1408 if (config.fulltypes == CV8) 1409 { 1410 typidx = cv8_fwdref(t.Ttag); 1411 } 1412 else 1413 { 1414 int foo = t.Ttag.Stypidx; 1415 typidx = cv4_struct(t.Ttag,0); 1416 //printf("struct '%s' %x %x\n", t.Ttag.Sident.ptr, foo, typidx); 1417 } 1418 break; 1419 } 1420 1421 case TYenum: 1422 if (CPP) 1423 { 1424 } 1425 else 1426 typidx = cv4_fwdenum(t); 1427 break; 1428 1429 case TYref: 1430 case TYnref: 1431 attribute |= 0x20; // indicate reference pointer 1432 tym = TYnptr; // convert to C data type 1433 goto L1; // and try again 1434 1435 case TYnullptr: 1436 tym = TYnptr; 1437 next = cv4_typidx(tstypes[TYvoid]); // rewrite as void* 1438 t = tspvoid; 1439 goto L1; 1440 1441 // vector types 1442 case TYfloat4: size = 16; next = dttab4[TYfloat]; goto Larray; 1443 case TYdouble2: size = 16; next = dttab4[TYdouble]; goto Larray; 1444 case TYschar16: size = 16; next = dttab4[TYschar]; goto Larray; 1445 case TYuchar16: size = 16; next = dttab4[TYuchar]; goto Larray; 1446 case TYshort8: size = 16; next = dttab4[TYshort]; goto Larray; 1447 case TYushort8: size = 16; next = dttab4[TYushort]; goto Larray; 1448 case TYlong4: size = 16; next = dttab4[TYlong]; goto Larray; 1449 case TYulong4: size = 16; next = dttab4[TYulong]; goto Larray; 1450 case TYllong2: size = 16; next = dttab4[TYllong]; goto Larray; 1451 case TYullong2: size = 16; next = dttab4[TYullong]; goto Larray; 1452 1453 case TYfloat8: size = 32; next = dttab4[TYfloat]; goto Larray; 1454 case TYdouble4: size = 32; next = dttab4[TYdouble]; goto Larray; 1455 case TYschar32: size = 32; next = dttab4[TYschar]; goto Larray; 1456 case TYuchar32: size = 32; next = dttab4[TYuchar]; goto Larray; 1457 case TYshort16: size = 32; next = dttab4[TYshort]; goto Larray; 1458 case TYushort16: size = 32; next = dttab4[TYushort]; goto Larray; 1459 case TYlong8: size = 32; next = dttab4[TYlong]; goto Larray; 1460 case TYulong8: size = 32; next = dttab4[TYulong]; goto Larray; 1461 case TYllong4: size = 32; next = dttab4[TYllong]; goto Larray; 1462 case TYullong4: size = 32; next = dttab4[TYullong]; goto Larray; 1463 1464 case TYfloat16: size = 64; next = dttab4[TYfloat]; goto Larray; 1465 case TYdouble8: size = 64; next = dttab4[TYdouble]; goto Larray; 1466 case TYschar64: size = 64; next = dttab4[TYschar]; goto Larray; 1467 case TYuchar64: size = 64; next = dttab4[TYuchar]; goto Larray; 1468 case TYshort32: size = 64; next = dttab4[TYshort]; goto Larray; 1469 case TYushort32: size = 64; next = dttab4[TYushort]; goto Larray; 1470 case TYlong16: size = 64; next = dttab4[TYlong]; goto Larray; 1471 case TYulong16: size = 64; next = dttab4[TYulong]; goto Larray; 1472 case TYllong8: size = 64; next = dttab4[TYllong]; goto Larray; 1473 case TYullong8: size = 64; next = dttab4[TYullong]; goto Larray; 1474 1475 default: 1476 debug 1477 printf("%s\n", tym_str(tym)); 1478 1479 assert(0); 1480 } 1481 1482 // Add in const and/or volatile modifiers 1483 if (tycv & (mTYconst | mTYimmutable | mTYvolatile)) 1484 { uint modifier; 1485 1486 modifier = (tycv & (mTYconst | mTYimmutable)) ? 1 : 0; 1487 modifier |= (tycv & mTYvolatile) ? 2 : 0; 1488 switch (config.fulltypes) 1489 { 1490 case CV8: 1491 d = debtyp_alloc(8); 1492 TOWORD(d.data.ptr,0x1001); 1493 TOLONG(d.data.ptr + 2,typidx); 1494 TOWORD(d.data.ptr + 6,modifier); 1495 break; 1496 1497 case CV4: 1498 d = debtyp_alloc(6); 1499 TOWORD(d.data.ptr,LF_MODIFIER); 1500 TOWORD(d.data.ptr + 2,modifier); 1501 TOWORD(d.data.ptr + 4,typidx); 1502 break; 1503 1504 default: 1505 d = debtyp_alloc(10); 1506 TOWORD(d.data.ptr,LF_MODIFIER); 1507 TOLONG(d.data.ptr + 2,modifier); 1508 TOLONG(d.data.ptr + 6,typidx); 1509 break; 1510 } 1511 typidx = cv_debtyp(d); 1512 } 1513 1514 assert(typidx); 1515 return typidx; 1516 } 1517 1518 /****************************************** 1519 * Write out symbol s. 1520 */ 1521 1522 @trusted 1523 private void cv4_outsym(Symbol *s) 1524 { 1525 uint len; 1526 type *t; 1527 uint length; 1528 uint u; 1529 tym_t tym; 1530 const(char)* id; 1531 ubyte *debsym = null; 1532 ubyte[64] buf = void; 1533 1534 //printf("cv4_outsym(%s)\n",s.Sident.ptr); 1535 symbol_debug(s); 1536 if (s.Sflags & SFLnodebug) 1537 return; 1538 t = s.Stype; 1539 type_debug(t); 1540 tym = tybasic(t.Tty); 1541 if (tyfunc(tym) && s.Sclass != SC.typedef_) 1542 { int framedatum,targetdatum,fd; 1543 char idfree; 1544 idx_t typidx; 1545 1546 if (s != funcsym_p) 1547 return; 1548 id = s.prettyIdent ? s.prettyIdent : s.Sident.ptr; 1549 len = cv_stringbytes(id); 1550 1551 // Length of record 1552 length = 2 + 2 + 4 * 3 + _tysize[TYint] * 4 + 2 + cgcv.sz_idx + 1; 1553 debsym = (length + len <= (buf).sizeof) ? buf.ptr : cast(ubyte *) malloc(length + len); 1554 if (!debsym) 1555 err_nomem(); 1556 memset(debsym,0,length + len); 1557 1558 // Symbol type 1559 u = (s.Sclass == SC.static_) ? S_LPROC16 : S_GPROC16; 1560 if (I32) 1561 u += S_GPROC32 - S_GPROC16; 1562 TOWORD(debsym + 2,u); 1563 1564 if (config.fulltypes == CV4) 1565 { 1566 // Offsets 1567 if (I32) 1568 { TOLONG(debsym + 16,cast(uint)s.Ssize); // proc length 1569 TOLONG(debsym + 20,cast(uint)startoffset); // debug start 1570 TOLONG(debsym + 24,cast(uint)retoffset); // debug end 1571 u = 28; // offset to fixup 1572 } 1573 else 1574 { TOWORD(debsym + 16,cast(uint)s.Ssize); // proc length 1575 TOWORD(debsym + 18,cast(uint)startoffset); // debug start 1576 TOWORD(debsym + 20,cast(uint)retoffset); // debug end 1577 u = 22; // offset to fixup 1578 } 1579 length += cv_namestring(debsym + u + _tysize[TYint] + 2 + cgcv.sz_idx + 1,id); 1580 typidx = cv4_symtypidx(s); 1581 TOIDX(debsym + u + _tysize[TYint] + 2,typidx); // proc type 1582 debsym[u + _tysize[TYint] + 2 + cgcv.sz_idx] = tyfarfunc(tym) ? 4 : 0; 1583 TOWORD(debsym,length - 2); 1584 } 1585 else 1586 { 1587 // Offsets 1588 if (I32) 1589 { TOLONG(debsym + 16 + cgcv.sz_idx,cast(uint)s.Ssize); // proc length 1590 TOLONG(debsym + 20 + cgcv.sz_idx,cast(uint)startoffset); // debug start 1591 TOLONG(debsym + 24 + cgcv.sz_idx,cast(uint)retoffset); // debug end 1592 u = 28; // offset to fixup 1593 } 1594 else 1595 { TOWORD(debsym + 16 + cgcv.sz_idx,cast(uint)s.Ssize); // proc length 1596 TOWORD(debsym + 18 + cgcv.sz_idx,cast(uint)startoffset); // debug start 1597 TOWORD(debsym + 20 + cgcv.sz_idx,cast(uint)retoffset); // debug end 1598 u = 22; // offset to fixup 1599 } 1600 u += cgcv.sz_idx; 1601 length += cv_namestring(debsym + u + _tysize[TYint] + 2 + 1,id); 1602 typidx = cv4_symtypidx(s); 1603 TOIDX(debsym + 16,typidx); // proc type 1604 debsym[u + _tysize[TYint] + 2] = tyfarfunc(tym) ? 4 : 0; 1605 TOWORD(debsym,length - 2); 1606 } 1607 1608 uint soffset = cast(uint)Offset(DEBSYM); 1609 objmod.write_bytes(SegData[DEBSYM],debsym[0 .. length]); 1610 1611 // Put out fixup for function start offset 1612 objmod.reftoident(DEBSYM,soffset + u,s,0,CFseg | CFoff); 1613 } 1614 else 1615 { targ_size_t base; 1616 int reg; 1617 uint fd; 1618 uint idx1,idx2; 1619 uint value; 1620 uint fixoff; 1621 idx_t typidx; 1622 1623 typidx = cv4_typidx(t); 1624 id = s.prettyIdent ? s.prettyIdent : prettyident(s); 1625 len = cast(uint)strlen(id); 1626 debsym = (39 + IDOHD + len <= (buf).sizeof) ? buf.ptr : cast(ubyte *) malloc(39 + IDOHD + len); 1627 if (!debsym) 1628 err_nomem(); 1629 switch (s.Sclass) 1630 { 1631 case SC.parameter: 1632 case SC.regpar: 1633 if (s.Sfl == FLreg) 1634 { 1635 s.Sfl = FLpara; 1636 cv4_outsym(s); 1637 s.Sfl = FLreg; 1638 goto case_register; 1639 } 1640 base = Para.size - BPoff; // cancel out add of BPoff 1641 goto L1; 1642 1643 case SC.auto_: 1644 if (s.Sfl == FLreg) 1645 goto case_register; 1646 case_auto: 1647 base = Auto.size; 1648 L1: 1649 if (s.Sscope) // local variables moved into the closure cannot be emitted directly 1650 goto Lret; 1651 TOWORD(debsym + 2,I32 ? S_BPREL32 : S_BPREL16); 1652 if (config.fulltypes == CV4) 1653 { TOOFFSET(debsym + 4,s.Soffset + base + BPoff); 1654 TOIDX(debsym + 4 + _tysize[TYint],typidx); 1655 } 1656 else 1657 { TOOFFSET(debsym + 4 + cgcv.sz_idx,s.Soffset + base + BPoff); 1658 TOIDX(debsym + 4,typidx); 1659 } 1660 length = 2 + 2 + _tysize[TYint] + cgcv.sz_idx; 1661 length += cv_namestring(debsym + length,id); 1662 TOWORD(debsym,length - 2); 1663 break; 1664 1665 case SC.bprel: 1666 base = -BPoff; 1667 goto L1; 1668 1669 case SC.fastpar: 1670 if (s.Sfl != FLreg) 1671 { base = Fast.size; 1672 goto L1; 1673 } 1674 goto case_register; 1675 1676 case SC.register: 1677 if (s.Sfl != FLreg) 1678 goto case_auto; 1679 goto case_register; 1680 1681 case SC.pseudo: 1682 case_register: 1683 TOWORD(debsym + 2,S_REGISTER); 1684 reg = cv_regnum(s); 1685 TOIDX(debsym + 4,typidx); 1686 TOWORD(debsym + 4 + cgcv.sz_idx,reg); 1687 length = 2 * 3 + cgcv.sz_idx; 1688 length += 1 + cv_namestring(debsym + length,id); 1689 TOWORD(debsym,length - 2); 1690 break; 1691 1692 case SC.extern_: 1693 case SC.comdef: 1694 // Common blocks have a non-zero Sxtrnnum and an UNKNOWN seg 1695 if (!(s.Sxtrnnum && s.Sseg == UNKNOWN)) // if it's not really a common block 1696 { 1697 goto Lret; 1698 } 1699 goto case; 1700 case SC.global: 1701 case SC.comdat: 1702 u = S_GDATA16; 1703 goto L2; 1704 1705 case SC.static_: 1706 case SC.locstat: 1707 u = S_LDATA16; 1708 L2: 1709 if (I32) 1710 u += S_GDATA32 - S_GDATA16; 1711 TOWORD(debsym + 2,u); 1712 if (config.fulltypes == CV4) 1713 { 1714 fixoff = 4; 1715 length = 2 + 2 + _tysize[TYint] + 2; 1716 TOOFFSET(debsym + fixoff,s.Soffset); 1717 TOWORD(debsym + fixoff + _tysize[TYint],0); 1718 TOIDX(debsym + length,typidx); 1719 } 1720 else 1721 { 1722 fixoff = 8; 1723 length = 2 + 2 + _tysize[TYint] + 2; 1724 TOOFFSET(debsym + fixoff,s.Soffset); 1725 TOWORD(debsym + fixoff + _tysize[TYint],0); // segment 1726 TOIDX(debsym + 4,typidx); 1727 } 1728 length += cgcv.sz_idx; 1729 length += cv_namestring(debsym + length,id); 1730 TOWORD(debsym,length - 2); 1731 assert(length <= 40 + len); 1732 1733 if (s.Sseg == UNKNOWN || s.Sclass == SC.comdat) // if common block 1734 { 1735 if (config.exe & EX_flat) 1736 { 1737 fd = 0x16; 1738 idx1 = DGROUPIDX; 1739 idx2 = s.Sxtrnnum; 1740 } 1741 else 1742 { 1743 fd = 0x26; 1744 idx1 = idx2 = s.Sxtrnnum; 1745 } 1746 } 1747 else if (s.ty() & (mTYfar | mTYcs)) 1748 { 1749 fd = 0x04; 1750 idx1 = idx2 = SegData[s.Sseg].segidx; 1751 } 1752 else 1753 { fd = 0x14; 1754 idx1 = DGROUPIDX; 1755 idx2 = SegData[s.Sseg].segidx; 1756 } 1757 /* Because of the linker limitations, the length cannot 1758 * exceed 0x1000. 1759 * See optlink\cv\cvhashes.asm 1760 */ 1761 assert(length <= 0x1000); 1762 if (idx2 != 0) 1763 { uint offset = cast(uint)Offset(DEBSYM); 1764 objmod.write_bytes(SegData[DEBSYM],debsym[0 .. length]); 1765 objmod.write_long(DEBSYM,offset + fixoff,cast(uint)s.Soffset, 1766 cgcv.LCFDpointer + fd,idx1,idx2); 1767 } 1768 goto Lret; 1769 1770 static if (1) 1771 { 1772 case SC.typedef_: 1773 s.Stypidx = typidx; 1774 reset_symbuf.write((&s)[0 .. 1]); 1775 goto L4; 1776 1777 case SC.struct_: 1778 if (s.Sstruct.Sflags & STRnotagname) 1779 goto Lret; 1780 goto L4; 1781 1782 case SC.enum_: 1783 L4: 1784 // Output a 'user-defined type' for the tag name 1785 TOWORD(debsym + 2,S_UDT); 1786 TOIDX(debsym + 4,typidx); 1787 length = 2 + 2 + cgcv.sz_idx; 1788 length += cv_namestring(debsym + length,id); 1789 TOWORD(debsym,length - 2); 1790 list_subtract(&cgcv.list,s); 1791 break; 1792 1793 case SC.const_: 1794 // The only constants are enum members 1795 value = cast(uint)el_tolongt(s.Svalue); 1796 TOWORD(debsym + 2,S_CONST); 1797 TOIDX(debsym + 4,typidx); 1798 length = 4 + cgcv.sz_idx; 1799 cv4_storenumeric(debsym + length,value); 1800 length += cv4_numericbytes(value); 1801 length += cv_namestring(debsym + length,id); 1802 TOWORD(debsym,length - 2); 1803 break; 1804 } 1805 default: 1806 goto Lret; 1807 } 1808 assert(length <= 40 + len); 1809 objmod.write_bytes(SegData[DEBSYM],debsym[0 .. length]); 1810 } 1811 Lret: 1812 if (debsym != buf.ptr) 1813 free(debsym); 1814 } 1815 1816 /****************************************** 1817 * Write out any deferred symbols. 1818 */ 1819 1820 @trusted 1821 private void cv_outlist() 1822 { 1823 while (cgcv.list) 1824 cv_outsym(cast(Symbol *) list_pop(&cgcv.list)); 1825 } 1826 1827 /****************************************** 1828 * Write out symbol table for current function. 1829 */ 1830 1831 @trusted 1832 private void cv4_func(Funcsym *s, ref symtab_t symtab) 1833 { 1834 int endarg; 1835 1836 cv4_outsym(s); // put out function symbol 1837 __gshared Funcsym* sfunc; 1838 __gshared int cntOpenBlocks; 1839 sfunc = s; 1840 cntOpenBlocks = 0; 1841 1842 struct cv4 1843 { 1844 nothrow: 1845 // record for CV record S_BLOCK32 1846 struct block32_data 1847 { 1848 ushort len; 1849 ushort id; 1850 uint pParent; 1851 uint pEnd; 1852 uint length; 1853 uint offset; 1854 ushort seg; 1855 ubyte[2] name; 1856 } 1857 1858 1859 static void endArgs() 1860 { 1861 __gshared ushort[2] endargs = [ 2, S_ENDARG ]; 1862 objmod.write_bytes(SegData[DEBSYM],endargs[]); 1863 } 1864 static void beginBlock(int offset, int length) 1865 { 1866 if (++cntOpenBlocks >= 255) 1867 return; // optlink does not like more than 255 scope blocks 1868 1869 uint soffset = cast(uint)Offset(DEBSYM); 1870 // parent and end to be filled by linker 1871 block32_data block32 = { (block32_data).sizeof - 2, S_BLOCK32, 0, 0, length, 0, 0, [ 0, '\0' ] }; 1872 objmod.write_bytes(SegData[DEBSYM], (&block32)[0 .. 1]); 1873 size_t offOffset = cast(char*)&block32.offset - cast(char*)&block32; 1874 objmod.reftoident(DEBSYM, soffset + offOffset, sfunc, offset + sfunc.Soffset, CFseg | CFoff); 1875 } 1876 static void endBlock() 1877 { 1878 if (cntOpenBlocks-- >= 255) 1879 return; // optlink does not like more than 255 scope blocks 1880 1881 __gshared ushort[2] endargs = [ 2, S_END ]; 1882 objmod.write_bytes(SegData[DEBSYM],endargs[]); 1883 } 1884 } 1885 1886 varStats_writeSymbolTable(symtab, &cv4_outsym, &cv4.endArgs, &cv4.beginBlock, &cv4.endBlock); 1887 1888 // Put out function return record 1889 if (1) 1890 { ubyte[2+2+2+1+1+4] sreturn = void; 1891 ushort flags; 1892 ubyte style; 1893 tym_t ty; 1894 tym_t tyret; 1895 uint u; 1896 1897 u = 2+2+1; 1898 ty = tybasic(s.ty()); 1899 1900 flags = tyrevfunc(ty) ? 0 : 1; 1901 flags |= typfunc(ty) ? 0 : 2; 1902 TOWORD(sreturn.ptr + 4,flags); 1903 1904 tyret = tybasic(s.Stype.Tnext.Tty); 1905 switch (tyret) 1906 { 1907 case TYvoid: 1908 default: 1909 style = 0; 1910 break; 1911 1912 case TYbool: 1913 case TYchar: 1914 case TYschar: 1915 case TYuchar: 1916 sreturn[7] = 1; 1917 sreturn[8] = 1; // AL 1918 goto L1; 1919 1920 case TYwchar_t: 1921 case TYchar16: 1922 case TYshort: 1923 case TYushort: 1924 goto case_ax; 1925 1926 case TYint: 1927 case TYuint: 1928 case TYsptr: 1929 case TYcptr: 1930 case TYnullptr: 1931 case TYnptr: 1932 case TYnref: 1933 if (I32) 1934 goto case_eax; 1935 else 1936 goto case_ax; 1937 1938 case TYfloat: 1939 case TYifloat: 1940 if (config.exe & EX_flat) 1941 goto case_st0; 1942 goto case; 1943 1944 case TYlong: 1945 case TYulong: 1946 case TYdchar: 1947 if (I32) 1948 goto case_eax; 1949 else 1950 goto case_dxax; 1951 1952 case TYfptr: 1953 case TYhptr: 1954 if (I32) 1955 goto case_edxeax; 1956 else 1957 goto case_dxax; 1958 1959 case TYvptr: 1960 if (I32) 1961 goto case_edxebx; 1962 else 1963 goto case_dxbx; 1964 1965 case TYdouble: 1966 case TYidouble: 1967 case TYdouble_alias: 1968 if (config.exe & EX_flat) 1969 goto case_st0; 1970 if (I32) 1971 goto case_edxeax; 1972 else 1973 goto case_axbxcxdx; 1974 1975 case TYllong: 1976 case TYullong: 1977 assert(I32); 1978 goto case_edxeax; 1979 1980 case TYldouble: 1981 case TYildouble: 1982 goto case_st0; 1983 1984 case TYcfloat: 1985 case TYcdouble: 1986 case TYcldouble: 1987 goto case_st01; 1988 1989 case_ax: 1990 sreturn[7] = 1; 1991 sreturn[8] = 9; // AX 1992 goto L1; 1993 1994 case_eax: 1995 sreturn[7] = 1; 1996 sreturn[8] = 17; // EAX 1997 goto L1; 1998 1999 2000 case_dxax: 2001 sreturn[7] = 2; 2002 sreturn[8] = 11; // DX 2003 sreturn[9] = 9; // AX 2004 goto L1; 2005 2006 case_dxbx: 2007 sreturn[7] = 2; 2008 sreturn[8] = 11; // DX 2009 sreturn[9] = 12; // BX 2010 goto L1; 2011 2012 case_axbxcxdx: 2013 sreturn[7] = 4; 2014 sreturn[8] = 9; // AX 2015 sreturn[9] = 12; // BX 2016 sreturn[10] = 10; // CX 2017 sreturn[11] = 11; // DX 2018 goto L1; 2019 2020 case_edxeax: 2021 sreturn[7] = 2; 2022 sreturn[8] = 19; // EDX 2023 sreturn[9] = 17; // EAX 2024 goto L1; 2025 2026 case_edxebx: 2027 sreturn[7] = 2; 2028 sreturn[8] = 19; // EDX 2029 sreturn[9] = 20; // EBX 2030 goto L1; 2031 2032 case_st0: 2033 sreturn[7] = 1; 2034 sreturn[8] = 128; // ST0 2035 goto L1; 2036 2037 case_st01: 2038 sreturn[7] = 2; 2039 sreturn[8] = 128; // ST0 (imaginary) 2040 sreturn[9] = 129; // ST1 (real) 2041 goto L1; 2042 2043 L1: 2044 style = 1; 2045 u += sreturn[7] + 1; 2046 break; 2047 } 2048 sreturn[6] = style; 2049 2050 TOWORD(sreturn.ptr,u); 2051 TOWORD(sreturn.ptr + 2,S_RETURN); 2052 objmod.write_bytes(SegData[DEBSYM],sreturn[0 .. u + 2]); 2053 } 2054 2055 // Put out end scope 2056 { __gshared ushort[2] endproc = [ 2,S_END ]; 2057 2058 objmod.write_bytes(SegData[DEBSYM],endproc[]); 2059 } 2060 2061 cv_outlist(); 2062 } 2063 2064 ////////////////////////////////////////////////////////// 2065 2066 /****************************************** 2067 * Write out data to .OBJ file. 2068 */ 2069 2070 @trusted 2071 void cv_term() 2072 { 2073 //printf("cv_term(): debtyp.length = %d\n",debtyp.length); 2074 2075 segidx_t typeseg = objmod.seg_debugT(); 2076 2077 switch (config.fulltypes) 2078 { 2079 case CV4: 2080 case CVSYM: 2081 cv_outlist(); 2082 goto case; 2083 case CV8: 2084 objmod.write_bytes(SegData[typeseg],(&cgcv.signature)[0 .. 1]); 2085 if (debtyp.length != 1 || config.fulltypes == CV8) 2086 { 2087 for (uint u = 0; u < debtyp.length; u++) 2088 { debtyp_t *d = debtyp[u]; 2089 2090 objmod.write_bytes(SegData[typeseg],(cast(void *)d)[uint.sizeof .. uint.sizeof + 2 + d.length]); 2091 debtyp_free(d); 2092 } 2093 } 2094 else if (debtyp.length) 2095 { 2096 debtyp_free(debtyp[0]); 2097 } 2098 break; 2099 2100 2101 default: 2102 assert(0); 2103 } 2104 2105 // debtyp.dtor(); // save for later 2106 vec_free(debtypvec); 2107 debtypvec = null; 2108 } 2109 2110 /****************************************** 2111 * Write out symbol table for current function. 2112 */ 2113 2114 @trusted 2115 void cv_func(Funcsym *s) 2116 { 2117 2118 //printf("cv_func('%s')\n",s.Sident.ptr); 2119 if (s.Sflags & SFLnodebug) 2120 return; 2121 2122 switch (config.fulltypes) 2123 { 2124 case CV4: 2125 case CVSYM: 2126 case CVTDB: 2127 cv4_func(s, globsym); 2128 break; 2129 2130 default: 2131 assert(0); 2132 } 2133 } 2134 2135 /****************************************** 2136 * Write out symbol table for current function. 2137 */ 2138 2139 @trusted 2140 void cv_outsym(Symbol *s) 2141 { 2142 //printf("cv_outsym('%s')\n",s.Sident.ptr); 2143 symbol_debug(s); 2144 if (s.Sflags & SFLnodebug) 2145 return; 2146 switch (config.fulltypes) 2147 { 2148 case CV4: 2149 case CVSYM: 2150 case CVTDB: 2151 cv4_outsym(s); 2152 break; 2153 2154 case CV8: 2155 cv8_outsym(s); 2156 break; 2157 2158 default: 2159 assert(0); 2160 } 2161 } 2162 2163 /****************************************** 2164 * Return cv type index for a type. 2165 */ 2166 2167 @trusted 2168 uint cv_typidx(type *t) 2169 { uint ti; 2170 2171 //printf("cv_typidx(%p)\n",t); 2172 switch (config.fulltypes) 2173 { 2174 case CV4: 2175 case CVTDB: 2176 case CVSYM: 2177 case CV8: 2178 ti = cv4_typidx(t); 2179 break; 2180 2181 default: 2182 debug 2183 printf("fulltypes = %d\n",config.fulltypes); 2184 2185 assert(0); 2186 } 2187 return ti; 2188 }