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