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 
28 typedef int (*ForeachDg)(void *ctx, size_t paramidx, Parameter *param);
29 int Parameter_foreach(Parameters *parameters, ForeachDg dg, void *ctx, size_t *pn = NULL);
30 
31 static const char *mangleChar[TMAX];
32 
initTypeMangle()33 void 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  */
MODtoDecoBuffer(OutBuffer * buf,MOD mod)98 void 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 
133 class Mangler : public Visitor
134 {
135 public:
136     OutBuffer *buf;
137 
Mangler(OutBuffer * buf)138     Mangler(OutBuffer *buf)
139     {
140         this->buf = buf;
141     }
142 
143 
144     ////////////////////////////////////////////////////////////////////////////
145 
146     /**************************************************
147      * Type mangling
148      */
149 
visitWithMask(Type * t,unsigned char modMask)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 
visit(Type * t)159     void visit(Type *t)
160     {
161         buf->writestring(mangleChar[t->ty]);
162     }
163 
visit(TypeNext * t)164     void visit(TypeNext *t)
165     {
166         visit((Type *)t);
167         visitWithMask(t->next, t->mod);
168     }
169 
visit(TypeVector * t)170     void visit(TypeVector *t)
171     {
172         buf->writestring("Nh");
173         visitWithMask(t->basetype, t->mod);
174     }
175 
visit(TypeSArray * t)176     void visit(TypeSArray *t)
177     {
178         visit((Type *)t);
179         if (t->dim)
180             buf->printf("%llu", t->dim->toInteger());
181         if (t->next)
182             visitWithMask(t->next, t->mod);
183     }
184 
visit(TypeDArray * t)185     void visit(TypeDArray *t)
186     {
187         visit((Type *)t);
188         if (t->next)
189             visitWithMask(t->next, t->mod);
190     }
191 
visit(TypeAArray * t)192     void visit(TypeAArray *t)
193     {
194         visit((Type *)t);
195         visitWithMask(t->index, 0);
196         visitWithMask(t->next, t->mod);
197     }
198 
visit(TypeFunction * t)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 
mangleFuncType(TypeFunction * t,TypeFunction * ta,unsigned char modMask,Type * tret)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 
visit(TypeIdentifier * t)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->printf("%u%s", (unsigned)len, name);
279     }
280 
visit(TypeEnum * t)281     void visit(TypeEnum *t)
282     {
283         visit((Type *)t);
284         t->sym->accept(this);
285     }
286 
visit(TypeStruct * t)287     void visit(TypeStruct *t)
288     {
289         //printf("TypeStruct::toDecoBuffer('%s') = '%s'\n", t->toChars(), name);
290         visit((Type *)t);
291         t->sym->accept(this);
292     }
293 
visit(TypeClass * t)294     void visit(TypeClass *t)
295     {
296         //printf("TypeClass::toDecoBuffer('%s' mod=%x) = '%s'\n", t->toChars(), mod, name);
297         visit((Type *)t);
298         t->sym->accept(this);
299     }
300 
visit(TypeTuple * t)301     void visit(TypeTuple *t)
302     {
303         //printf("TypeTuple::toDecoBuffer() t = %p, %s\n", t, t->toChars());
304         visit((Type *)t);
305 
306         OutBuffer buf2;
307         buf2.reserve(32);
308         Mangler v(&buf2);
309         v.paramsToDecoBuffer(t->arguments);
310         const char *s = buf2.peekString();
311         int len = (int)buf2.offset;
312         buf->printf("%d%.*s", len, len, s);
313     }
314 
visit(TypeNull * t)315     void visit(TypeNull *t)
316     {
317         visit((Type *)t);
318     }
319 
320     ////////////////////////////////////////////////////////////////////////////
321 
mangleDecl(Declaration * sthis)322     void mangleDecl(Declaration *sthis)
323     {
324         mangleParent(sthis);
325 
326         assert(sthis->ident);
327         const char *id = sthis->ident->toChars();
328         toBuffer(id, sthis);
329 
330         if (FuncDeclaration *fd = sthis->isFuncDeclaration())
331         {
332             mangleFunc(fd, false);
333         }
334         else if (sthis->type->deco)
335         {
336             buf->writestring(sthis->type->deco);
337         }
338         else
339             assert(0);
340     }
341 
mangleParent(Dsymbol * s)342     void mangleParent(Dsymbol *s)
343     {
344         Dsymbol *p;
345         if (TemplateInstance *ti = s->isTemplateInstance())
346             p = ti->isTemplateMixin() ? ti->parent : ti->tempdecl->parent;
347         else
348             p = s->parent;
349 
350         if (p)
351         {
352             mangleParent(p);
353 
354             if (p->getIdent())
355             {
356                 const char *id = p->ident->toChars();
357                 toBuffer(id, s);
358 
359                 if (FuncDeclaration *f = p->isFuncDeclaration())
360                     mangleFunc(f, true);
361             }
362             else
363                 buf->writeByte('0');
364         }
365     }
366 
mangleFunc(FuncDeclaration * fd,bool inParent)367     void mangleFunc(FuncDeclaration *fd, bool inParent)
368     {
369         //printf("deco = '%s'\n", fd->type->deco ? fd->type->deco : "null");
370         //printf("fd->type = %s\n", fd->type->toChars());
371         if (fd->needThis() || fd->isNested())
372             buf->writeByte('M');
373         if (inParent)
374         {
375             TypeFunction *tf = (TypeFunction *)fd->type;
376             TypeFunction *tfo = (TypeFunction *)fd->originalType;
377             mangleFuncType(tf, tfo, 0, NULL);
378         }
379         else if (fd->type->deco)
380         {
381             buf->writestring(fd->type->deco);
382         }
383         else
384         {
385             printf("[%s] %s %s\n", fd->loc.toChars(), fd->toChars(), fd->type->toChars());
386             assert(0);  // don't mangle function until semantic3 done.
387         }
388     }
389 
390     /************************************************************
391      * Write length prefixed string to buf.
392      */
toBuffer(const char * id,Dsymbol * s)393     void toBuffer(const char *id, Dsymbol *s)
394     {
395         size_t len = strlen(id);
396         if (len >= 8 * 1024 * 1024)         // 8 megs ought be enough for anyone
397             s->error("excessive length %llu for symbol, possible recursive expansion?", len);
398         else
399         {
400             buf->printf("%llu", (ulonglong)len);
401             buf->write(id, len);
402         }
403     }
404 
visit(Declaration * d)405     void visit(Declaration *d)
406     {
407         //printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n",
408         //        d, d->toChars(), d->parent ? d->parent->toChars() : "null", d->linkage);
409         if (!d->parent || d->parent->isModule() || d->linkage == LINKcpp) // if at global scope
410         {
411             switch (d->linkage)
412             {
413                 case LINKd:
414                     break;
415 
416                 case LINKc:
417                 case LINKwindows:
418                 case LINKpascal:
419                 case LINKobjc:
420                     buf->writestring(d->ident->toChars());
421                     return;
422 
423                 case LINKcpp:
424                     buf->writestring(Target::toCppMangle(d));
425                     return;
426 
427                 case LINKdefault:
428                     d->error("forward declaration");
429                     buf->writestring(d->ident->toChars());
430                     return;
431 
432                 default:
433                     fprintf(stderr, "'%s', linkage = %d\n", d->toChars(), d->linkage);
434                     assert(0);
435                     return;
436             }
437         }
438 
439         buf->writestring("_D");
440         mangleDecl(d);
441     }
442 
443     /******************************************************************************
444      * Normally FuncDeclaration and FuncAliasDeclaration have overloads.
445      * If and only if there is no overloads, mangle() could return
446      * exact mangled name.
447      *
448      *      module test;
449      *      void foo(long) {}           // _D4test3fooFlZv
450      *      void foo(string) {}         // _D4test3fooFAyaZv
451      *
452      *      // from FuncDeclaration::mangle().
453      *      pragma(msg, foo.mangleof);  // prints unexact mangled name "4test3foo"
454      *                                  // by calling Dsymbol::mangle()
455      *
456      *      // from FuncAliasDeclaration::mangle()
457      *      pragma(msg, __traits(getOverloads, test, "foo")[0].mangleof);  // "_D4test3fooFlZv"
458      *      pragma(msg, __traits(getOverloads, test, "foo")[1].mangleof);  // "_D4test3fooFAyaZv"
459      *
460      * If a function has no overloads, .mangleof property still returns exact mangled name.
461      *
462      *      void bar() {}
463      *      pragma(msg, bar.mangleof);  // still prints "_D4test3barFZv"
464      *                                  // by calling FuncDeclaration::mangleExact().
465      */
visit(FuncDeclaration * fd)466     void visit(FuncDeclaration *fd)
467     {
468         if (fd->isUnique())
469             mangleExact(fd);
470         else
471             visit((Dsymbol *)fd);
472     }
473 
474     // ditto
visit(FuncAliasDeclaration * fd)475     void visit(FuncAliasDeclaration *fd)
476     {
477         FuncDeclaration *f = fd->toAliasFunc();
478         FuncAliasDeclaration *fa = f->isFuncAliasDeclaration();
479         if (!fd->hasOverloads && !fa)
480         {
481             mangleExact(f);
482             return;
483         }
484         if (fa)
485         {
486             fa->accept(this);
487             return;
488         }
489         visit((Dsymbol *)fd);
490     }
491 
visit(OverDeclaration * od)492     void visit(OverDeclaration *od)
493     {
494         if (od->overnext)
495         {
496             visit((Dsymbol *)od);
497             return;
498         }
499 
500         if (FuncDeclaration *fd = od->aliassym->isFuncDeclaration())
501         {
502             if (!od->hasOverloads || fd->isUnique())
503             {
504                 mangleExact(fd);
505                 return;
506             }
507         }
508         if (TemplateDeclaration *td = od->aliassym->isTemplateDeclaration())
509         {
510             if (!od->hasOverloads || td->overnext == NULL)
511             {
512                 td->accept(this);
513                 return;
514             }
515         }
516         visit((Dsymbol *)od);
517     }
518 
mangleExact(FuncDeclaration * fd)519     void mangleExact(FuncDeclaration *fd)
520     {
521         assert(!fd->isFuncAliasDeclaration());
522 
523         if (fd->mangleOverride)
524         {
525             buf->writestring(fd->mangleOverride);
526             return;
527         }
528 
529         if (fd->isMain())
530         {
531             buf->writestring("_Dmain");
532             return;
533         }
534 
535         if (fd->isWinMain() || fd->isDllMain() || fd->ident == Id::tls_get_addr)
536         {
537             buf->writestring(fd->ident->toChars());
538             return;
539         }
540 
541         visit((Declaration *)fd);
542     }
543 
visit(VarDeclaration * vd)544     void visit(VarDeclaration *vd)
545     {
546         if (vd->mangleOverride)
547         {
548             buf->writestring(vd->mangleOverride);
549             return;
550         }
551 
552         visit((Declaration *)vd);
553     }
554 
visit(AggregateDeclaration * ad)555     void visit(AggregateDeclaration *ad)
556     {
557         ClassDeclaration *cd = ad->isClassDeclaration();
558         Dsymbol *parentsave = ad->parent;
559         if (cd)
560         {
561             /* These are reserved to the compiler, so keep simple
562              * names for them.
563              */
564             if ((cd->ident == Id::Exception && cd->parent->ident == Id::object) ||
565                 cd->ident == Id::TypeInfo ||
566                 cd->ident == Id::TypeInfo_Struct ||
567                 cd->ident == Id::TypeInfo_Class ||
568                 cd->ident == Id::TypeInfo_Tuple ||
569                 cd == ClassDeclaration::object ||
570                 cd == Type::typeinfoclass ||
571                 cd == Module::moduleinfo ||
572                 strncmp(cd->ident->toChars(), "TypeInfo_", 9) == 0)
573             {
574                 // Don't mangle parent
575                 ad->parent = NULL;
576             }
577         }
578 
579         visit((Dsymbol *)ad);
580 
581         ad->parent = parentsave;
582     }
583 
visit(TemplateInstance * ti)584     void visit(TemplateInstance *ti)
585     {
586         if (!ti->tempdecl)
587             ti->error("is not defined");
588         else
589             mangleParent(ti);
590 
591         ti->getIdent();
592         const char *id = ti->ident ? ti->ident->toChars() : ti->toChars();
593         toBuffer(id, ti);
594 
595         //printf("TemplateInstance::mangle() %s = %s\n", ti->toChars(), ti->id);
596     }
597 
visit(Dsymbol * s)598     void visit(Dsymbol *s)
599     {
600         mangleParent(s);
601 
602         const char *id = s->ident ? s->ident->toChars() : s->toChars();
603         toBuffer(id, s);
604 
605         //printf("Dsymbol::mangle() %s = %s\n", s->toChars(), id);
606     }
607 
608     ////////////////////////////////////////////////////////////////////////////
609 
visit(Expression * e)610     void visit(Expression *e)
611     {
612         e->error("expression %s is not a valid template value argument", e->toChars());
613     }
614 
visit(IntegerExp * e)615     void visit(IntegerExp *e)
616     {
617         if ((sinteger_t)e->value < 0)
618             buf->printf("N%lld", -e->value);
619         else
620             buf->printf("i%lld",  e->value);
621     }
622 
visit(RealExp * e)623     void visit(RealExp *e)
624     {
625         buf->writeByte('e');
626         realToMangleBuffer(e->value);
627     }
628 
realToMangleBuffer(real_t value)629     void realToMangleBuffer(real_t value)
630     {
631         /* Rely on %A to get portable mangling.
632          * Must munge result to get only identifier characters.
633          *
634          * Possible values from %A  => mangled result
635          * NAN                      => NAN
636          * -INF                     => NINF
637          * INF                      => INF
638          * -0X1.1BC18BA997B95P+79   => N11BC18BA997B95P79
639          * 0X1.9P+2                 => 19P2
640          */
641 
642         if (CTFloat::isNaN(value))
643             buf->writestring("NAN");        // no -NAN bugs
644         else if (CTFloat::isInfinity(value))
645             buf->writestring(value < CTFloat::zero ? "NINF" : "INF");
646         else
647         {
648             const size_t BUFFER_LEN = 36;
649             char buffer[BUFFER_LEN];
650             size_t n = CTFloat::sprint(buffer, 'A', value);
651             assert(n < BUFFER_LEN);
652             for (size_t i = 0; i < n; i++)
653             {
654                 char c = buffer[i];
655                 switch (c)
656                 {
657                     case '-':
658                         buf->writeByte('N');
659                         break;
660 
661                     case '+':
662                     case 'X':
663                     case '.':
664                         break;
665 
666                     case '0':
667                         if (i < 2)
668                             break;          // skip leading 0X
669                         /* fall through */
670                     default:
671                         buf->writeByte(c);
672                         break;
673                 }
674             }
675         }
676     }
677 
visit(ComplexExp * e)678     void visit(ComplexExp *e)
679     {
680         buf->writeByte('c');
681         realToMangleBuffer(e->toReal());
682         buf->writeByte('c');        // separate the two
683         realToMangleBuffer(e->toImaginary());
684     }
685 
visit(NullExp *)686     void visit(NullExp *)
687     {
688         buf->writeByte('n');
689     }
690 
visit(StringExp * e)691     void visit(StringExp *e)
692     {
693         char m;
694         OutBuffer tmp;
695         utf8_t *q;
696         size_t qlen;
697 
698         /* Write string in UTF-8 format
699          */
700         switch (e->sz)
701         {
702             case 1:
703                 m = 'a';
704                 q = (utf8_t *)e->string;
705                 qlen = e->len;
706                 break;
707 
708             case 2:
709                 m = 'w';
710                 for (size_t u = 0; u < e->len; )
711                 {
712                     unsigned c;
713                     const char *p = utf_decodeWchar((unsigned short *)e->string, e->len, &u, &c);
714                     if (p)
715                         e->error("%s", p);
716                     else
717                         tmp.writeUTF8(c);
718                 }
719                 q = (utf8_t *)tmp.data;
720                 qlen = tmp.offset;
721                 break;
722 
723             case 4:
724                 m = 'd';
725                 for (size_t u = 0; u < e->len; u++)
726                 {
727                     unsigned c = ((unsigned *)e->string)[u];
728                     if (!utf_isValidDchar(c))
729                         e->error("invalid UCS-32 char \\U%08x", c);
730                     else
731                         tmp.writeUTF8(c);
732                 }
733                 q = (utf8_t *)tmp.data;
734                 qlen = tmp.offset;
735                 break;
736 
737             default:
738                 assert(0);
739         }
740         buf->reserve(1 + 11 + 2 * qlen);
741         buf->writeByte(m);
742         buf->printf("%d_", (int)qlen); // nbytes <= 11
743 
744         for (utf8_t *p = (utf8_t *)buf->data + buf->offset, *pend = p + 2 * qlen;
745              p < pend; p += 2, ++q)
746         {
747             utf8_t hi = *q >> 4 & 0xF;
748             p[0] = (utf8_t)(hi < 10 ? hi + '0' : hi - 10 + 'a');
749             utf8_t lo = *q & 0xF;
750             p[1] = (utf8_t)(lo < 10 ? lo + '0' : lo - 10 + 'a');
751         }
752         buf->offset += 2 * qlen;
753     }
754 
visit(ArrayLiteralExp * e)755     void visit(ArrayLiteralExp *e)
756     {
757         size_t dim = e->elements ? e->elements->dim : 0;
758         buf->printf("A%u", dim);
759         for (size_t i = 0; i < dim; i++)
760         {
761             e->getElement(i)->accept(this);
762         }
763     }
764 
visit(AssocArrayLiteralExp * e)765     void visit(AssocArrayLiteralExp *e)
766     {
767         size_t dim = e->keys->dim;
768         buf->printf("A%u", dim);
769         for (size_t i = 0; i < dim; i++)
770         {
771             (*e->keys)[i]->accept(this);
772             (*e->values)[i]->accept(this);
773         }
774     }
775 
visit(StructLiteralExp * e)776     void visit(StructLiteralExp *e)
777     {
778         size_t dim = e->elements ? e->elements->dim : 0;
779         buf->printf("S%u", dim);
780         for (size_t i = 0; i < dim; i++)
781         {
782             Expression *ex = (*e->elements)[i];
783             if (ex)
784                 ex->accept(this);
785             else
786                 buf->writeByte('v');        // 'v' for void
787         }
788     }
789 
790     ////////////////////////////////////////////////////////////////////////////
791 
paramsToDecoBuffer(Parameters * parameters)792     void paramsToDecoBuffer(Parameters *parameters)
793     {
794         //printf("Parameter::paramsToDecoBuffer()\n");
795         Parameter_foreach(parameters, &paramsToDecoBufferDg, (void *)this);
796     }
797 
paramsToDecoBufferDg(void * ctx,size_t,Parameter * p)798     static int paramsToDecoBufferDg(void *ctx, size_t, Parameter *p)
799     {
800         p->accept((Visitor *)ctx);
801         return 0;
802     }
803 
visit(Parameter * p)804     void visit(Parameter *p)
805     {
806         if (p->storageClass & STCscope && !(p->storageClass & STCscopeinferred))
807             buf->writeByte('M');
808         // 'return inout ref' is the same as 'inout ref'
809         if ((p->storageClass & (STCreturn | STCwild)) == STCreturn)
810             buf->writestring("Nk");
811         switch (p->storageClass & (STCin | STCout | STCref | STClazy))
812         {
813             case 0:
814             case STCin:
815                 break;
816             case STCout:
817                 buf->writeByte('J');
818                 break;
819             case STCref:
820                 buf->writeByte('K');
821                 break;
822             case STClazy:
823                 buf->writeByte('L');
824                 break;
825             default:
826                 assert(0);
827         }
828         visitWithMask(p->type, 0);
829     }
830 };
831 
832 /******************************************************************************
833  * Returns exact mangled name of function.
834  */
mangleExact(FuncDeclaration * fd)835 const char *mangleExact(FuncDeclaration *fd)
836 {
837     if (!fd->mangleString)
838     {
839         OutBuffer buf;
840         Mangler v(&buf);
841         v.mangleExact(fd);
842         fd->mangleString = buf.extractString();
843     }
844     return fd->mangleString;
845 }
846 
mangleToBuffer(Type * t,OutBuffer * buf)847 void mangleToBuffer(Type *t, OutBuffer *buf)
848 {
849     Mangler v(buf);
850     v.visitWithMask(t, 0);
851 }
852 
mangleToBuffer(Expression * e,OutBuffer * buf)853 void mangleToBuffer(Expression *e, OutBuffer *buf)
854 {
855     Mangler v(buf);
856     e->accept(&v);
857 }
858 
mangleToBuffer(Dsymbol * s,OutBuffer * buf)859 void mangleToBuffer(Dsymbol *s, OutBuffer *buf)
860 {
861     Mangler v(buf);
862     s->accept(&v);
863 }
864