1 
2 /* Compiler implementation of the D programming language
3  * Copyright (C) 1999-2021 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 #include "root/aav.h"
14 
15 #include "mangle.h"
16 #include "init.h"
17 #include "declaration.h"
18 #include "aggregate.h"
19 #include "mtype.h"
20 #include "attrib.h"
21 #include "target.h"
22 #include "template.h"
23 #include "id.h"
24 #include "module.h"
25 #include "enum.h"
26 #include "expression.h"
27 #include "utf.h"
28 
29 typedef int (*ForeachDg)(void *ctx, size_t paramidx, Parameter *param);
30 int Parameter_foreach(Parameters *parameters, ForeachDg dg, void *ctx, size_t *pn = NULL);
31 
32 static const char *mangleChar[TMAX];
33 
initTypeMangle()34 void initTypeMangle()
35 {
36     mangleChar[Tarray] = "A";
37     mangleChar[Tsarray] = "G";
38     mangleChar[Taarray] = "H";
39     mangleChar[Tpointer] = "P";
40     mangleChar[Treference] = "R";
41     mangleChar[Tfunction] = "F";
42     mangleChar[Tident] = "I";
43     mangleChar[Tclass] = "C";
44     mangleChar[Tstruct] = "S";
45     mangleChar[Tenum] = "E";
46     mangleChar[Tdelegate] = "D";
47 
48     mangleChar[Tnone] = "n";
49     mangleChar[Tvoid] = "v";
50     mangleChar[Tint8] = "g";
51     mangleChar[Tuns8] = "h";
52     mangleChar[Tint16] = "s";
53     mangleChar[Tuns16] = "t";
54     mangleChar[Tint32] = "i";
55     mangleChar[Tuns32] = "k";
56     mangleChar[Tint64] = "l";
57     mangleChar[Tuns64] = "m";
58     mangleChar[Tint128] = "zi";
59     mangleChar[Tuns128] = "zk";
60     mangleChar[Tfloat32] = "f";
61     mangleChar[Tfloat64] = "d";
62     mangleChar[Tfloat80] = "e";
63 
64     mangleChar[Timaginary32] = "o";
65     mangleChar[Timaginary64] = "p";
66     mangleChar[Timaginary80] = "j";
67     mangleChar[Tcomplex32] = "q";
68     mangleChar[Tcomplex64] = "r";
69     mangleChar[Tcomplex80] = "c";
70 
71     mangleChar[Tbool] = "b";
72     mangleChar[Tchar] = "a";
73     mangleChar[Twchar] = "u";
74     mangleChar[Tdchar] = "w";
75 
76     // '@' shouldn't appear anywhere in the deco'd names
77     mangleChar[Tinstance] = "@";
78     mangleChar[Terror] = "@";
79     mangleChar[Ttypeof] = "@";
80     mangleChar[Ttuple] = "B";
81     mangleChar[Tslice] = "@";
82     mangleChar[Treturn] = "@";
83     mangleChar[Tvector] = "@";
84     mangleChar[Ttraits] = "@";
85     mangleChar[Tmixin] = "@";
86     mangleChar[Tnoreturn] = "@";    // becomes 'Nn'
87 
88     mangleChar[Tnull] = "n";    // same as TypeNone
89 
90     for (size_t i = 0; i < TMAX; i++)
91     {
92         if (!mangleChar[i])
93             fprintf(stderr, "ty = %llu\n", (ulonglong)i);
94         assert(mangleChar[i]);
95     }
96 }
97 
98 /*********************************
99  * Mangling for mod.
100  */
MODtoDecoBuffer(OutBuffer * buf,MOD mod)101 void MODtoDecoBuffer(OutBuffer *buf, MOD mod)
102 {
103     switch (mod)
104     {
105         case 0:
106             break;
107         case MODconst:
108             buf->writeByte('x');
109             break;
110         case MODimmutable:
111             buf->writeByte('y');
112             break;
113         case MODshared:
114             buf->writeByte('O');
115             break;
116         case MODshared | MODconst:
117             buf->writestring("Ox");
118             break;
119         case MODwild:
120             buf->writestring("Ng");
121             break;
122         case MODwildconst:
123             buf->writestring("Ngx");
124             break;
125         case MODshared | MODwild:
126             buf->writestring("ONg");
127             break;
128         case MODshared | MODwildconst:
129             buf->writestring("ONgx");
130             break;
131         default:
132             assert(0);
133     }
134 }
135 
136 class Mangler : public Visitor
137 {
138 public:
139     AA *types;
140     AA *idents;
141     OutBuffer *buf;
142 
Mangler(OutBuffer * buf)143     Mangler(OutBuffer *buf)
144     {
145         this->types = NULL;
146         this->idents = NULL;
147         this->buf = buf;
148     }
149 
150     /**
151     * writes a back reference with the relative position encoded with base 26
152     *  using upper case letters for all digits but the last digit which uses
153     *  a lower case letter.
154     * The decoder has to look up the referenced position to determine
155     *  whether the back reference is an identifier (starts with a digit)
156     *  or a type (starts with a letter).
157     *
158     * Params:
159     *  pos           = relative position to encode
160     */
writeBackRef(size_t pos)161     void writeBackRef(size_t pos)
162     {
163         buf->writeByte('Q');
164         const size_t base = 26;
165         size_t mul = 1;
166         while (pos >= mul * base)
167             mul *= base;
168         while (mul >= base)
169         {
170             unsigned char dig = (unsigned char)(pos / mul);
171             buf->writeByte('A' + dig);
172             pos -= dig * mul;
173             mul /= base;
174         }
175         buf->writeByte('a' + (unsigned char)pos);
176     }
177 
178     /**
179     * Back references a non-basic type
180     *
181     * The encoded mangling is
182     *       'Q' <relative position of first occurrence of type>
183     *
184     * Params:
185     *  t = the type to encode via back referencing
186     *
187     * Returns:
188     *  true if the type was found. A back reference has been encoded.
189     *  false if the type was not found. The current position is saved for later back references.
190     */
backrefType(Type * t)191     bool backrefType(Type *t)
192     {
193         if (!t->isTypeBasic())
194         {
195             size_t *p = (size_t *)dmd_aaGet(&types, (void *)t);
196             if (*p)
197             {
198                 writeBackRef(buf->length() - *p);
199                 return true;
200             }
201             *p = buf->length();
202         }
203         return false;
204     }
205 
206     /**
207     * Back references a single identifier
208     *
209     * The encoded mangling is
210     *       'Q' <relative position of first occurrence of type>
211     *
212     * Params:
213     *  id = the identifier to encode via back referencing
214     *
215     * Returns:
216     *  true if the identifier was found. A back reference has been encoded.
217     *  false if the identifier was not found. The current position is saved for later back references.
218     */
backrefIdentifier(Identifier * id)219     bool backrefIdentifier(Identifier *id)
220     {
221         size_t *p = (size_t *)dmd_aaGet(&idents, (void *)id);
222         if (*p)
223         {
224             writeBackRef(buf->length() - *p);
225             return true;
226         }
227         *p = buf->length();
228         return false;
229     }
230 
mangleSymbol(Dsymbol * s)231     void mangleSymbol(Dsymbol *s)
232     {
233         s->accept(this);
234     }
235 
mangleType(Type * t)236     void mangleType(Type *t)
237     {
238         if (!backrefType(t))
239             t->accept(this);
240     }
241 
mangleIdentifier(Identifier * id,Dsymbol * s)242     void mangleIdentifier(Identifier *id, Dsymbol *s)
243     {
244         if (!backrefIdentifier(id))
245             toBuffer(id->toChars(), s);
246     }
247 
248     ////////////////////////////////////////////////////////////////////////////
249 
250     /**************************************************
251      * Type mangling
252      */
253 
visitWithMask(Type * t,unsigned char modMask)254     void visitWithMask(Type *t, unsigned char modMask)
255     {
256         if (modMask != t->mod)
257         {
258             MODtoDecoBuffer(buf, t->mod);
259         }
260         mangleType(t);
261     }
262 
visit(Type * t)263     void visit(Type *t)
264     {
265         buf->writestring(mangleChar[t->ty]);
266     }
267 
visit(TypeNext * t)268     void visit(TypeNext *t)
269     {
270         visit((Type *)t);
271         visitWithMask(t->next, t->mod);
272     }
273 
visit(TypeVector * t)274     void visit(TypeVector *t)
275     {
276         buf->writestring("Nh");
277         visitWithMask(t->basetype, t->mod);
278     }
279 
visit(TypeSArray * t)280     void visit(TypeSArray *t)
281     {
282         visit((Type *)t);
283         if (t->dim)
284             buf->print(t->dim->toInteger());
285         if (t->next)
286             visitWithMask(t->next, t->mod);
287     }
288 
visit(TypeDArray * t)289     void visit(TypeDArray *t)
290     {
291         visit((Type *)t);
292         if (t->next)
293             visitWithMask(t->next, t->mod);
294     }
295 
visit(TypeAArray * t)296     void visit(TypeAArray *t)
297     {
298         visit((Type *)t);
299         visitWithMask(t->index, 0);
300         visitWithMask(t->next, t->mod);
301     }
302 
visit(TypeFunction * t)303     void visit(TypeFunction *t)
304     {
305         //printf("TypeFunction::toDecoBuffer() t = %p %s\n", t, t->toChars());
306         //static int nest; if (++nest == 50) *(char*)0=0;
307 
308         mangleFuncType(t, t, t->mod, t->next);
309     }
310 
mangleFuncType(TypeFunction * t,TypeFunction * ta,unsigned char modMask,Type * tret)311     void mangleFuncType(TypeFunction *t, TypeFunction *ta, unsigned char modMask, Type *tret)
312     {
313         //printf("mangleFuncType() %s\n", t->toChars());
314         if (t->inuse && tret)
315         {
316             // printf("TypeFunction.mangleFuncType() t = %s inuse\n", t->toChars());
317             t->inuse = 2;       // flag error to caller
318             return;
319         }
320         t->inuse++;
321 
322         if (modMask != t->mod)
323             MODtoDecoBuffer(buf, t->mod);
324 
325         unsigned char mc;
326         switch (t->linkage)
327         {
328             case LINKd:             mc = 'F';       break;
329             case LINKc:             mc = 'U';       break;
330             case LINKwindows:       mc = 'W';       break;
331             case LINKcpp:           mc = 'R';       break;
332             case LINKobjc:          mc = 'Y';       break;
333             default:
334                 assert(0);
335         }
336         buf->writeByte(mc);
337 
338         if (ta->purity || ta->isnothrow || ta->isnogc || ta->isproperty || ta->isref || ta->trust || ta->isreturn || ta->isscope)
339         {
340             if (ta->purity)
341                 buf->writestring("Na");
342             if (ta->isnothrow)
343                 buf->writestring("Nb");
344             if (ta->isref)
345                 buf->writestring("Nc");
346             if (ta->isproperty)
347                 buf->writestring("Nd");
348             if (ta->isnogc)
349                 buf->writestring("Ni");
350             if (ta->isreturn)
351                 buf->writestring("Nj");
352             if (ta->isscope && !ta->isreturn && !ta->isscopeinferred)
353                 buf->writestring("Nl");
354             switch (ta->trust)
355             {
356                 case TRUSTtrusted:
357                     buf->writestring("Ne");
358                     break;
359                 case TRUSTsafe:
360                     buf->writestring("Nf");
361                     break;
362                 default:
363                     break;
364             }
365         }
366 
367         // Write argument types
368         paramsToDecoBuffer(t->parameterList.parameters);
369         //if (buf->slice().ptr[buf->length() - 1] == '@') halt();
370         buf->writeByte('Z' - t->parameterList.varargs);   // mark end of arg list
371         if (tret != NULL)
372             visitWithMask(tret, 0);
373 
374         t->inuse--;
375     }
376 
visit(TypeIdentifier * t)377     void visit(TypeIdentifier *t)
378     {
379         visit((Type *)t);
380         const char *name = t->ident->toChars();
381         size_t len = strlen(name);
382         buf->print(len);
383         buf->writestring(name);
384     }
385 
visit(TypeEnum * t)386     void visit(TypeEnum *t)
387     {
388         visit((Type *)t);
389         mangleSymbol(t->sym);
390     }
391 
visit(TypeStruct * t)392     void visit(TypeStruct *t)
393     {
394         //printf("TypeStruct::toDecoBuffer('%s') = '%s'\n", t->toChars(), name);
395         visit((Type *)t);
396         mangleSymbol(t->sym);
397     }
398 
visit(TypeClass * t)399     void visit(TypeClass *t)
400     {
401         //printf("TypeClass::toDecoBuffer('%s' mod=%x) = '%s'\n", t->toChars(), mod, name);
402         visit((Type *)t);
403         mangleSymbol(t->sym);
404     }
405 
visit(TypeTuple * t)406     void visit(TypeTuple *t)
407     {
408         //printf("TypeTuple::toDecoBuffer() t = %p, %s\n", t, t->toChars());
409         visit((Type *)t);
410         paramsToDecoBuffer(t->arguments);
411         buf->writeByte('Z');
412     }
413 
visit(TypeNull * t)414     void visit(TypeNull *t)
415     {
416         visit((Type *)t);
417     }
418 
visit(TypeNoreturn *)419     void visit(TypeNoreturn *)
420     {
421         buf->writestring("Nn");
422     }
423 
424     ////////////////////////////////////////////////////////////////////////////
425 
mangleDecl(Declaration * sthis)426     void mangleDecl(Declaration *sthis)
427     {
428         mangleParent(sthis);
429 
430         assert(sthis->ident);
431         mangleIdentifier(sthis->ident, sthis);
432         if (FuncDeclaration *fd = sthis->isFuncDeclaration())
433         {
434             mangleFunc(fd, false);
435         }
436         else if (sthis->type)
437         {
438             visitWithMask(sthis->type, 0);
439         }
440         else
441             assert(0);
442     }
443 
mangleParent(Dsymbol * s)444     void mangleParent(Dsymbol *s)
445     {
446         Dsymbol *p;
447         if (TemplateInstance *ti = s->isTemplateInstance())
448             p = ti->isTemplateMixin() ? ti->parent : ti->tempdecl->parent;
449         else
450             p = s->parent;
451 
452         if (p)
453         {
454             mangleParent(p);
455             TemplateInstance *ti = p->isTemplateInstance();
456             if (ti && !ti->isTemplateMixin())
457             {
458                 mangleTemplateInstance(ti);
459             }
460             else if (p->getIdent())
461             {
462                 mangleIdentifier(p->ident, s);
463                 if (FuncDeclaration *f = p->isFuncDeclaration())
464                     mangleFunc(f, true);
465             }
466             else
467                 buf->writeByte('0');
468         }
469     }
470 
mangleFunc(FuncDeclaration * fd,bool inParent)471     void mangleFunc(FuncDeclaration *fd, bool inParent)
472     {
473         //printf("deco = '%s'\n", fd->type->deco ? fd->type->deco : "null");
474         //printf("fd->type = %s\n", fd->type->toChars());
475         if (fd->needThis() || fd->isNested())
476             buf->writeByte('M');
477         if (inParent)
478         {
479             TypeFunction *tf = (TypeFunction *)fd->type;
480             TypeFunction *tfo = (TypeFunction *)fd->originalType;
481             mangleFuncType(tf, tfo, 0, NULL);
482         }
483         else if (fd->type)
484         {
485             visitWithMask(fd->type, 0);
486         }
487         else
488         {
489             printf("[%s] %s no type\n", fd->loc.toChars(), fd->toChars());
490             assert(0);  // don't mangle function until semantic3 done.
491         }
492     }
493 
494     /************************************************************
495      * Write length prefixed string to buf.
496      */
toBuffer(const char * id,Dsymbol * s)497     void toBuffer(const char *id, Dsymbol *s)
498     {
499         size_t len = strlen(id);
500         if (buf->length() + len >= 8 * 1024 * 1024) // 8 megs ought be enough for anyone
501             s->error("excessive length %llu for symbol, possible recursive expansion?", buf->length() + len);
502         else
503         {
504             buf->print(len);
505             buf->write(id, len);
506         }
507     }
508 
externallyMangledIdentifier(Declaration * d)509     static const char *externallyMangledIdentifier(Declaration *d)
510     {
511         if (!d->parent || d->parent->isModule() || d->linkage == LINKcpp) // if at global scope
512         {
513             switch (d->linkage)
514             {
515                 case LINKd:
516                     break;
517                 case LINKc:
518                 case LINKwindows:
519                 case LINKobjc:
520                     return d->ident->toChars();
521                 case LINKcpp:
522                     return target.cpp.toMangle(d);
523                 case LINKdefault:
524                     d->error("forward declaration");
525                     return d->ident->toChars();
526                 default:
527                     fprintf(stderr, "'%s', linkage = %d\n", d->toChars(), d->linkage);
528                     assert(0);
529             }
530         }
531         return NULL;
532     }
533 
visit(Declaration * d)534     void visit(Declaration *d)
535     {
536         //printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n",
537         //        d, d->toChars(), d->parent ? d->parent->toChars() : "null", d->linkage);
538         if (const char *id = externallyMangledIdentifier(d))
539         {
540             buf->writestring(id);
541             return;
542         }
543         buf->writestring("_D");
544         mangleDecl(d);
545     }
546 
547     /******************************************************************************
548      * Normally FuncDeclaration and FuncAliasDeclaration have overloads.
549      * If and only if there is no overloads, mangle() could return
550      * exact mangled name.
551      *
552      *      module test;
553      *      void foo(long) {}           // _D4test3fooFlZv
554      *      void foo(string) {}         // _D4test3fooFAyaZv
555      *
556      *      // from FuncDeclaration::mangle().
557      *      pragma(msg, foo.mangleof);  // prints unexact mangled name "4test3foo"
558      *                                  // by calling Dsymbol::mangle()
559      *
560      *      // from FuncAliasDeclaration::mangle()
561      *      pragma(msg, __traits(getOverloads, test, "foo")[0].mangleof);  // "_D4test3fooFlZv"
562      *      pragma(msg, __traits(getOverloads, test, "foo")[1].mangleof);  // "_D4test3fooFAyaZv"
563      *
564      * If a function has no overloads, .mangleof property still returns exact mangled name.
565      *
566      *      void bar() {}
567      *      pragma(msg, bar.mangleof);  // still prints "_D4test3barFZv"
568      *                                  // by calling FuncDeclaration::mangleExact().
569      */
visit(FuncDeclaration * fd)570     void visit(FuncDeclaration *fd)
571     {
572         if (fd->isUnique())
573             mangleExact(fd);
574         else
575             visit((Dsymbol *)fd);
576     }
577 
578     // ditto
visit(FuncAliasDeclaration * fd)579     void visit(FuncAliasDeclaration *fd)
580     {
581         FuncDeclaration *f = fd->toAliasFunc();
582         FuncAliasDeclaration *fa = f->isFuncAliasDeclaration();
583         if (!fd->hasOverloads && !fa)
584         {
585             mangleExact(f);
586             return;
587         }
588         if (fa)
589         {
590             mangleSymbol(fa);
591             return;
592         }
593         visit((Dsymbol *)fd);
594     }
595 
visit(OverDeclaration * od)596     void visit(OverDeclaration *od)
597     {
598         if (od->overnext)
599         {
600             visit((Dsymbol *)od);
601             return;
602         }
603 
604         if (FuncDeclaration *fd = od->aliassym->isFuncDeclaration())
605         {
606             if (!od->hasOverloads || fd->isUnique())
607             {
608                 mangleExact(fd);
609                 return;
610             }
611         }
612         if (TemplateDeclaration *td = od->aliassym->isTemplateDeclaration())
613         {
614             if (!od->hasOverloads || td->overnext == NULL)
615             {
616                 mangleSymbol(td);
617                 return;
618             }
619         }
620         visit((Dsymbol *)od);
621     }
622 
mangleExact(FuncDeclaration * fd)623     void mangleExact(FuncDeclaration *fd)
624     {
625         assert(!fd->isFuncAliasDeclaration());
626 
627         if (fd->mangleOverride.length)
628         {
629             buf->writestring(fd->mangleOverride.ptr);
630             return;
631         }
632 
633         if (fd->isMain())
634         {
635             buf->writestring("_Dmain");
636             return;
637         }
638 
639         if (fd->isWinMain() || fd->isDllMain() || fd->ident == Id::tls_get_addr)
640         {
641             buf->writestring(fd->ident->toChars());
642             return;
643         }
644 
645         visit((Declaration *)fd);
646     }
647 
visit(VarDeclaration * vd)648     void visit(VarDeclaration *vd)
649     {
650         if (vd->mangleOverride.length)
651         {
652             buf->writestring(vd->mangleOverride.ptr);
653             return;
654         }
655 
656         visit((Declaration *)vd);
657     }
658 
visit(AggregateDeclaration * ad)659     void visit(AggregateDeclaration *ad)
660     {
661         ClassDeclaration *cd = ad->isClassDeclaration();
662         Dsymbol *parentsave = ad->parent;
663         if (cd)
664         {
665             /* These are reserved to the compiler, so keep simple
666              * names for them.
667              */
668             if ((cd->ident == Id::Exception && cd->parent->ident == Id::object) ||
669                 cd->ident == Id::TypeInfo ||
670                 cd->ident == Id::TypeInfo_Struct ||
671                 cd->ident == Id::TypeInfo_Class ||
672                 cd->ident == Id::TypeInfo_Tuple ||
673                 cd == ClassDeclaration::object ||
674                 cd == Type::typeinfoclass ||
675                 cd == Module::moduleinfo ||
676                 strncmp(cd->ident->toChars(), "TypeInfo_", 9) == 0)
677             {
678                 // Don't mangle parent
679                 ad->parent = NULL;
680             }
681         }
682 
683         visit((Dsymbol *)ad);
684 
685         ad->parent = parentsave;
686     }
687 
visit(TemplateInstance * ti)688     void visit(TemplateInstance *ti)
689     {
690         if (!ti->tempdecl)
691             ti->error("is not defined");
692         else
693             mangleParent(ti);
694 
695         if (ti->isTemplateMixin() && ti->ident)
696             mangleIdentifier(ti->ident, ti);
697         else
698             mangleTemplateInstance(ti);
699     }
700 
mangleTemplateInstance(TemplateInstance * ti)701     void mangleTemplateInstance(TemplateInstance *ti)
702     {
703         TemplateDeclaration *tempdecl = ti->tempdecl->isTemplateDeclaration();
704         assert(tempdecl);
705 
706         // Use "__U" for the symbols declared inside template constraint.
707         const char T = ti->members ? 'T' : 'U';
708         buf->printf("__%c", T);
709         mangleIdentifier(tempdecl->ident, tempdecl);
710 
711         Objects *args = ti->tiargs;
712         size_t nparams = tempdecl->parameters->length - (tempdecl->isVariadic() ? 1 : 0);
713         for (size_t i = 0; i < args->length; i++)
714         {
715             RootObject *o = (*args)[i];
716             Type *ta = isType(o);
717             Expression *ea = isExpression(o);
718             Dsymbol *sa = isDsymbol(o);
719             Tuple *va = isTuple(o);
720             //printf("\to [%d] %p ta %p ea %p sa %p va %p\n", i, o, ta, ea, sa, va);
721             if (i < nparams && (*tempdecl->parameters)[i]->specialization())
722                 buf->writeByte('H'); // https://issues.dlang.org/show_bug.cgi?id=6574
723             if (ta)
724             {
725                 buf->writeByte('T');
726                 visitWithMask(ta, 0);
727             }
728             else if (ea)
729             {
730                 // Don't interpret it yet, it might actually be an alias template parameter.
731                 // Only constfold manifest constants, not const/immutable lvalues, see https://issues.dlang.org/show_bug.cgi?id=17339.
732                 const bool keepLvalue = true;
733                 ea = ea->optimize(WANTvalue, keepLvalue);
734                 if (ea->op == TOKvar)
735                 {
736                     sa = ((VarExp *)ea)->var;
737                     ea = NULL;
738                     goto Lsa;
739                 }
740                 if (ea->op == TOKthis)
741                 {
742                     sa = ((ThisExp *)ea)->var;
743                     ea = NULL;
744                     goto Lsa;
745                 }
746                 if (ea->op == TOKfunction)
747                 {
748                     if (((FuncExp *)ea)->td)
749                         sa = ((FuncExp *)ea)->td;
750                     else
751                         sa = ((FuncExp *)ea)->fd;
752                     ea = NULL;
753                     goto Lsa;
754                 }
755                 buf->writeByte('V');
756                 if (ea->op == TOKtuple)
757                 {
758                     ea->error("tuple is not a valid template value argument");
759                     continue;
760                 }
761                 // Now that we know it is not an alias, we MUST obtain a value
762                 unsigned olderr = global.errors;
763                 ea = ea->ctfeInterpret();
764                 if (ea->op == TOKerror || olderr != global.errors)
765                     continue;
766 
767                 /* Use type mangling that matches what it would be for a function parameter
768                 */
769                 visitWithMask(ea->type, 0);
770                 ea->accept(this);
771             }
772             else if (sa)
773             {
774             Lsa:
775                 sa = sa->toAlias();
776                 if (Declaration *d = sa->isDeclaration())
777                 {
778                     if (FuncAliasDeclaration *fad = d->isFuncAliasDeclaration())
779                         d = fad->toAliasFunc();
780                     if (d->mangleOverride.length)
781                     {
782                         buf->writeByte('X');
783                         toBuffer(d->mangleOverride.ptr, d);
784                         continue;
785                     }
786                     if (const char *id = externallyMangledIdentifier(d))
787                     {
788                         buf->writeByte('X');
789                         toBuffer(id, d);
790                         continue;
791                     }
792                     if (!d->type || !d->type->deco)
793                     {
794                         ti->error("forward reference of %s %s", d->kind(), d->toChars());
795                         continue;
796                     }
797                 }
798                 buf->writeByte('S');
799                 mangleSymbol(sa);
800             }
801             else if (va)
802             {
803                 assert(i + 1 == args->length); // must be last one
804                 args = &va->objects;
805                 i = -(size_t)1;
806             }
807             else
808                 assert(0);
809         }
810         buf->writeByte('Z');
811     }
812 
visit(Dsymbol * s)813     void visit(Dsymbol *s)
814     {
815         mangleParent(s);
816         if (s->ident)
817             mangleIdentifier(s->ident, s);
818         else
819             toBuffer(s->toChars(), s);
820         //printf("Dsymbol::mangle() %s = %s\n", s->toChars(), id);
821     }
822 
823     ////////////////////////////////////////////////////////////////////////////
824 
visit(Expression * e)825     void visit(Expression *e)
826     {
827         e->error("expression %s is not a valid template value argument", e->toChars());
828     }
829 
visit(IntegerExp * e)830     void visit(IntegerExp *e)
831     {
832         if ((sinteger_t)e->value < 0)
833         {
834             buf->writeByte('N');
835             buf->print(-e->value);
836         }
837         else
838         {
839             buf->writeByte('i');
840             buf->print(e->value);
841         }
842     }
843 
visit(RealExp * e)844     void visit(RealExp *e)
845     {
846         buf->writeByte('e');
847         realToMangleBuffer(e->value);
848     }
849 
realToMangleBuffer(real_t value)850     void realToMangleBuffer(real_t value)
851     {
852         /* Rely on %A to get portable mangling.
853          * Must munge result to get only identifier characters.
854          *
855          * Possible values from %A  => mangled result
856          * NAN                      => NAN
857          * -INF                     => NINF
858          * INF                      => INF
859          * -0X1.1BC18BA997B95P+79   => N11BC18BA997B95P79
860          * 0X1.9P+2                 => 19P2
861          */
862 
863         if (CTFloat::isNaN(value))
864             buf->writestring("NAN");        // no -NAN bugs
865         else if (CTFloat::isInfinity(value))
866             buf->writestring(value < CTFloat::zero ? "NINF" : "INF");
867         else
868         {
869             const size_t BUFFER_LEN = 36;
870             char buffer[BUFFER_LEN];
871             size_t n = CTFloat::sprint(buffer, 'A', value);
872             assert(n < BUFFER_LEN);
873             for (size_t i = 0; i < n; i++)
874             {
875                 char c = buffer[i];
876                 switch (c)
877                 {
878                     case '-':
879                         buf->writeByte('N');
880                         break;
881 
882                     case '+':
883                     case 'X':
884                     case '.':
885                         break;
886 
887                     case '0':
888                         if (i < 2)
889                             break;          // skip leading 0X
890                         /* fall through */
891                     default:
892                         buf->writeByte(c);
893                         break;
894                 }
895             }
896         }
897     }
898 
visit(ComplexExp * e)899     void visit(ComplexExp *e)
900     {
901         buf->writeByte('c');
902         realToMangleBuffer(e->toReal());
903         buf->writeByte('c');        // separate the two
904         realToMangleBuffer(e->toImaginary());
905     }
906 
visit(NullExp *)907     void visit(NullExp *)
908     {
909         buf->writeByte('n');
910     }
911 
visit(StringExp * e)912     void visit(StringExp *e)
913     {
914         char m;
915         OutBuffer tmp;
916         utf8_t *q;
917         size_t qlen;
918 
919         /* Write string in UTF-8 format
920          */
921         switch (e->sz)
922         {
923             case 1:
924                 m = 'a';
925                 q = (utf8_t *)e->string;
926                 qlen = e->len;
927                 break;
928 
929             case 2:
930                 m = 'w';
931                 for (size_t u = 0; u < e->len; )
932                 {
933                     unsigned c;
934                     const char *p = utf_decodeWchar((unsigned short *)e->string, e->len, &u, &c);
935                     if (p)
936                         e->error("%s", p);
937                     else
938                         tmp.writeUTF8(c);
939                 }
940                 q = (utf8_t *)tmp.slice().ptr;
941                 qlen = tmp.length();
942                 break;
943 
944             case 4:
945                 m = 'd';
946                 for (size_t u = 0; u < e->len; u++)
947                 {
948                     unsigned c = ((unsigned *)e->string)[u];
949                     if (!utf_isValidDchar(c))
950                         e->error("invalid UCS-32 char \\U%08x", c);
951                     else
952                         tmp.writeUTF8(c);
953                 }
954                 q = (utf8_t *)tmp.slice().ptr;
955                 qlen = tmp.length();
956                 break;
957 
958             default:
959                 assert(0);
960         }
961         buf->reserve(1 + 11 + 2 * qlen);
962         buf->writeByte(m);
963         buf->print(qlen);
964         buf->writeByte('_');    // nbytes <= 11
965 
966         for (utf8_t *p = (utf8_t *)buf->slice().ptr + buf->length(), *pend = p + 2 * qlen;
967              p < pend; p += 2, ++q)
968         {
969             utf8_t hi = *q >> 4 & 0xF;
970             p[0] = (utf8_t)(hi < 10 ? hi + '0' : hi - 10 + 'a');
971             utf8_t lo = *q & 0xF;
972             p[1] = (utf8_t)(lo < 10 ? lo + '0' : lo - 10 + 'a');
973         }
974         buf->setsize(buf->length() + 2 * qlen);
975     }
976 
visit(ArrayLiteralExp * e)977     void visit(ArrayLiteralExp *e)
978     {
979         size_t dim = e->elements ? e->elements->length : 0;
980         buf->writeByte('A');
981         buf->print(dim);
982         for (size_t i = 0; i < dim; i++)
983         {
984             e->getElement(i)->accept(this);
985         }
986     }
987 
visit(AssocArrayLiteralExp * e)988     void visit(AssocArrayLiteralExp *e)
989     {
990         size_t dim = e->keys->length;
991         buf->writeByte('A');
992         buf->print(dim);
993         for (size_t i = 0; i < dim; i++)
994         {
995             (*e->keys)[i]->accept(this);
996             (*e->values)[i]->accept(this);
997         }
998     }
999 
visit(StructLiteralExp * e)1000     void visit(StructLiteralExp *e)
1001     {
1002         size_t dim = e->elements ? e->elements->length : 0;
1003         buf->writeByte('S');
1004         buf->print(dim);
1005         for (size_t i = 0; i < dim; i++)
1006         {
1007             Expression *ex = (*e->elements)[i];
1008             if (ex)
1009                 ex->accept(this);
1010             else
1011                 buf->writeByte('v');        // 'v' for void
1012         }
1013     }
1014 
1015     ////////////////////////////////////////////////////////////////////////////
1016 
paramsToDecoBuffer(Parameters * parameters)1017     void paramsToDecoBuffer(Parameters *parameters)
1018     {
1019         //printf("Parameter::paramsToDecoBuffer()\n");
1020         Parameter_foreach(parameters, &paramsToDecoBufferDg, (void *)this);
1021     }
1022 
paramsToDecoBufferDg(void * ctx,size_t,Parameter * p)1023     static int paramsToDecoBufferDg(void *ctx, size_t, Parameter *p)
1024     {
1025         p->accept((Visitor *)ctx);
1026         return 0;
1027     }
1028 
visit(Parameter * p)1029     void visit(Parameter *p)
1030     {
1031         if (p->storageClass & STCscope && !(p->storageClass & STCscopeinferred))
1032             buf->writeByte('M');
1033         // 'return inout ref' is the same as 'inout ref'
1034         if ((p->storageClass & (STCreturn | STCwild)) == STCreturn)
1035             buf->writestring("Nk");
1036         switch (p->storageClass & (STCin | STCout | STCref | STClazy))
1037         {
1038             case 0:
1039             case STCin:
1040                 break;
1041             case STCout:
1042                 buf->writeByte('J');
1043                 break;
1044             case STCref:
1045                 buf->writeByte('K');
1046                 break;
1047             case STClazy:
1048                 buf->writeByte('L');
1049                 break;
1050             default:
1051                 assert(0);
1052         }
1053         visitWithMask(p->type, 0);
1054     }
1055 };
1056 
1057 /******************************************************************************
1058  * Returns exact mangled name of function.
1059  */
mangleExact(FuncDeclaration * fd)1060 const char *mangleExact(FuncDeclaration *fd)
1061 {
1062     if (!fd->mangleString)
1063     {
1064         OutBuffer buf;
1065         Mangler v(&buf);
1066         v.mangleExact(fd);
1067         fd->mangleString = buf.extractChars();
1068     }
1069     return fd->mangleString;
1070 }
1071 
mangleToBuffer(Type * t,OutBuffer * buf)1072 void mangleToBuffer(Type *t, OutBuffer *buf)
1073 {
1074     Mangler v(buf);
1075     v.visitWithMask(t, 0);
1076 }
1077 
mangleToBuffer(Expression * e,OutBuffer * buf)1078 void mangleToBuffer(Expression *e, OutBuffer *buf)
1079 {
1080     Mangler v(buf);
1081     e->accept(&v);
1082 }
1083 
mangleToBuffer(Dsymbol * s,OutBuffer * buf)1084 void mangleToBuffer(Dsymbol *s, OutBuffer *buf)
1085 {
1086     Mangler v(buf);
1087     s->accept(&v);
1088 }
1089 
mangleToBuffer(TemplateInstance * ti,OutBuffer * buf)1090 void mangleToBuffer(TemplateInstance *ti, OutBuffer *buf)
1091 {
1092     Mangler v(buf);
1093     v.mangleTemplateInstance(ti);
1094 }
1095 
1096 /**********************************************
1097  * Convert a string representing a type (the deco) and
1098  * return its equivalent Type.
1099  * Params:
1100  *      deco = string containing the deco
1101  * Returns:
1102  *      null for failed to convert
1103  *      Type for succeeded
1104  */
1105 
decoToType(const char * deco)1106 Type *decoToType(const char *deco)
1107 {
1108     if (!deco)
1109         return NULL;
1110 
1111     //printf("decoToType(): %s\n", deco)
1112     if (StringValue *sv = Type::stringtable.lookup(deco, strlen(deco)))
1113     {
1114         if (sv->ptrvalue)
1115         {
1116             Type *t = (Type *)sv->ptrvalue;
1117             assert(t->deco);
1118             return t;
1119         }
1120     }
1121     return NULL;
1122 }
1123