1 2/* Compiler implementation of the D programming language 3 * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved 4 * written by Walter Bright 5 * http://www.digitalmars.com 6 * Distributed under the Boost Software License, Version 1.0. 7 * http://www.boost.org/LICENSE_1_0.txt 8 * https://github.com/D-Programming-Language/dmd/blob/master/src/mangle.c 9 */ 10 11#include "root/dsystem.h" 12#include "root/root.h" 13 14#include "mangle.h" 15#include "init.h" 16#include "declaration.h" 17#include "aggregate.h" 18#include "mtype.h" 19#include "attrib.h" 20#include "target.h" 21#include "template.h" 22#include "id.h" 23#include "module.h" 24#include "enum.h" 25#include "expression.h" 26#include "utf.h" 27 28typedef int (*ForeachDg)(void *ctx, size_t paramidx, Parameter *param); 29int Parameter_foreach(Parameters *parameters, ForeachDg dg, void *ctx, size_t *pn = NULL); 30 31static const char *mangleChar[TMAX]; 32 33void initTypeMangle() 34{ 35 mangleChar[Tarray] = "A"; 36 mangleChar[Tsarray] = "G"; 37 mangleChar[Taarray] = "H"; 38 mangleChar[Tpointer] = "P"; 39 mangleChar[Treference] = "R"; 40 mangleChar[Tfunction] = "F"; 41 mangleChar[Tident] = "I"; 42 mangleChar[Tclass] = "C"; 43 mangleChar[Tstruct] = "S"; 44 mangleChar[Tenum] = "E"; 45 mangleChar[Tdelegate] = "D"; 46 47 mangleChar[Tnone] = "n"; 48 mangleChar[Tvoid] = "v"; 49 mangleChar[Tint8] = "g"; 50 mangleChar[Tuns8] = "h"; 51 mangleChar[Tint16] = "s"; 52 mangleChar[Tuns16] = "t"; 53 mangleChar[Tint32] = "i"; 54 mangleChar[Tuns32] = "k"; 55 mangleChar[Tint64] = "l"; 56 mangleChar[Tuns64] = "m"; 57 mangleChar[Tint128] = "zi"; 58 mangleChar[Tuns128] = "zk"; 59 mangleChar[Tfloat32] = "f"; 60 mangleChar[Tfloat64] = "d"; 61 mangleChar[Tfloat80] = "e"; 62 63 mangleChar[Timaginary32] = "o"; 64 mangleChar[Timaginary64] = "p"; 65 mangleChar[Timaginary80] = "j"; 66 mangleChar[Tcomplex32] = "q"; 67 mangleChar[Tcomplex64] = "r"; 68 mangleChar[Tcomplex80] = "c"; 69 70 mangleChar[Tbool] = "b"; 71 mangleChar[Tchar] = "a"; 72 mangleChar[Twchar] = "u"; 73 mangleChar[Tdchar] = "w"; 74 75 // '@' shouldn't appear anywhere in the deco'd names 76 mangleChar[Tinstance] = "@"; 77 mangleChar[Terror] = "@"; 78 mangleChar[Ttypeof] = "@"; 79 mangleChar[Ttuple] = "B"; 80 mangleChar[Tslice] = "@"; 81 mangleChar[Treturn] = "@"; 82 mangleChar[Tvector] = "@"; 83 mangleChar[Ttraits] = "@"; 84 85 mangleChar[Tnull] = "n"; // same as TypeNone 86 87 for (size_t i = 0; i < TMAX; i++) 88 { 89 if (!mangleChar[i]) 90 fprintf(stderr, "ty = %llu\n", (ulonglong)i); 91 assert(mangleChar[i]); 92 } 93} 94 95/********************************* 96 * Mangling for mod. 97 */ 98void MODtoDecoBuffer(OutBuffer *buf, MOD mod) 99{ 100 switch (mod) 101 { 102 case 0: 103 break; 104 case MODconst: 105 buf->writeByte('x'); 106 break; 107 case MODimmutable: 108 buf->writeByte('y'); 109 break; 110 case MODshared: 111 buf->writeByte('O'); 112 break; 113 case MODshared | MODconst: 114 buf->writestring("Ox"); 115 break; 116 case MODwild: 117 buf->writestring("Ng"); 118 break; 119 case MODwildconst: 120 buf->writestring("Ngx"); 121 break; 122 case MODshared | MODwild: 123 buf->writestring("ONg"); 124 break; 125 case MODshared | MODwildconst: 126 buf->writestring("ONgx"); 127 break; 128 default: 129 assert(0); 130 } 131} 132 133class Mangler : public Visitor 134{ 135public: 136 OutBuffer *buf; 137 138 Mangler(OutBuffer *buf) 139 { 140 this->buf = buf; 141 } 142 143 144 //////////////////////////////////////////////////////////////////////////// 145 146 /************************************************** 147 * Type mangling 148 */ 149 150 void visitWithMask(Type *t, unsigned char modMask) 151 { 152 if (modMask != t->mod) 153 { 154 MODtoDecoBuffer(buf, t->mod); 155 } 156 t->accept(this); 157 } 158 159 void visit(Type *t) 160 { 161 buf->writestring(mangleChar[t->ty]); 162 } 163 164 void visit(TypeNext *t) 165 { 166 visit((Type *)t); 167 visitWithMask(t->next, t->mod); 168 } 169 170 void visit(TypeVector *t) 171 { 172 buf->writestring("Nh"); 173 visitWithMask(t->basetype, t->mod); 174 } 175 176 void visit(TypeSArray *t) 177 { 178 visit((Type *)t); 179 if (t->dim) 180 buf->print(t->dim->toInteger()); 181 if (t->next) 182 visitWithMask(t->next, t->mod); 183 } 184 185 void visit(TypeDArray *t) 186 { 187 visit((Type *)t); 188 if (t->next) 189 visitWithMask(t->next, t->mod); 190 } 191 192 void visit(TypeAArray *t) 193 { 194 visit((Type *)t); 195 visitWithMask(t->index, 0); 196 visitWithMask(t->next, t->mod); 197 } 198 199 void visit(TypeFunction *t) 200 { 201 //printf("TypeFunction::toDecoBuffer() t = %p %s\n", t, t->toChars()); 202 //static int nest; if (++nest == 50) *(char*)0=0; 203 204 mangleFuncType(t, t, t->mod, t->next); 205 } 206 207 void mangleFuncType(TypeFunction *t, TypeFunction *ta, unsigned char modMask, Type *tret) 208 { 209 //printf("mangleFuncType() %s\n", t->toChars()); 210 if (t->inuse) 211 { 212 t->inuse = 2; // flag error to caller 213 return; 214 } 215 t->inuse++; 216 217 if (modMask != t->mod) 218 MODtoDecoBuffer(buf, t->mod); 219 220 unsigned char mc; 221 switch (t->linkage) 222 { 223 case LINKd: mc = 'F'; break; 224 case LINKc: mc = 'U'; break; 225 case LINKwindows: mc = 'W'; break; 226 case LINKpascal: mc = 'V'; break; 227 case LINKcpp: mc = 'R'; break; 228 case LINKobjc: mc = 'Y'; break; 229 default: 230 assert(0); 231 } 232 buf->writeByte(mc); 233 234 if (ta->purity || ta->isnothrow || ta->isnogc || ta->isproperty || ta->isref || ta->trust || ta->isreturn || ta->isscope) 235 { 236 if (ta->purity) 237 buf->writestring("Na"); 238 if (ta->isnothrow) 239 buf->writestring("Nb"); 240 if (ta->isref) 241 buf->writestring("Nc"); 242 if (ta->isproperty) 243 buf->writestring("Nd"); 244 if (ta->isnogc) 245 buf->writestring("Ni"); 246 if (ta->isreturn) 247 buf->writestring("Nj"); 248 if (ta->isscope && !ta->isreturn && !ta->isscopeinferred) 249 buf->writestring("Nl"); 250 switch (ta->trust) 251 { 252 case TRUSTtrusted: 253 buf->writestring("Ne"); 254 break; 255 case TRUSTsafe: 256 buf->writestring("Nf"); 257 break; 258 default: 259 break; 260 } 261 } 262 263 // Write argument types 264 paramsToDecoBuffer(t->parameters); 265 //if (buf->data[buf->offset - 1] == '@') halt(); 266 buf->writeByte('Z' - t->varargs); // mark end of arg list 267 if (tret != NULL) 268 visitWithMask(tret, 0); 269 270 t->inuse--; 271 } 272 273 void visit(TypeIdentifier *t) 274 { 275 visit((Type *)t); 276 const char *name = t->ident->toChars(); 277 size_t len = strlen(name); 278 buf->print(len); 279 buf->writestring(name); 280 } 281 282 void visit(TypeEnum *t) 283 { 284 visit((Type *)t); 285 t->sym->accept(this); 286 } 287 288 void visit(TypeStruct *t) 289 { 290 //printf("TypeStruct::toDecoBuffer('%s') = '%s'\n", t->toChars(), name); 291 visit((Type *)t); 292 t->sym->accept(this); 293 } 294 295 void visit(TypeClass *t) 296 { 297 //printf("TypeClass::toDecoBuffer('%s' mod=%x) = '%s'\n", t->toChars(), mod, name); 298 visit((Type *)t); 299 t->sym->accept(this); 300 } 301 302 void visit(TypeTuple *t) 303 { 304 //printf("TypeTuple::toDecoBuffer() t = %p, %s\n", t, t->toChars()); 305 visit((Type *)t); 306 307 OutBuffer buf2; 308 buf2.reserve(32); 309 Mangler v(&buf2); 310 v.paramsToDecoBuffer(t->arguments); 311 const char *s = buf2.peekString(); 312 int len = (int)buf2.offset; 313 buf->printf("%d%.*s", len, len, s); 314 } 315 316 void visit(TypeNull *t) 317 { 318 visit((Type *)t); 319 } 320 321 //////////////////////////////////////////////////////////////////////////// 322 323 void mangleDecl(Declaration *sthis) 324 { 325 mangleParent(sthis); 326 327 assert(sthis->ident); 328 const char *id = sthis->ident->toChars(); 329 toBuffer(id, sthis); 330 331 if (FuncDeclaration *fd = sthis->isFuncDeclaration()) 332 { 333 mangleFunc(fd, false); 334 } 335 else if (sthis->type->deco) 336 { 337 buf->writestring(sthis->type->deco); 338 } 339 else 340 assert(0); 341 } 342 343 void mangleParent(Dsymbol *s) 344 { 345 Dsymbol *p; 346 if (TemplateInstance *ti = s->isTemplateInstance()) 347 p = ti->isTemplateMixin() ? ti->parent : ti->tempdecl->parent; 348 else 349 p = s->parent; 350 351 if (p) 352 { 353 mangleParent(p); 354 355 if (p->getIdent()) 356 { 357 const char *id = p->ident->toChars(); 358 toBuffer(id, s); 359 360 if (FuncDeclaration *f = p->isFuncDeclaration()) 361 mangleFunc(f, true); 362 } 363 else 364 buf->writeByte('0'); 365 } 366 } 367 368 void mangleFunc(FuncDeclaration *fd, bool inParent) 369 { 370 //printf("deco = '%s'\n", fd->type->deco ? fd->type->deco : "null"); 371 //printf("fd->type = %s\n", fd->type->toChars()); 372 if (fd->needThis() || fd->isNested()) 373 buf->writeByte('M'); 374 if (inParent) 375 { 376 TypeFunction *tf = (TypeFunction *)fd->type; 377 TypeFunction *tfo = (TypeFunction *)fd->originalType; 378 mangleFuncType(tf, tfo, 0, NULL); 379 } 380 else if (fd->type->deco) 381 { 382 buf->writestring(fd->type->deco); 383 } 384 else 385 { 386 printf("[%s] %s %s\n", fd->loc.toChars(), fd->toChars(), fd->type->toChars()); 387 assert(0); // don't mangle function until semantic3 done. 388 } 389 } 390 391 /************************************************************ 392 * Write length prefixed string to buf. 393 */ 394 void toBuffer(const char *id, Dsymbol *s) 395 { 396 size_t len = strlen(id); 397 if (len >= 8 * 1024 * 1024) // 8 megs ought be enough for anyone 398 s->error("excessive length %llu for symbol, possible recursive expansion?", len); 399 else 400 { 401 buf->print(len); 402 buf->write(id, len); 403 } 404 } 405 406 void visit(Declaration *d) 407 { 408 //printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n", 409 // d, d->toChars(), d->parent ? d->parent->toChars() : "null", d->linkage); 410 if (!d->parent || d->parent->isModule() || d->linkage == LINKcpp) // if at global scope 411 { 412 switch (d->linkage) 413 { 414 case LINKd: 415 break; 416 417 case LINKc: 418 case LINKwindows: 419 case LINKpascal: 420 case LINKobjc: 421 buf->writestring(d->ident->toChars()); 422 return; 423 424 case LINKcpp: 425 buf->writestring(Target::toCppMangle(d)); 426 return; 427 428 case LINKdefault: 429 d->error("forward declaration"); 430 buf->writestring(d->ident->toChars()); 431 return; 432 433 default: 434 fprintf(stderr, "'%s', linkage = %d\n", d->toChars(), d->linkage); 435 assert(0); 436 return; 437 } 438 } 439 440 buf->writestring("_D"); 441 mangleDecl(d); 442 } 443 444 /****************************************************************************** 445 * Normally FuncDeclaration and FuncAliasDeclaration have overloads. 446 * If and only if there is no overloads, mangle() could return 447 * exact mangled name. 448 * 449 * module test; 450 * void foo(long) {} // _D4test3fooFlZv 451 * void foo(string) {} // _D4test3fooFAyaZv 452 * 453 * // from FuncDeclaration::mangle(). 454 * pragma(msg, foo.mangleof); // prints unexact mangled name "4test3foo" 455 * // by calling Dsymbol::mangle() 456 * 457 * // from FuncAliasDeclaration::mangle() 458 * pragma(msg, __traits(getOverloads, test, "foo")[0].mangleof); // "_D4test3fooFlZv" 459 * pragma(msg, __traits(getOverloads, test, "foo")[1].mangleof); // "_D4test3fooFAyaZv" 460 * 461 * If a function has no overloads, .mangleof property still returns exact mangled name. 462 * 463 * void bar() {} 464 * pragma(msg, bar.mangleof); // still prints "_D4test3barFZv" 465 * // by calling FuncDeclaration::mangleExact(). 466 */ 467 void visit(FuncDeclaration *fd) 468 { 469 if (fd->isUnique()) 470 mangleExact(fd); 471 else 472 visit((Dsymbol *)fd); 473 } 474 475 // ditto 476 void visit(FuncAliasDeclaration *fd) 477 { 478 FuncDeclaration *f = fd->toAliasFunc(); 479 FuncAliasDeclaration *fa = f->isFuncAliasDeclaration(); 480 if (!fd->hasOverloads && !fa) 481 { 482 mangleExact(f); 483 return; 484 } 485 if (fa) 486 { 487 fa->accept(this); 488 return; 489 } 490 visit((Dsymbol *)fd); 491 } 492 493 void visit(OverDeclaration *od) 494 { 495 if (od->overnext) 496 { 497 visit((Dsymbol *)od); 498 return; 499 } 500 501 if (FuncDeclaration *fd = od->aliassym->isFuncDeclaration()) 502 { 503 if (!od->hasOverloads || fd->isUnique()) 504 { 505 mangleExact(fd); 506 return; 507 } 508 } 509 if (TemplateDeclaration *td = od->aliassym->isTemplateDeclaration()) 510 { 511 if (!od->hasOverloads || td->overnext == NULL) 512 { 513 td->accept(this); 514 return; 515 } 516 } 517 visit((Dsymbol *)od); 518 } 519 520 void mangleExact(FuncDeclaration *fd) 521 { 522 assert(!fd->isFuncAliasDeclaration()); 523 524 if (fd->mangleOverride) 525 { 526 buf->writestring(fd->mangleOverride); 527 return; 528 } 529 530 if (fd->isMain()) 531 { 532 buf->writestring("_Dmain"); 533 return; 534 } 535 536 if (fd->isWinMain() || fd->isDllMain() || fd->ident == Id::tls_get_addr) 537 { 538 buf->writestring(fd->ident->toChars()); 539 return; 540 } 541 542 visit((Declaration *)fd); 543 } 544 545 void visit(VarDeclaration *vd) 546 { 547 if (vd->mangleOverride) 548 { 549 buf->writestring(vd->mangleOverride); 550 return; 551 } 552 553 visit((Declaration *)vd); 554 } 555 556 void visit(AggregateDeclaration *ad) 557 { 558 ClassDeclaration *cd = ad->isClassDeclaration(); 559 Dsymbol *parentsave = ad->parent; 560 if (cd) 561 { 562 /* These are reserved to the compiler, so keep simple 563 * names for them. 564 */ 565 if ((cd->ident == Id::Exception && cd->parent->ident == Id::object) || 566 cd->ident == Id::TypeInfo || 567 cd->ident == Id::TypeInfo_Struct || 568 cd->ident == Id::TypeInfo_Class || 569 cd->ident == Id::TypeInfo_Tuple || 570 cd == ClassDeclaration::object || 571 cd == Type::typeinfoclass || 572 cd == Module::moduleinfo || 573 strncmp(cd->ident->toChars(), "TypeInfo_", 9) == 0) 574 { 575 // Don't mangle parent 576 ad->parent = NULL; 577 } 578 } 579 580 visit((Dsymbol *)ad); 581 582 ad->parent = parentsave; 583 } 584 585 void visit(TemplateInstance *ti) 586 { 587 if (!ti->tempdecl) 588 ti->error("is not defined"); 589 else 590 mangleParent(ti); 591 592 ti->getIdent(); 593 const char *id = ti->ident ? ti->ident->toChars() : ti->toChars(); 594 toBuffer(id, ti); 595 596 //printf("TemplateInstance::mangle() %s = %s\n", ti->toChars(), ti->id); 597 } 598 599 void visit(Dsymbol *s) 600 { 601 mangleParent(s); 602 603 const char *id = s->ident ? s->ident->toChars() : s->toChars(); 604 toBuffer(id, s); 605 606 //printf("Dsymbol::mangle() %s = %s\n", s->toChars(), id); 607 } 608 609 //////////////////////////////////////////////////////////////////////////// 610 611 void visit(Expression *e) 612 { 613 e->error("expression %s is not a valid template value argument", e->toChars()); 614 } 615 616 void visit(IntegerExp *e) 617 { 618 if ((sinteger_t)e->value < 0) 619 { 620 buf->writeByte('N'); 621 buf->print(-e->value); 622 } 623 else 624 { 625 buf->writeByte('i'); 626 buf->print(e->value); 627 } 628 } 629 630 void visit(RealExp *e) 631 { 632 buf->writeByte('e'); 633 realToMangleBuffer(e->value); 634 } 635 636 void realToMangleBuffer(real_t value) 637 { 638 /* Rely on %A to get portable mangling. 639 * Must munge result to get only identifier characters. 640 * 641 * Possible values from %A => mangled result 642 * NAN => NAN 643 * -INF => NINF 644 * INF => INF 645 * -0X1.1BC18BA997B95P+79 => N11BC18BA997B95P79 646 * 0X1.9P+2 => 19P2 647 */ 648 649 if (CTFloat::isNaN(value)) 650 buf->writestring("NAN"); // no -NAN bugs 651 else if (CTFloat::isInfinity(value)) 652 buf->writestring(value < CTFloat::zero ? "NINF" : "INF"); 653 else 654 { 655 const size_t BUFFER_LEN = 36; 656 char buffer[BUFFER_LEN]; 657 size_t n = CTFloat::sprint(buffer, 'A', value); 658 assert(n < BUFFER_LEN); 659 for (size_t i = 0; i < n; i++) 660 { 661 char c = buffer[i]; 662 switch (c) 663 { 664 case '-': 665 buf->writeByte('N'); 666 break; 667 668 case '+': 669 case 'X': 670 case '.': 671 break; 672 673 case '0': 674 if (i < 2) 675 break; // skip leading 0X 676 /* fall through */ 677 default: 678 buf->writeByte(c); 679 break; 680 } 681 } 682 } 683 } 684 685 void visit(ComplexExp *e) 686 { 687 buf->writeByte('c'); 688 realToMangleBuffer(e->toReal()); 689 buf->writeByte('c'); // separate the two 690 realToMangleBuffer(e->toImaginary()); 691 } 692 693 void visit(NullExp *) 694 { 695 buf->writeByte('n'); 696 } 697 698 void visit(StringExp *e) 699 { 700 char m; 701 OutBuffer tmp; 702 utf8_t *q; 703 size_t qlen; 704 705 /* Write string in UTF-8 format 706 */ 707 switch (e->sz) 708 { 709 case 1: 710 m = 'a'; 711 q = (utf8_t *)e->string; 712 qlen = e->len; 713 break; 714 715 case 2: 716 m = 'w'; 717 for (size_t u = 0; u < e->len; ) 718 { 719 unsigned c; 720 const char *p = utf_decodeWchar((unsigned short *)e->string, e->len, &u, &c); 721 if (p) 722 e->error("%s", p); 723 else 724 tmp.writeUTF8(c); 725 } 726 q = (utf8_t *)tmp.data; 727 qlen = tmp.offset; 728 break; 729 730 case 4: 731 m = 'd'; 732 for (size_t u = 0; u < e->len; u++) 733 { 734 unsigned c = ((unsigned *)e->string)[u]; 735 if (!utf_isValidDchar(c)) 736 e->error("invalid UCS-32 char \\U%08x", c); 737 else 738 tmp.writeUTF8(c); 739 } 740 q = (utf8_t *)tmp.data; 741 qlen = tmp.offset; 742 break; 743 744 default: 745 assert(0); 746 } 747 buf->reserve(1 + 11 + 2 * qlen); 748 buf->writeByte(m); 749 buf->print(qlen); 750 buf->writeByte('_'); // nbytes <= 11 751 752 for (utf8_t *p = (utf8_t *)buf->data + buf->offset, *pend = p + 2 * qlen; 753 p < pend; p += 2, ++q) 754 { 755 utf8_t hi = *q >> 4 & 0xF; 756 p[0] = (utf8_t)(hi < 10 ? hi + '0' : hi - 10 + 'a'); 757 utf8_t lo = *q & 0xF; 758 p[1] = (utf8_t)(lo < 10 ? lo + '0' : lo - 10 + 'a'); 759 } 760 buf->offset += 2 * qlen; 761 } 762 763 void visit(ArrayLiteralExp *e) 764 { 765 size_t dim = e->elements ? e->elements->dim : 0; 766 buf->writeByte('A'); 767 buf->print(dim); 768 for (size_t i = 0; i < dim; i++) 769 { 770 e->getElement(i)->accept(this); 771 } 772 } 773 774 void visit(AssocArrayLiteralExp *e) 775 { 776 size_t dim = e->keys->dim; 777 buf->writeByte('A'); 778 buf->print(dim); 779 for (size_t i = 0; i < dim; i++) 780 { 781 (*e->keys)[i]->accept(this); 782 (*e->values)[i]->accept(this); 783 } 784 } 785 786 void visit(StructLiteralExp *e) 787 { 788 size_t dim = e->elements ? e->elements->dim : 0; 789 buf->writeByte('S'); 790 buf->print(dim); 791 for (size_t i = 0; i < dim; i++) 792 { 793 Expression *ex = (*e->elements)[i]; 794 if (ex) 795 ex->accept(this); 796 else 797 buf->writeByte('v'); // 'v' for void 798 } 799 } 800 801 //////////////////////////////////////////////////////////////////////////// 802 803 void paramsToDecoBuffer(Parameters *parameters) 804 { 805 //printf("Parameter::paramsToDecoBuffer()\n"); 806 Parameter_foreach(parameters, ¶msToDecoBufferDg, (void *)this); 807 } 808 809 static int paramsToDecoBufferDg(void *ctx, size_t, Parameter *p) 810 { 811 p->accept((Visitor *)ctx); 812 return 0; 813 } 814 815 void visit(Parameter *p) 816 { 817 if (p->storageClass & STCscope && !(p->storageClass & STCscopeinferred)) 818 buf->writeByte('M'); 819 // 'return inout ref' is the same as 'inout ref' 820 if ((p->storageClass & (STCreturn | STCwild)) == STCreturn) 821 buf->writestring("Nk"); 822 switch (p->storageClass & (STCin | STCout | STCref | STClazy)) 823 { 824 case 0: 825 case STCin: 826 break; 827 case STCout: 828 buf->writeByte('J'); 829 break; 830 case STCref: 831 buf->writeByte('K'); 832 break; 833 case STClazy: 834 buf->writeByte('L'); 835 break; 836 default: 837 assert(0); 838 } 839 visitWithMask(p->type, 0); 840 } 841}; 842 843/****************************************************************************** 844 * Returns exact mangled name of function. 845 */ 846const char *mangleExact(FuncDeclaration *fd) 847{ 848 if (!fd->mangleString) 849 { 850 OutBuffer buf; 851 Mangler v(&buf); 852 v.mangleExact(fd); 853 fd->mangleString = buf.extractString(); 854 } 855 return fd->mangleString; 856} 857 858void mangleToBuffer(Type *t, OutBuffer *buf) 859{ 860 Mangler v(buf); 861 v.visitWithMask(t, 0); 862} 863 864void mangleToBuffer(Expression *e, OutBuffer *buf) 865{ 866 Mangler v(buf); 867 e->accept(&v); 868} 869 870void mangleToBuffer(Dsymbol *s, OutBuffer *buf) 871{ 872 Mangler v(buf); 873 s->accept(&v); 874} 875