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