1 /** 2 * Compiler implementation of the 3 * $(LINK2 http://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (C) 1992-1998 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/newman.c, backend/newman.c) 10 */ 11 12 module dmd.backend.newman; 13 14 version (SCPP) 15 { 16 version = COMPILE; 17 version = SCPPorMARS; 18 version = SCPPorHTOD; 19 } 20 version (HTOD) 21 { 22 version = COMPILE; 23 version = SCPPorMARS; 24 version = SCPPorHTOD; 25 } 26 version (MARS) 27 { 28 version = COMPILE; 29 version = SCPPorMARS; 30 } 31 32 version (COMPILE) 33 { 34 35 import core.stdc.ctype; 36 import core.stdc.stdio; 37 import core.stdc.stdlib; 38 import core.stdc..string; 39 40 import dmd.backend.cc; 41 import dmd.backend.cdef; 42 import dmd.backend.code; 43 import dmd.backend.code_x86; 44 import dmd.backend.mem; 45 import dmd.backend.el; 46 import dmd.backend.exh; 47 import dmd.backend.global; 48 import dmd.backend.obj; 49 import dmd.backend.oper; 50 import dmd.backend.rtlsym; 51 import dmd.backend.ty; 52 import dmd.backend.type; 53 import dmd.backend.xmm; 54 55 version (SCPPorHTOD) 56 { 57 import cpp; 58 import dtoken; 59 import msgs2; 60 import parser; 61 import scopeh; 62 } 63 64 version (MARS) 65 struct token_t; 66 67 extern (C++): 68 69 nothrow: 70 71 bool NEWTEMPMANGLE() { return !(config.flags4 & CFG4oldtmangle); } // do new template mangling 72 73 enum BUFIDMAX = 2 * IDMAX; 74 75 struct Mangle 76 { 77 char[BUFIDMAX + 2] buf; 78 79 char *np; // index into buf[] 80 81 // Used for compression of redundant znames 82 const(char)*[10] zname; 83 int znamei; 84 85 type*[10] arg; // argument_replicator 86 int argi; // number used in arg[] 87 } 88 89 private __gshared 90 { 91 Mangle mangle; 92 93 int mangle_inuse; 94 } 95 96 struct MangleInuse 97 { 98 static if (0) 99 { 100 this(int i) 101 { 102 assert(mangle_inuse == 0); 103 mangle_inuse++; 104 } 105 106 ~this() 107 { 108 assert(mangle_inuse == 1); 109 mangle_inuse--; 110 } 111 } 112 } 113 114 /* Names for special variables */ 115 __gshared 116 { 117 char[3] cpp_name_new = "?2"; 118 char[3] cpp_name_delete = "?3"; 119 char[4] cpp_name_anew = "?_P"; 120 char[4] cpp_name_adelete = "?_Q"; 121 char[3] cpp_name_ct = "?0"; 122 char[3] cpp_name_dt = "?1"; 123 char[3] cpp_name_as = "?4"; 124 char[4] cpp_name_vc = "?_H"; 125 char[4] cpp_name_primdt = "?_D"; 126 char[4] cpp_name_scaldeldt = "?_G"; 127 char[4] cpp_name_priminv = "?_R"; 128 } 129 130 131 /**************************** 132 */ 133 134 version (MARS) 135 { 136 struct OPTABLE 137 { 138 ubyte tokn; 139 ubyte oper; 140 const(char)* string; 141 const(char)* pretty; 142 } 143 } 144 145 version (SCPPorHTOD) 146 { 147 __gshared OPTABLE[57] oparray = [ 148 { TKnew, OPnew, cpp_name_new.ptr, "new" }, 149 { TKdelete, OPdelete, cpp_name_delete.ptr,"del" }, 150 { TKadd, OPadd, "?H", "+" }, 151 { TKadd, OPuadd, "?H", "+" }, 152 { TKmin, OPmin, "?G", "-" }, 153 { TKmin, OPneg, "?G", "-" }, 154 { TKstar, OPmul, "?D", "*" }, 155 { TKstar, OPind, "?D", "*" }, 156 { TKdiv, OPdiv, "?K", "/" }, 157 { TKmod, OPmod, "?L", "%" }, 158 { TKxor, OPxor, "?T", "^" }, 159 { TKand, OPand, "?I", "&" }, 160 { TKand, OPaddr, "?I", "&" }, 161 { TKor, OPor, "?U", "|" }, 162 { TKcom, OPcom, "?S", "~" }, 163 { TKnot, OPnot, "?7", "!" }, 164 { TKeq, OPeq, cpp_name_as.ptr, "=" }, 165 { TKeq, OPstreq, "?4", "=" }, 166 { TKlt, OPlt, "?M", "<" }, 167 { TKgt, OPgt, "?O", ">" }, 168 { TKnew, OPanew, cpp_name_anew.ptr, "n[]" }, 169 { TKdelete, OPadelete, cpp_name_adelete.ptr,"d[]" }, 170 { TKunord, OPunord, "?_S", "!<>=" }, 171 { TKlg, OPlg, "?_T", "<>" }, 172 { TKleg, OPleg, "?_U", "<>=" }, 173 { TKule, OPule, "?_V", "!>" }, 174 { TKul, OPul, "?_W", "!>=" }, 175 { TKuge, OPuge, "?_X", "!<" }, 176 { TKug, OPug, "?_Y", "!<=" }, 177 { TKue, OPue, "?_Z", "!<>" }, 178 { TKaddass, OPaddass, "?Y", "+=" }, 179 { TKminass, OPminass, "?Z", "-=" }, 180 { TKmulass, OPmulass, "?X", "*=" }, 181 { TKdivass, OPdivass, "?_0", "/=" }, 182 { TKmodass, OPmodass, "?_1", "%=" }, 183 { TKxorass, OPxorass, "?_6", "^=" }, 184 { TKandass, OPandass, "?_4", "&=" }, 185 { TKorass, OPorass, "?_5", "|=" }, 186 { TKshl, OPshl, "?6", "<<" }, 187 { TKshr, OPshr, "?5", ">>" }, 188 { TKshrass, OPshrass, "?_2", ">>=" }, 189 { TKshlass, OPshlass, "?_3", "<<=" }, 190 { TKeqeq, OPeqeq, "?8", "==" }, 191 { TKne, OPne, "?9", "!=" }, 192 { TKle, OPle, "?N", "<=" }, 193 { TKge, OPge, "?P", ">=" }, 194 { TKandand, OPandand, "?V", "&&" }, 195 { TKoror, OPoror, "?W", "||" }, 196 { TKplpl, OPpostinc, "?E", "++" }, 197 { TKplpl, OPpreinc, "?E", "++" }, 198 { TKmimi, OPpostdec, "?F", "--" }, 199 { TKmimi, OPpredec, "?F", "--" }, 200 { TKlpar, OPcall, "?R", "()" }, 201 { TKlbra, OPbrack, "?A", "[]" }, 202 { TKarrow, OParrow, "?C", "->" }, 203 { TKcomma, OPcomma, "?Q", "," }, 204 { TKarrowstar, OParrowstar, "?J", "->*" }, 205 ]; 206 } 207 208 /**************************************** 209 * Convert from identifier to operator 210 */ 211 version (SCPPorHTOD) 212 { 213 214 static if (0) //__GNUC__ // NOT DONE - FIX 215 { 216 char * unmangle_pt(const(char)** s) 217 { 218 return cast(char *)*s; 219 } 220 } 221 else 222 { 223 extern (C) char *unmangle_pt(const(char)**); 224 } 225 226 char *cpp_unmangleident(const(char)* p) 227 { 228 MangleInuse m; 229 230 //printf("cpp_unmangleident('%s')\n", p); 231 if (*p == '$') // if template name 232 { 233 L1: 234 const(char)* q = p; 235 char* s = unmangle_pt(&q); 236 if (s) 237 { if (strlen(s) <= BUFIDMAX) 238 p = strcpy(mangle.buf.ptr, s); 239 free(s); 240 } 241 } 242 else if (*p == '?') // if operator name 243 { int i; 244 245 if (NEWTEMPMANGLE && p[1] == '$') // if template name 246 goto L1; 247 for (i = 0; i < oparray.length; i++) 248 { if (strcmp(p,oparray[i].string) == 0) 249 { const(char)* s; 250 251 strcpy(mangle.buf.ptr, "operator "); 252 switch (oparray[i].oper) 253 { case OPanew: 254 s = "new[]"; 255 break; 256 case OPadelete: 257 s = "delete[]"; 258 break; 259 case OPdelete: 260 s = "delete"; 261 break; 262 default: 263 s = oparray[i].pretty.ptr; 264 break; 265 } 266 strcat(mangle.buf.ptr,s); 267 p = mangle.buf.ptr; 268 break; 269 } 270 } 271 } 272 //printf("-cpp_unmangleident() = '%s'\n", p); 273 return cast(char *)p; 274 } 275 } 276 277 /**************************************** 278 * Find index in oparray[] for operator. 279 * Returns: 280 * index or -1 if not found 281 */ 282 283 version (SCPPorHTOD) 284 { 285 286 int cpp_opidx(int op) 287 { int i; 288 289 for (i = 0; i < oparray.length; i++) 290 if (oparray[i].oper == op) 291 return i; 292 return -1; 293 } 294 295 } 296 297 /*************************************** 298 * Find identifier string associated with operator. 299 * Returns: 300 * null if not found 301 */ 302 303 version (SCPPorHTOD) 304 { 305 306 char *cpp_opident(int op) 307 { int i; 308 309 i = cpp_opidx(op); 310 return (i == -1) ? null : cast(char*)oparray[i].string; 311 } 312 313 } 314 315 /********************************** 316 * Convert from operator token to name. 317 * Output: 318 * *poper OPxxxx 319 * *pt set to type for user defined conversion 320 * Returns: 321 * pointer to corresponding name 322 */ 323 324 version (SCPPorHTOD) 325 { 326 327 char *cpp_operator(int *poper,type **pt) 328 { 329 int i; 330 type *typ_spec; 331 char *s; 332 333 *pt = null; 334 stoken(); /* skip over operator keyword */ 335 for (i = 0; i < oparray.length; i++) 336 { if (oparray[i].tokn == tok.TKval) 337 goto L1; 338 } 339 340 /* Look for type conversion */ 341 if (type_specifier(&typ_spec)) 342 { type *t; 343 344 t = ptr_operator(typ_spec); // parse ptr-operator 345 fixdeclar(t); 346 type_free(typ_spec); 347 *pt = t; 348 return cpp_typetostring(t,cast(char*)"?B".ptr); 349 } 350 351 cpperr(EM_not_overloadable); // that token cannot be overloaded 352 s = cast(char*)"_".ptr; 353 goto L2; 354 355 L1: 356 s = cast(char*)oparray[i].string; 357 *poper = oparray[i].oper; 358 switch (*poper) 359 { case OPcall: 360 if (stoken() != TKrpar) 361 synerr(EM_rpar); /* ')' expected */ 362 break; 363 364 case OPbrack: 365 if (stoken() != TKrbra) 366 synerr(EM_rbra); /* ']' expected */ 367 break; 368 369 case OPnew: 370 if (stoken() != TKlbra) 371 goto Lret; 372 *poper = OPanew; // operator new[] 373 s = cpp_name_anew.ptr; 374 goto L3; 375 376 case OPdelete: 377 if (stoken() != TKlbra) 378 goto Lret; 379 *poper = OPadelete; // operator delete[] 380 s = cpp_name_adelete.ptr; 381 L3: 382 if (stoken() != TKrbra) 383 synerr(EM_rbra); // ']' expected 384 if (!(config.flags4 & CFG4anew)) 385 { cpperr(EM_enable_anew); // throw -Aa to support this 386 config.flags4 |= CFG4anew; 387 } 388 break; 389 390 default: 391 break; 392 } 393 L2: 394 stoken(); 395 Lret: 396 return s; 397 } 398 399 /****************************************** 400 * Alternate version that works on a list of token's. 401 * Input: 402 * to list of tokens 403 * Output: 404 * *pcastoverload 1 if user defined type conversion 405 */ 406 407 char *cpp_operator2(token_t *to, int *pcastoverload) 408 { 409 int i; 410 char *s; 411 token_t *tn; 412 int oper; 413 414 *pcastoverload = 0; 415 if (!to || !to.TKnext) 416 return null; 417 418 for (i = 0; i < oparray.length; i++) 419 { 420 //printf("[%d] %d, %d\n", i, oparray[i].tokn, tok.TKval); 421 if (oparray[i].tokn == to.TKval) 422 goto L1; 423 } 424 425 //printf("cpp_operator2(): castoverload\n"); 426 *pcastoverload = 1; 427 return null; 428 429 L1: 430 tn = to.TKnext; 431 s = cast(char*)oparray[i].string; 432 oper = oparray[i].oper; 433 switch (oper) 434 { case OPcall: 435 if (tn.TKval != TKrpar) 436 synerr(EM_rpar); // ')' expected 437 break; 438 439 case OPbrack: 440 if (tn.TKval != TKrbra) 441 synerr(EM_rbra); // ']' expected 442 break; 443 444 case OPnew: 445 if (tn.TKval != TKlbra) 446 break; 447 oper = OPanew; // operator new[] 448 s = cpp_name_anew.ptr; 449 goto L3; 450 451 case OPdelete: 452 if (tn.TKval != TKlbra) 453 break; 454 oper = OPadelete; // operator delete[] 455 s = cpp_name_adelete.ptr; 456 L3: 457 if (tn.TKval != TKrbra) 458 synerr(EM_rbra); // ']' expected 459 if (!(config.flags4 & CFG4anew)) 460 { cpperr(EM_enable_anew); // throw -Aa to support this 461 config.flags4 |= CFG4anew; 462 } 463 break; 464 465 default: 466 break; 467 } 468 return s; 469 } 470 471 } 472 473 /*********************************** 474 * Generate and return a pointer to a string constructed from 475 * the type, appended to the prefix. 476 * Since these generated strings determine the uniqueness of names, 477 * they are also used to determine if two types are the same. 478 * Returns: 479 * pointer to static name[] 480 */ 481 482 char *cpp_typetostring(type *t,char *prefix) 483 { int i; 484 485 if (prefix) 486 { strcpy(mangle.buf.ptr,prefix); 487 i = cast(int)strlen(prefix); 488 } 489 else 490 i = 0; 491 //dbg_printf("cpp_typetostring:\n"); 492 //type_print(t); 493 MangleInuse m; 494 mangle.znamei = 0; 495 mangle.argi = 0; 496 mangle.np = mangle.buf.ptr + i; 497 mangle.buf[BUFIDMAX + 1] = 0x55; 498 cpp_data_type(t); 499 *mangle.np = 0; // 0-terminate mangle.buf[] 500 //dbg_printf("cpp_typetostring: '%s'\n", mangle.buf); 501 assert(strlen(mangle.buf.ptr) <= BUFIDMAX); 502 assert(mangle.buf[BUFIDMAX + 1] == 0x55); 503 return mangle.buf.ptr; 504 } 505 506 version (MARS) { } else 507 { 508 509 /******************************** 510 * 'Mangle' a name for output. 511 * Returns: 512 * pointer to mangled name (a static buffer) 513 */ 514 515 char *cpp_mangle(Symbol *s) 516 { 517 symbol_debug(s); 518 //printf("cpp_mangle(s = %p, '%s')\n", s, s.Sident); 519 //type_print(s.Stype); 520 521 version (SCPPorHTOD) 522 { 523 if (!CPP) 524 return symbol_ident(s); 525 } 526 527 if (type_mangle(s.Stype) != mTYman_cpp) 528 return symbol_ident(s); 529 else 530 { 531 MangleInuse m; 532 533 mangle.znamei = 0; 534 mangle.argi = 0; 535 mangle.np = mangle.buf.ptr; 536 mangle.buf[BUFIDMAX + 1] = 0x55; 537 cpp_decorated_name(s); 538 *mangle.np = 0; // 0-terminate cpp_name[] 539 //dbg_printf("cpp_mangle() = '%s'\n", mangle.buf); 540 assert(strlen(mangle.buf.ptr) <= BUFIDMAX); 541 assert(mangle.buf[BUFIDMAX + 1] == 0x55); 542 return mangle.buf.ptr; 543 } 544 } 545 546 } 547 /////////////////////////////////////////////////////// 548 549 /********************************* 550 * Add char into cpp_name[]. 551 */ 552 553 private void CHAR(int c) 554 { 555 if (mangle.np < &mangle.buf[BUFIDMAX]) 556 *mangle.np++ = cast(char)c; 557 } 558 559 /********************************* 560 * Add char into cpp_name[]. 561 */ 562 563 private void STR(const(char)* p) 564 { 565 size_t len; 566 567 len = strlen(p); 568 if (mangle.np + len <= &mangle.buf[BUFIDMAX]) 569 { memcpy(mangle.np,p,len); 570 mangle.np += len; 571 } 572 else 573 for (; *p; p++) 574 CHAR(*p); 575 } 576 577 /*********************************** 578 * Convert const volatile combinations into 0..3 579 */ 580 581 private int cpp_cvidx(tym_t ty) 582 { int i; 583 584 i = (ty & mTYconst) ? 1 : 0; 585 i |= (ty & mTYvolatile) ? 2 : 0; 586 return i; 587 } 588 589 /****************************** 590 * Turn protection into 0..2 591 */ 592 593 private int cpp_protection(Symbol *s) 594 { int i; 595 596 switch (s.Sflags & SFLpmask) 597 { case SFLprivate: i = 0; break; 598 case SFLprotected: i = 1; break; 599 case SFLpublic: i = 2; break; 600 default: 601 symbol_print(s); 602 assert(0); 603 } 604 return i; 605 } 606 607 /*********************************** 608 * Create mangled name for template instantiation. 609 */ 610 611 version (SCPPorHTOD) 612 { 613 614 char *template_mangle(Symbol *s,param_t *arglist) 615 { 616 /* mangling ::= '$' template_name { type | expr } 617 type ::= "T" mangled type 618 expr ::= integer | string | address | float | double | long_double 619 integer ::= "I" dimension 620 string ::= "S" string 621 address ::= "R" zname 622 float ::= "F" hex_digits 623 double ::= "D" hex_digits 624 long_double ::= "L" hex_digits 625 */ 626 param_t *p; 627 628 assert(s); 629 symbol_debug(s); 630 //assert(s.Sclass == SCtemplate); 631 632 //printf("\ntemplate_mangle(s = '%s', arglist = %p)\n", s.Sident, arglist); 633 //arglist.print_list(); 634 635 MangleInuse m; 636 mangle.znamei = 0; 637 mangle.argi = 0; 638 mangle.np = mangle.buf.ptr; 639 mangle.buf[BUFIDMAX + 1] = 0x55; 640 641 if (NEWTEMPMANGLE) 642 STR("?$"); 643 else 644 CHAR('$'); 645 646 // BUG: this is for templates nested inside class scopes. 647 // Need to check if it creates names that are properly unmanglable. 648 cpp_zname(s.Sident.ptr); 649 if (s.Sscope) 650 cpp_scope(s.Sscope); 651 652 for (p = arglist; p; p = p.Pnext) 653 { 654 if (p.Ptype) 655 { /* Argument is a type */ 656 if (!NEWTEMPMANGLE) 657 CHAR('T'); 658 cpp_argument_list(p.Ptype, 1); 659 } 660 else if (p.Psym) 661 { 662 CHAR('V'); // this is a 'class' name, but it should be a 'template' name 663 cpp_ecsu_name(p.Psym); 664 } 665 else 666 { /* Argument is an expression */ 667 elem *e = p.Pelem; 668 tym_t ty = tybasic(e.ET.Tty); 669 char *p2; 670 char[2] a = void; 671 int ni; 672 char c; 673 674 L2: 675 switch (e.Eoper) 676 { case OPconst: 677 switch (ty) 678 { case TYfloat: ni = FLOATSIZE; c = 'F'; goto L1; 679 case TYdouble_alias: 680 case TYdouble: ni = DOUBLESIZE; c = 'D'; goto L1; 681 case TYldouble: ni = tysize(TYldouble); c = 'L'; goto L1; 682 L1: 683 if (NEWTEMPMANGLE) 684 CHAR('$'); 685 CHAR(c); 686 p2 = cast(char *)&e.EV.Vdouble; 687 while (ni--) 688 { char ch; 689 static immutable char[16] hex = "0123456789ABCDEF"; 690 691 ch = *p2++; 692 CHAR(hex[ch & 15]); 693 CHAR(hex[(ch >> 4) & 15]); 694 } 695 break; 696 default: 697 debug 698 { 699 if (!tyintegral(ty) && !tymptr(ty)) 700 elem_print(e); 701 } 702 assert(tyintegral(ty) || tymptr(ty)); 703 if (NEWTEMPMANGLE) 704 STR("$0"); 705 else 706 CHAR('I'); 707 cpp_dimension(el_tolongt(e)); 708 break; 709 } 710 break; 711 case OPstring: 712 if (NEWTEMPMANGLE) 713 STR("$S"); 714 else 715 CHAR('S'); 716 if (e.EV.Voffset) 717 synerr(EM_const_init); // constant initializer expected 718 cpp_string(e.EV.Vstring,e.EV.Vstrlen); 719 break; 720 case OPrelconst: 721 if (e.EV.Voffset) 722 synerr(EM_const_init); // constant initializer expected 723 s = e.EV.Vsym; 724 if (NEWTEMPMANGLE) 725 { STR("$1"); 726 cpp_decorated_name(s); 727 } 728 else 729 { CHAR('R'); 730 cpp_zname(s.Sident.ptr); 731 } 732 break; 733 case OPvar: 734 if (e.EV.Vsym.Sflags & SFLvalue && 735 tybasic(e.ET.Tty) != TYstruct) 736 { 737 e = e.EV.Vsym.Svalue; 738 goto L2; 739 } 740 else if (e.EV.Vsym.Sclass == SCconst /*&& 741 pstate.STintemplate*/) 742 { 743 CHAR('V'); // pretend to be a class name 744 cpp_zname(e.EV.Vsym.Sident.ptr); 745 break; 746 } 747 goto default; 748 749 default: 750 version (SCPPorHTOD) 751 { 752 debug 753 { 754 if (!errcnt) 755 elem_print(e); 756 } 757 synerr(EM_const_init); // constant initializer expected 758 assert(errcnt); 759 } 760 break; 761 } 762 } 763 } 764 *mangle.np = 0; 765 //printf("template_mangle() = '%s'\n", mangle.buf); 766 assert(strlen(mangle.buf.ptr) <= BUFIDMAX); 767 assert(mangle.buf[BUFIDMAX + 1] == 0x55); 768 return mangle.buf.ptr; 769 } 770 771 } 772 773 ////////////////////////////////////////////////////// 774 // Functions corresponding to the name mangling grammar in the 775 // "Microsoft Object Mapping Specification" 776 777 private void cpp_string(char *s,size_t len) 778 { char c; 779 780 for (; --len; s++) 781 { static immutable char[11] special_char = ",/\\:. \n\t'-"; 782 char *p; 783 784 c = *s; 785 if (c & 0x80 && isalpha(c & 0x7F)) 786 { CHAR('?'); 787 c &= 0x7F; 788 } 789 else if (isalnum(c)) 790 { } 791 else 792 { 793 CHAR('?'); 794 if ((p = cast(char *)strchr(special_char.ptr,c)) != null) 795 c = cast(char)('0' + (p - special_char.ptr)); 796 else 797 { 798 CHAR('$'); 799 CHAR('A' + ((c >> 4) & 0x0F)); 800 c = 'A' + (c & 0x0F); 801 } 802 } 803 CHAR(c); 804 } 805 CHAR('@'); 806 } 807 808 private void cpp_dimension(targ_ullong u) 809 { 810 if (u && u <= 10) 811 CHAR('0' + cast(char)u - 1); 812 else 813 { char[u.sizeof * 2 + 1] buffer = void; 814 char *p; 815 816 buffer[buffer.length - 1] = 0; 817 for (p = &buffer[buffer.length - 1]; u; u >>= 4) 818 { 819 *--p = 'A' + (u & 0x0F); 820 } 821 STR(p); 822 CHAR('@'); 823 } 824 } 825 826 static if (0) 827 { 828 private void cpp_dimension_ld(targ_ldouble ld) 829 { ubyte[targ_ldouble.sizeof] ldbuf = void; 830 831 memcpy(ldbuf.ptr,&ld,ld.sizeof); 832 if (u && u <= 10) 833 CHAR('0' + cast(char)u - 1); 834 else 835 { char[u.sizeof * 2 + 1] buffer = void; 836 char *p; 837 838 buffer[buffer.length - 1] = 0; 839 for (p = &buffer[buffer.length - 1]; u; u >>= 4) 840 { 841 *--p = 'A' + (u & 0x0F); 842 } 843 STR(p); 844 CHAR('@'); 845 } 846 } 847 } 848 849 private void cpp_enum_name(Symbol *s) 850 { type *t; 851 char c; 852 853 t = tstypes[TYint]; 854 switch (tybasic(t.Tty)) 855 { 856 case TYschar: c = '0'; break; 857 case TYuchar: c = '1'; break; 858 case TYshort: c = '2'; break; 859 case TYushort: c = '3'; break; 860 case TYint: c = '4'; break; 861 case TYuint: c = '5'; break; 862 case TYlong: c = '6'; break; 863 case TYulong: c = '7'; break; 864 default: assert(0); 865 } 866 CHAR(c); 867 cpp_ecsu_name(s); 868 } 869 870 private void cpp_reference_data_type(type *t, int flag) 871 { 872 if (tybasic(t.Tty) == TYarray) 873 { 874 int ndim; 875 type *tn; 876 int i; 877 878 CHAR('Y'); 879 880 // Compute number of dimensions (we have at least one) 881 ndim = 0; 882 tn = t; 883 do 884 { ndim++; 885 tn = tn.Tnext; 886 } while (tybasic(tn.Tty) == TYarray); 887 888 cpp_dimension(ndim); 889 for (; tybasic(t.Tty) == TYarray; t = t.Tnext) 890 { 891 if (t.Tflags & TFvla) 892 CHAR('X'); // DMC++ extension 893 else 894 cpp_dimension(t.Tdim); 895 } 896 897 // DMC++ extension 898 if (flag) // if template type argument 899 { 900 i = cpp_cvidx(t.Tty); 901 if (i) 902 { CHAR('_'); 903 //CHAR('X' + i - 1); // _X, _Y, _Z 904 CHAR('O' + i - 1); // _O, _P, _Q 905 } 906 } 907 908 cpp_basic_data_type(t); 909 } 910 else 911 cpp_basic_data_type(t); 912 } 913 914 private void cpp_pointer_data_type(type *t) 915 { 916 if (tybasic(t.Tty) == TYvoid) 917 CHAR('X'); 918 else 919 cpp_reference_data_type(t, 0); 920 } 921 922 private void cpp_ecsu_data_type(type *t) 923 { char c; 924 Symbol *stag; 925 int i; 926 927 type_debug(t); 928 switch (tybasic(t.Tty)) 929 { 930 case TYstruct: 931 stag = t.Ttag; 932 switch (stag.Sstruct.Sflags & (STRclass | STRunion)) 933 { case 0: c = 'U'; break; 934 case STRunion: c = 'T'; break; 935 case STRclass: c = 'V'; break; 936 default: 937 assert(0); 938 } 939 CHAR(c); 940 cpp_ecsu_name(stag); 941 break; 942 case TYenum: 943 CHAR('W'); 944 cpp_enum_name(t.Ttag); 945 break; 946 default: 947 debug 948 type_print(t); 949 950 assert(0); 951 } 952 } 953 954 private void cpp_basic_data_type(type *t) 955 { char c; 956 int i; 957 958 //printf("cpp_basic_data_type(t)\n"); 959 //type_print(t); 960 switch (tybasic(t.Tty)) 961 { 962 case TYschar: c = 'C'; goto dochar; 963 case TYchar: c = 'D'; goto dochar; 964 case TYuchar: c = 'E'; goto dochar; 965 case TYshort: c = 'F'; goto dochar; 966 case TYushort: c = 'G'; goto dochar; 967 case TYint: c = 'H'; goto dochar; 968 case TYuint: c = 'I'; goto dochar; 969 case TYlong: c = 'J'; goto dochar; 970 case TYulong: c = 'K'; goto dochar; 971 case TYfloat: c = 'M'; goto dochar; 972 case TYdouble: c = 'N'; goto dochar; 973 974 case TYdouble_alias: 975 if (_tysize[TYint] == 4) 976 { c = 'O'; 977 goto dochar; 978 } 979 c = 'Z'; 980 goto dochar2; 981 982 case TYldouble: 983 if (_tysize[TYint] == 2) 984 { c = 'O'; 985 goto dochar; 986 } 987 c = 'Z'; 988 goto dochar2; 989 dochar: 990 CHAR(c); 991 break; 992 993 case TYllong: c = 'J'; goto dochar2; 994 case TYullong: c = 'K'; goto dochar2; 995 case TYbool: c = 'N'; goto dochar2; // was 'X' prior to 8.1b8 996 case TYwchar_t: 997 if (config.flags4 & CFG4nowchar_t) 998 { 999 c = 'G'; 1000 goto dochar; // same as TYushort 1001 } 1002 else 1003 { 1004 pstate.STflags |= PFLmfc; 1005 c = 'Y'; 1006 goto dochar2; 1007 } 1008 1009 // Digital Mars extensions 1010 case TYifloat: c = 'R'; goto dochar2; 1011 case TYidouble: c = 'S'; goto dochar2; 1012 case TYildouble: c = 'T'; goto dochar2; 1013 case TYcfloat: c = 'U'; goto dochar2; 1014 case TYcdouble: c = 'V'; goto dochar2; 1015 case TYcldouble: c = 'W'; goto dochar2; 1016 1017 case TYchar16: c = 'X'; goto dochar2; 1018 case TYdchar: c = 'Y'; goto dochar2; 1019 case TYnullptr: c = 'Z'; goto dochar2; 1020 1021 dochar2: 1022 CHAR('_'); 1023 goto dochar; 1024 1025 case TYsptr: 1026 case TYcptr: 1027 case TYf16ptr: 1028 case TYfptr: 1029 case TYhptr: 1030 case TYvptr: 1031 case TYmemptr: 1032 case TYnptr: 1033 case TYimmutPtr: 1034 case TYsharePtr: 1035 case TYrestrictPtr: 1036 case TYfgPtr: 1037 c = cast(char)('P' + cpp_cvidx(t.Tty)); 1038 CHAR(c); 1039 if(I64) 1040 CHAR('E'); // __ptr64 modifier 1041 cpp_pointer_type(t); 1042 break; 1043 case TYstruct: 1044 case TYenum: 1045 cpp_ecsu_data_type(t); 1046 break; 1047 case TYarray: 1048 i = cpp_cvidx(t.Tty); 1049 i |= 1; // always const 1050 CHAR('P' + i); 1051 cpp_pointer_type(t); 1052 break; 1053 case TYvoid: 1054 c = 'X'; 1055 goto dochar; 1056 version (SCPPorHTOD) 1057 { 1058 case TYident: 1059 if (pstate.STintemplate) 1060 { 1061 CHAR('V'); // pretend to be a class name 1062 cpp_zname(t.Tident); 1063 } 1064 else 1065 { 1066 version (SCPPorHTOD) 1067 { 1068 cpperr(EM_no_type,t.Tident); // no type for argument 1069 } 1070 c = 'X'; 1071 goto dochar; 1072 } 1073 break; 1074 case TYtemplate: 1075 if (pstate.STintemplate) 1076 { 1077 CHAR('V'); // pretend to be a class name 1078 cpp_zname((cast(typetemp_t *)t).Tsym.Sident.ptr); 1079 } 1080 else 1081 goto Ldefault; 1082 break; 1083 } 1084 1085 default: 1086 Ldefault: 1087 if (tyfunc(t.Tty)) 1088 cpp_function_type(t); 1089 else 1090 { 1091 version (SCPPorHTOD) 1092 { 1093 debug 1094 if (!errcnt) 1095 type_print(t); 1096 assert(errcnt); 1097 } 1098 } 1099 } 1100 } 1101 1102 private void cpp_function_indirect_type(type *t) 1103 { int farfunc; 1104 1105 farfunc = tyfarfunc(t.Tnext.Tty) != 0; 1106 version (SCPPorHTOD) 1107 { 1108 if (tybasic(t.Tty) == TYmemptr) 1109 { 1110 CHAR('8' + farfunc); 1111 cpp_scope(t.Ttag); 1112 CHAR('@'); 1113 //cpp_this_type(t.Tnext,t.Ttag); // MSC doesn't do this 1114 } 1115 else 1116 CHAR('6' + farfunc); 1117 } 1118 else 1119 CHAR('6' + farfunc); 1120 } 1121 1122 private void cpp_data_indirect_type(type *t) 1123 { int i; 1124 version (SCPPorHTOD) 1125 { 1126 if (tybasic(t.Tty) == TYmemptr) // if pointer to member 1127 { 1128 i = cpp_cvidx(t.Tty); 1129 if (t.Tty & mTYfar) 1130 i += 4; 1131 CHAR('Q' + i); 1132 cpp_scope(t.Ttag); 1133 CHAR('@'); 1134 } 1135 else 1136 cpp_ecsu_data_indirect_type(t); 1137 } 1138 else 1139 { 1140 cpp_ecsu_data_indirect_type(t); 1141 } 1142 } 1143 1144 private void cpp_ecsu_data_indirect_type(type *t) 1145 { int i; 1146 tym_t ty; 1147 1148 i = 0; 1149 if (t.Tnext) 1150 { ty = t.Tnext.Tty & (mTYconst | mTYvolatile); 1151 switch (tybasic(t.Tty)) 1152 { 1153 case TYfptr: 1154 case TYvptr: 1155 case TYfref: 1156 ty |= mTYfar; 1157 break; 1158 1159 case TYhptr: 1160 i += 8; 1161 break; 1162 case TYref: 1163 case TYarray: 1164 if (LARGEDATA && !(ty & mTYLINK)) 1165 ty |= mTYfar; 1166 break; 1167 1168 default: 1169 break; 1170 } 1171 } 1172 else 1173 ty = t.Tty & (mTYLINK | mTYconst | mTYvolatile); 1174 i |= cpp_cvidx(ty); 1175 if (ty & (mTYcs | mTYfar)) 1176 i += 4; 1177 CHAR('A' + i); 1178 } 1179 1180 private void cpp_pointer_type(type *t) 1181 { tym_t ty; 1182 1183 if (tyfunc(t.Tnext.Tty)) 1184 { 1185 cpp_function_indirect_type(t); 1186 cpp_function_type(t.Tnext); 1187 } 1188 else 1189 { 1190 cpp_data_indirect_type(t); 1191 cpp_pointer_data_type(t.Tnext); 1192 } 1193 } 1194 1195 private void cpp_reference_type(type *t) 1196 { 1197 cpp_data_indirect_type(t); 1198 cpp_reference_data_type(t.Tnext, 0); 1199 } 1200 1201 private void cpp_primary_data_type(type *t) 1202 { 1203 if (tyref(t.Tty)) 1204 { 1205 static if (1) 1206 { 1207 // C++98 8.3.2 says cv-qualified references are ignored 1208 CHAR('A'); 1209 } 1210 else 1211 { 1212 switch (t.Tty & (mTYconst | mTYvolatile)) 1213 { 1214 case 0: CHAR('A'); break; 1215 case mTYvolatile: CHAR('B'); break; 1216 1217 // Digital Mars extensions 1218 case mTYconst | mTYvolatile: CHAR('_'); CHAR('L'); break; 1219 case mTYconst: CHAR('_'); CHAR('M'); break; 1220 1221 default: 1222 break; 1223 } 1224 } 1225 cpp_reference_type(t); 1226 } 1227 else 1228 cpp_basic_data_type(t); 1229 } 1230 1231 /***** 1232 * flag: 1 = template argument 1233 */ 1234 1235 private void cpp_argument_list(type *t, int flag) 1236 { int i; 1237 tym_t ty; 1238 1239 //printf("cpp_argument_list(flag = %d)\n", flag); 1240 // If a data type that encodes only into one character 1241 ty = tybasic(t.Tty); 1242 if (ty <= TYldouble && ty != TYenum 1243 && ty != TYbool // added for versions >= 8.1b9 1244 && !(t.Tty & (mTYconst | mTYvolatile)) 1245 ) 1246 { 1247 cpp_primary_data_type(t); 1248 } 1249 else 1250 { 1251 // See if a match with a previously used type 1252 for (i = 0; 1; i++) 1253 { 1254 if (i == mangle.argi) // no match 1255 { 1256 if (ty <= TYcldouble || ty == TYstruct) 1257 { 1258 int cvidx = cpp_cvidx(t.Tty); 1259 if (cvidx) 1260 { 1261 // Digital Mars extensions 1262 CHAR('_'); 1263 CHAR('N' + cvidx); // _O, _P, _Q prefix 1264 } 1265 } 1266 if (flag && tybasic(t.Tty) == TYarray) 1267 { 1268 cpp_reference_data_type(t, flag); 1269 } 1270 else 1271 cpp_primary_data_type(t); 1272 if (mangle.argi < 10) 1273 mangle.arg[mangle.argi++] = t; 1274 break; 1275 } 1276 if (typematch(t,mangle.arg[i],0)) 1277 { 1278 CHAR('0' + i); // argument_replicator 1279 break; 1280 } 1281 } 1282 } 1283 } 1284 1285 private void cpp_argument_types(type *t) 1286 { param_t *p; 1287 char c; 1288 1289 //printf("cpp_argument_types()\n"); 1290 //type_debug(t); 1291 for (p = t.Tparamtypes; p; p = p.Pnext) 1292 cpp_argument_list(p.Ptype, 0); 1293 if (t.Tflags & TFfixed) 1294 c = t.Tparamtypes ? '@' : 'X'; 1295 else 1296 c = 'Z'; 1297 CHAR(c); 1298 } 1299 1300 private void cpp_calling_convention(type *t) 1301 { char c; 1302 1303 switch (tybasic(t.Tty)) 1304 { 1305 case TYnfunc: 1306 case TYhfunc: 1307 case TYffunc: 1308 c = 'A'; break; 1309 case TYf16func: 1310 case TYfpfunc: 1311 case TYnpfunc: 1312 c = 'C'; break; 1313 case TYnsfunc: 1314 case TYfsfunc: 1315 c = 'G'; break; 1316 case TYjfunc: 1317 case TYmfunc: 1318 case TYnsysfunc: 1319 case TYfsysfunc: 1320 c = 'E'; break; 1321 case TYifunc: 1322 c = 'K'; break; 1323 default: 1324 assert(0); 1325 } 1326 CHAR(c); 1327 } 1328 1329 private void cpp_vcall_model_type() 1330 { 1331 } 1332 1333 version (SCPPorMARS) 1334 { 1335 1336 private void cpp_this_type(type *tfunc,Classsym *stag) 1337 { type *t; 1338 1339 type_debug(tfunc); 1340 symbol_debug(stag); 1341 1342 version (MARS) 1343 t = type_pointer(stag.Stype); 1344 else 1345 t = cpp_thistype(tfunc,stag); 1346 1347 //cpp_data_indirect_type(t); 1348 cpp_ecsu_data_indirect_type(t); 1349 type_free(t); 1350 } 1351 1352 } 1353 1354 private void cpp_storage_convention(Symbol *s) 1355 { tym_t ty; 1356 type *t = s.Stype; 1357 1358 ty = t.Tty; 1359 if (LARGEDATA && !(ty & mTYLINK)) 1360 t.Tty |= mTYfar; 1361 cpp_data_indirect_type(t); 1362 t.Tty = ty; 1363 } 1364 1365 private void cpp_data_type(type *t) 1366 { 1367 type_debug(t); 1368 switch (tybasic(t.Tty)) 1369 { case TYvoid: 1370 CHAR('X'); 1371 break; 1372 case TYstruct: 1373 case TYenum: 1374 CHAR('?'); 1375 cpp_ecsu_data_indirect_type(t); 1376 cpp_ecsu_data_type(t); 1377 break; 1378 default: 1379 cpp_primary_data_type(t); 1380 break; 1381 } 1382 } 1383 1384 private void cpp_return_type(Symbol *s) 1385 { 1386 if (s.Sfunc.Fflags & (Fctor | Fdtor)) // if ctor or dtor 1387 CHAR('@'); // no type 1388 else 1389 cpp_data_type(s.Stype.Tnext); 1390 } 1391 1392 private void cpp_ecsu_name(Symbol *s) 1393 { 1394 //printf("cpp_ecsu_name(%s)\n", symbol_ident(s)); 1395 cpp_zname(symbol_ident(s)); 1396 version (SCPPorMARS) 1397 { 1398 if (s.Sscope) 1399 cpp_scope(s.Sscope); 1400 } 1401 CHAR('@'); 1402 } 1403 1404 private void cpp_throw_types(type *t) 1405 { 1406 //cpp_argument_types(?); 1407 CHAR('Z'); 1408 } 1409 1410 private void cpp_function_type(type *t) 1411 { tym_t ty; 1412 type *tn; 1413 1414 //printf("cpp_function_type()\n"); 1415 //type_debug(t); 1416 assert(tyfunc(t.Tty)); 1417 cpp_calling_convention(t); 1418 //cpp_return_type(s); 1419 tn = t.Tnext; 1420 ty = tn.Tty; 1421 if (LARGEDATA && (tybasic(ty) == TYstruct || tybasic(ty) == TYenum) && 1422 !(ty & mTYLINK)) 1423 tn.Tty |= mTYfar; 1424 cpp_data_type(tn); 1425 tn.Tty = ty; 1426 cpp_argument_types(t); 1427 cpp_throw_types(t); 1428 } 1429 1430 private void cpp_adjustor_thunk_type(Symbol *s) 1431 { 1432 } 1433 1434 private void cpp_vftable_type(Symbol *s) 1435 { 1436 cpp_ecsu_data_indirect_type(s.Stype); 1437 // vpath_name(); 1438 CHAR('@'); 1439 } 1440 1441 private void cpp_local_static_data_type(Symbol *s) 1442 { 1443 //cpp_lexical_frame(?); 1444 cpp_external_data_type(s); 1445 } 1446 1447 private void cpp_static_member_data_type(Symbol *s) 1448 { 1449 cpp_external_data_type(s); 1450 } 1451 1452 private void cpp_static_member_function_type(Symbol *s) 1453 { 1454 cpp_function_type(s.Stype); 1455 } 1456 1457 version (SCPPorMARS) 1458 { 1459 private void cpp_member_function_type(Symbol *s) 1460 { 1461 assert(tyfunc(s.Stype.Tty)); 1462 cpp_this_type(s.Stype,cast(Classsym *)s.Sscope); 1463 if (s.Sfunc.Fflags & (Fctor | Fdtor)) 1464 { type *t = s.Stype; 1465 1466 cpp_calling_convention(t); 1467 CHAR('@'); // return_type for ctors & dtors 1468 cpp_argument_types(t); 1469 cpp_throw_types(t); 1470 } 1471 else 1472 cpp_static_member_function_type(s); 1473 } 1474 } 1475 1476 private void cpp_external_data_type(Symbol *s) 1477 { 1478 cpp_primary_data_type(s.Stype); 1479 cpp_storage_convention(s); 1480 } 1481 1482 private void cpp_external_function_type(Symbol *s) 1483 { 1484 cpp_function_type(s.Stype); 1485 } 1486 1487 private void cpp_type_encoding(Symbol *s) 1488 { char c; 1489 1490 //printf("cpp_type_encoding()\n"); 1491 if (tyfunc(s.Stype.Tty)) 1492 { int farfunc; 1493 1494 farfunc = tyfarfunc(s.Stype.Tty) != 0; 1495 version (SCPPorMARS) 1496 { 1497 if (isclassmember(s)) 1498 { // Member function 1499 int protection; 1500 int ftype; 1501 1502 protection = cpp_protection(s); 1503 if (s.Sfunc.Fthunk && !(s.Sfunc.Fflags & Finstance)) 1504 ftype = 3; 1505 else 1506 switch (s.Sfunc.Fflags & (Fvirtual | Fstatic)) 1507 { case Fvirtual: ftype = 2; break; 1508 case Fstatic: ftype = 1; break; 1509 case 0: ftype = 0; break; 1510 default: assert(0); 1511 } 1512 CHAR('A' + farfunc + protection * 8 + ftype * 2); 1513 switch (ftype) 1514 { case 0: cpp_member_function_type(s); break; 1515 case 1: cpp_static_member_function_type(s); break; 1516 case 2: cpp_member_function_type(s); break; 1517 case 3: cpp_adjustor_thunk_type(s); break; 1518 default: 1519 break; 1520 } 1521 } 1522 else 1523 { // Non-member function 1524 CHAR('Y' + farfunc); 1525 cpp_external_function_type(s); 1526 } 1527 } 1528 else 1529 { 1530 // Non-member function 1531 CHAR('Y' + farfunc); 1532 cpp_external_function_type(s); 1533 } 1534 } 1535 else 1536 { 1537 version (SCPPorMARS) 1538 { 1539 if (isclassmember(s)) 1540 { 1541 // Static data member 1542 CHAR(cpp_protection(s) + '0'); 1543 cpp_static_member_data_type(s); 1544 } 1545 else 1546 { 1547 if (s.Sclass == SCstatic || 1548 (s.Sscope && 1549 s.Sscope.Sclass != SCstruct && 1550 s.Sscope.Sclass != SCnamespace)) 1551 { 1552 CHAR('4'); 1553 cpp_local_static_data_type(s); 1554 } 1555 else 1556 { 1557 CHAR('3'); 1558 cpp_external_data_type(s); 1559 } 1560 } 1561 } 1562 else 1563 { 1564 if (s.Sclass == SCstatic) 1565 { 1566 CHAR('4'); 1567 cpp_local_static_data_type(s); 1568 } 1569 else 1570 { 1571 CHAR('3'); 1572 cpp_external_data_type(s); 1573 } 1574 } 1575 } 1576 } 1577 1578 private void cpp_scope(Symbol *s) 1579 { 1580 /* scope ::= 1581 zname [ scope ] 1582 '?' decorated_name [ scope ] 1583 '?' lexical_frame [ scope ] 1584 '?' '$' template_name [ scope ] 1585 */ 1586 while (s) 1587 { char *p; 1588 1589 symbol_debug(s); 1590 switch (s.Sclass) 1591 { 1592 case SCnamespace: 1593 cpp_zname(s.Sident.ptr); 1594 break; 1595 1596 case SCstruct: 1597 cpp_zname(symbol_ident(s)); 1598 break; 1599 1600 default: 1601 STR("?1?"); // Why? Who knows. 1602 cpp_decorated_name(s); 1603 break; 1604 } 1605 1606 version (SCPPorMARS) 1607 s = s.Sscope; 1608 else 1609 break; 1610 1611 } 1612 } 1613 1614 private void cpp_zname(const(char)* p) 1615 { 1616 //printf("cpp_zname(%s)\n", p); 1617 if (*p != '?' || // if not operator_name 1618 (NEWTEMPMANGLE && p[1] == '$')) // ?$ is a template name 1619 { 1620 version (MARS) 1621 { 1622 /* Scan forward past any dots 1623 */ 1624 for (const(char)* q = p; *q; q++) 1625 { 1626 if (*q == '.') 1627 p = q + 1; 1628 } 1629 } 1630 1631 for (int i = 0; i < mangle.znamei; i++) 1632 { 1633 if (strcmp(p,mangle.zname[i]) == 0) 1634 { CHAR('0' + i); 1635 return; 1636 } 1637 } 1638 if (mangle.znamei < 10) 1639 mangle.zname[mangle.znamei++] = p; 1640 STR(p); 1641 CHAR('@'); 1642 } 1643 else if (p[1] == 'B') 1644 STR("?B"); // skip return value encoding 1645 else 1646 { 1647 STR(p); 1648 } 1649 } 1650 1651 private void cpp_symbol_name(Symbol *s) 1652 { char *p; 1653 1654 p = s.Sident.ptr; 1655 version (SCPPorHTOD) 1656 { 1657 if (tyfunc(s.Stype.Tty) && s.Sfunc) 1658 { 1659 if (s.Sfunc.Fflags & Finstance) 1660 { 1661 Mangle save = mangle; 1662 char *q; 1663 int len; 1664 1665 p = template_mangle(s, s.Sfunc.Fptal); 1666 len = strlen(p); 1667 q = cast(char *)alloca(len + 1); 1668 assert(q); 1669 memcpy(q, p, len + 1); 1670 mangle = save; 1671 p = q; 1672 } 1673 else if (s.Sfunc.Fflags & Foperator) 1674 { // operator_name ::= '?' operator_code 1675 //CHAR('?'); // already there 1676 STR(p); 1677 return; 1678 } 1679 } 1680 } 1681 version (none) //#if MARS && 0 1682 { 1683 //It mangles correctly, but the ABI doesn't match, 1684 // leading to copious segfaults. At least with the 1685 // wrong mangling you get link errors. 1686 if (tyfunc(s.Stype.Tty) && s.Sfunc) 1687 { 1688 if (s.Sfunc.Fflags & Fctor) 1689 { 1690 cpp_zname(cpp_name_ct); 1691 return; 1692 } 1693 if (s.Sfunc.Fflags & Fdtor) 1694 { 1695 cpp_zname(cpp_name_dt); 1696 return; 1697 } 1698 } 1699 } 1700 cpp_zname(p); 1701 } 1702 1703 private void cpp_decorated_name(Symbol *s) 1704 { char *p; 1705 1706 CHAR('?'); 1707 cpp_symbol_name(s); 1708 version (SCPPorMARS) 1709 { 1710 if (s.Sscope) 1711 cpp_scope(s.Sscope); 1712 } 1713 CHAR('@'); 1714 cpp_type_encoding(s); 1715 } 1716 1717 /********************************* 1718 * Mangle a vtbl or vbtbl name. 1719 * Returns: 1720 * pointer to generated symbol with mangled name 1721 */ 1722 1723 version (SCPPorHTOD) 1724 { 1725 1726 Symbol *mangle_tbl( 1727 int flag, // 0: vtbl, 1: vbtbl 1728 type *t, // type for symbol 1729 Classsym *stag, // class we're putting tbl in 1730 baseclass_t *b) // base class (null if none) 1731 { const(char)* id; 1732 Symbol *s; 1733 1734 static if (0) 1735 { 1736 printf("mangle_tbl(stag = '%s', sbase = '%s', parent = '%s')\n", 1737 stag.Sident.ptr,b ? b.BCbase.Sident.ptr : "null", b ? b.parent.Sident.ptr : "null"); 1738 } 1739 if (flag == 0) 1740 id = config.flags3 & CFG3rtti ? "?_Q" : "?_7"; 1741 else 1742 id = "?_8"; 1743 MangleInuse m; 1744 mangle.znamei = 0; 1745 mangle.argi = 0; 1746 mangle.np = mangle.buf.ptr; 1747 CHAR('?'); 1748 cpp_zname(id); 1749 cpp_scope(stag); 1750 CHAR('@'); 1751 CHAR('6' + flag); 1752 cpp_ecsu_data_indirect_type(t); 1753 static if (1) 1754 { 1755 while (b) 1756 { 1757 cpp_scope(b.BCbase); 1758 CHAR('@'); 1759 b = b.BCpbase; 1760 } 1761 } 1762 else 1763 { 1764 if (b) 1765 { cpp_scope(b.BCbase); 1766 CHAR('@'); 1767 // BUG: what if b is more than one level down? 1768 if (b.parent != stag) 1769 { cpp_scope(b.BCparent); 1770 CHAR('@'); 1771 } 1772 } 1773 } 1774 CHAR('@'); 1775 *mangle.np = 0; // 0-terminate mangle.buf[] 1776 assert(strlen(mangle.buf.ptr) <= BUFIDMAX); 1777 s = scope_define(mangle.buf.ptr,SCTglobal | SCTnspace | SCTlocal,SCunde); 1778 s.Stype = t; 1779 t.Tcount++; 1780 return s; 1781 } 1782 1783 } 1784 1785 }