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/cppmangle.c
9  */
10 
11 /**
12  * Do mangling for C++ linkage.
13  *
14  * References:
15  *  Follows Itanium C++ ABI 1.86 section 5.1
16  *  http://refspecs.linux-foundation.org/cxxabi-1.86.html#mangling
17  *  which is where the grammar comments come from.
18  *
19  * Bugs:
20  *  https://issues.dlang.org/query.cgi
21  *  enter `C++, mangling` as the keywords.
22  */
23 
24 #include "root/dsystem.h"
25 
26 #include "mars.h"
27 #include "dsymbol.h"
28 #include "mtype.h"
29 #include "scope.h"
30 #include "init.h"
31 #include "expression.h"
32 #include "attrib.h"
33 #include "declaration.h"
34 #include "template.h"
35 #include "id.h"
36 #include "enum.h"
37 #include "import.h"
38 #include "aggregate.h"
39 #include "target.h"
40 
41 typedef int (*ForeachDg)(void *ctx, size_t paramidx, Parameter *param);
42 int Parameter_foreach(Parameters *parameters, ForeachDg dg, void *ctx, size_t *pn = NULL);
43 
44 class CppMangleVisitor : public Visitor
45 {
46     Objects components;         // array of components available for substitution
47     OutBuffer *buf;             // append the mangling to buf[]
48   public:
49     Loc loc;                    // location for use in error messages
50 
51     // Write <seq-id> to buf
write_seq_id(size_t i)52     void write_seq_id(size_t i)
53     {
54         if (i >= 36)
55         {
56             write_seq_id(i / 36);
57             i %= 36;
58         }
59         i += (i < 10) ? '0' : 'A' - 10;
60         buf->writeByte((char)i);
61     }
62 
substitute(RootObject * p)63     bool substitute(RootObject *p)
64     {
65         //printf("substitute %s\n", p ? p->toChars() : NULL);
66         int i = find(p);
67         if (i >= 0)
68         {
69             //printf("\tmatch\n");
70             /* Sequence is S_, S0_, .., S9_, SA_, ..., SZ_, S10_, ...
71              */
72             buf->writeByte('S');
73             if (i)
74             {
75                 write_seq_id(i - 1);
76             }
77             buf->writeByte('_');
78             return true;
79         }
80         return false;
81     }
82 
83     /******
84      * See if `p` exists in components[]
85      * Returns:
86      *  index if found, -1 if not
87      */
find(RootObject * p)88     int find(RootObject *p)
89     {
90         //printf("find %p %d %s\n", p, p.dyncast(), p ? p.toChars() : NULL);
91         for (size_t i = 0; i < components.length; i++)
92         {
93             if (p == components[i])
94                 return (int)i;
95         }
96         return -1;
97     }
98 
99     /*********************
100      * Append p to components[]
101      */
append(RootObject * p)102     void append(RootObject *p)
103     {
104         //printf("append %p %d %s\n", p, p.dyncast(), p ? p.toChars() : "null");
105         components.push(p);
106     }
107 
108     /************************
109      * Determine if symbol is indeed the global ::std namespace.
110      * Params:
111      *  s = symbol to check
112      * Returns:
113      *  true if it is ::std
114      */
isStd(Dsymbol * s)115     static bool isStd(Dsymbol *s)
116     {
117         return (s &&
118                 s->ident == Id::std &&  // the right name
119                 s->isNspace() &&        // g++ disallows global "std" for other than a namespace
120                 !getQualifier(s));      // at global level
121     }
122 
123     /************************
124      * Determine if type is a C++ fundamental type.
125      * Params:
126      *  t = type to check
127      * Returns:
128      *  true if it is a fundamental type
129      */
isFundamentalType(Type * t)130     static bool isFundamentalType(Type *t)
131     {
132         // First check the target whether some specific ABI is being followed.
133         bool isFundamental;
134         if (target.cpp.fundamentalType(t, isFundamental))
135             return isFundamental;
136         if (t->ty == Tenum)
137         {
138             // Peel off enum type from special types.
139             TypeEnum *te = (TypeEnum *)t;
140             if (te->sym->isSpecial())
141                 t = te->sym->getMemtype(Loc());
142         }
143 
144         // Fundamental arithmetic types:
145         // 1. integral types: bool, char, int, ...
146         // 2. floating point types: float, double, real
147         // 3. void
148         // 4. null pointer: std::nullptr_t (since C++11)
149         if (t->ty == Tvoid || t->ty == Tbool)
150             return true;
151         else if (t->ty == Tnull && global.params.cplusplus >= CppStdRevisionCpp11)
152             return true;
153         else
154             return t->isTypeBasic() && (t->isintegral() || t->isreal());
155     }
156 
157     /******************************
158      * Write the mangled representation of the template arguments.
159      * Params:
160      *  ti = the template instance
161      */
template_args(TemplateInstance * ti)162     void template_args(TemplateInstance *ti)
163     {
164         /* <template-args> ::= I <template-arg>+ E
165          */
166         if (!ti)                // could happen if std::basic_string is not a template
167             return;
168         buf->writeByte('I');
169         for (size_t i = 0; i < ti->tiargs->length; i++)
170         {
171             RootObject *o = (*ti->tiargs)[i];
172             TemplateDeclaration *td = ti->tempdecl->isTemplateDeclaration();
173             assert(td);
174             TemplateParameter *tp = (*td->parameters)[i];
175 
176             /*
177              * <template-arg> ::= <type>               # type or template
178              *                ::= X <expression> E     # expression
179              *                ::= <expr-primary>       # simple expressions
180              *                ::= I <template-arg>* E  # argument pack
181              */
182             if (tp->isTemplateTupleParameter())
183             {
184                 buf->writeByte('I');     // argument pack
185 
186                 // mangle the rest of the arguments as types
187                 for (size_t j = i; j < ti->tiargs->length; j++)
188                 {
189                     Type *t = isType((*ti->tiargs)[j]);
190                     assert(t);
191                     t->accept(this);
192                 }
193 
194                 buf->writeByte('E');
195                 break;
196             }
197             if (tp->isTemplateTypeParameter())
198             {
199                 Type *t = isType(o);
200                 assert(t);
201                 t->accept(this);
202             }
203             else if (TemplateValueParameter *tv = tp->isTemplateValueParameter())
204             {
205                 // <expr-primary> ::= L <type> <value number> E  # integer literal
206                 if (tv->valType->isintegral())
207                 {
208                     Expression *e = isExpression(o);
209                     assert(e);
210                     buf->writeByte('L');
211                     tv->valType->accept(this);
212                     uinteger_t val = e->toUInteger();
213                     if (!tv->valType->isunsigned() && (sinteger_t)val < 0)
214                     {
215                         val = -val;
216                         buf->writeByte('n');
217                     }
218                     buf->printf("%llu", val);
219                     buf->writeByte('E');
220                 }
221                 else
222                 {
223                     ti->error("Internal Compiler Error: C++ `%s` template value parameter is not supported", tv->valType->toChars());
224                     fatal();
225                 }
226             }
227             else if (tp->isTemplateAliasParameter())
228             {
229                 Dsymbol *d = isDsymbol(o);
230                 Expression *e = isExpression(o);
231                 if (d && d->isFuncDeclaration())
232                 {
233                     bool is_nested = d->toParent3() &&
234                         !d->toParent3()->isModule() &&
235                         ((TypeFunction*)d->isFuncDeclaration()->type)->linkage == LINKcpp;
236                     if (is_nested)
237                         buf->writeByte('X');
238                     buf->writeByte('L');
239                     mangle_function(d->isFuncDeclaration());
240                     buf->writeByte('E');
241                     if (is_nested)
242                         buf->writeByte('E');
243                 }
244                 else if (e && e->op == TOKvar && ((VarExp*)e)->var->isVarDeclaration())
245                 {
246                     VarDeclaration *vd = ((VarExp*)e)->var->isVarDeclaration();
247                     buf->writeByte('L');
248                     mangle_variable(vd, true);
249                     buf->writeByte('E');
250                 }
251                 else if (d && d->isTemplateDeclaration() && d->isTemplateDeclaration()->onemember)
252                 {
253                     if (!substitute(d))
254                     {
255                         cpp_mangle_name(d, false);
256                     }
257                 }
258                 else
259                 {
260                     ti->error("Internal Compiler Error: `%s` is unsupported parameter for C++ template", o->toChars());
261                     fatal();
262                 }
263             }
264             else if (tp->isTemplateThisParameter())
265             {
266                 ti->error("Internal Compiler Error: C++ `%s` template this parameter is not supported", o->toChars());
267                 fatal();
268             }
269             else
270             {
271                 assert(0);
272             }
273         }
274         buf->writeByte('E');
275     }
276 
source_name(Dsymbol * s)277     void source_name(Dsymbol *s)
278     {
279         //printf("source_name(%s)\n", s->toChars());
280         if (TemplateInstance *ti = s->isTemplateInstance())
281         {
282             if (!substitute(ti->tempdecl))
283             {
284                 append(ti->tempdecl);
285                 const char *name = ti->tempdecl->toAlias()->ident->toChars();
286                 buf->printf("%d", strlen(name));
287                 buf->writestring(name);
288             }
289             template_args(ti);
290         }
291         else
292         {
293             const char *name = s->ident->toChars();
294             buf->printf("%d", strlen(name));
295             buf->writestring(name);
296         }
297     }
298 
299     /********
300      * See if s is actually an instance of a template
301      * Params:
302      *  s = symbol
303      * Returns:
304      *  if s is instance of a template, return the instance, otherwise return s
305      */
getInstance(Dsymbol * s)306     Dsymbol *getInstance(Dsymbol *s)
307     {
308         Dsymbol *p = s->toParent3();
309         if (p)
310         {
311             if (TemplateInstance *ti = p->isTemplateInstance())
312                 return ti;
313         }
314         return s;
315     }
316 
317     /********
318      * Get qualifier for `s`, meaning the symbol
319      * that s is in the symbol table of.
320      * The module does not count as a qualifier, because C++
321      * does not have modules.
322      * Params:
323      *  s = symbol that may have a qualifier
324      * Returns:
325      *  qualifier, NULL if none
326      */
getQualifier(Dsymbol * s)327     static Dsymbol *getQualifier(Dsymbol *s)
328     {
329         Dsymbol *p = s->toParent3();
330         return (p && !p->isModule()) ? p : NULL;
331     }
332 
333     // Detect type char
isChar(RootObject * o)334     static bool isChar(RootObject *o)
335     {
336         Type *t = isType(o);
337         return (t && t->equals(Type::tchar));
338     }
339 
340     // Detect type ::std::char_traits<char>
isChar_traits_char(RootObject * o)341     static bool isChar_traits_char(RootObject *o)
342     {
343         return isIdent_char(Id::char_traits, o);
344     }
345 
346     // Detect type ::std::allocator<char>
isAllocator_char(RootObject * o)347     static bool isAllocator_char(RootObject *o)
348     {
349         return isIdent_char(Id::allocator, o);
350     }
351 
352     // Detect type ::std::ident<char>
isIdent_char(Identifier * ident,RootObject * o)353     static bool isIdent_char(Identifier *ident, RootObject *o)
354     {
355         Type *t = isType(o);
356         if (!t || t->ty != Tstruct)
357             return false;
358         Dsymbol *s = ((TypeStruct*)t)->toDsymbol(NULL);
359         if (s->ident != ident)
360             return false;
361         Dsymbol *p = s->toParent3();
362         if (!p)
363             return false;
364         TemplateInstance *ti = p->isTemplateInstance();
365         if (!ti)
366             return false;
367         Dsymbol *q = getQualifier(ti);
368         return isStd(q) && ti->tiargs->length == 1 && isChar((*ti->tiargs)[0]);
369     }
370 
371     /***
372      * Detect template args <char, ::std::char_traits<char>>
373      * and write st if found.
374      * Returns:
375      *  true if found
376      */
char_std_char_traits_char(TemplateInstance * ti,const char * st)377     bool char_std_char_traits_char(TemplateInstance *ti, const char *st)
378     {
379         if (ti->tiargs->length == 2 &&
380             isChar((*ti->tiargs)[0]) &&
381             isChar_traits_char((*ti->tiargs)[1]))
382         {
383             buf->writestring(st);
384             return true;
385         }
386         return false;
387     }
388 
389 
prefix_name(Dsymbol * s)390     void prefix_name(Dsymbol *s)
391     {
392         //printf("prefix_name(%s)\n", s->toChars());
393         if (!substitute(s))
394         {
395             Dsymbol *si = getInstance(s);
396             Dsymbol *p = getQualifier(si);
397             if (p)
398             {
399                 if (isStd(p))
400                 {
401                     TemplateInstance *ti = si->isTemplateInstance();
402                     if (ti)
403                     {
404                         if (s->ident == Id::allocator)
405                         {
406                             buf->writestring("Sa");
407                             template_args(ti);
408                             append(ti);
409                             return;
410                         }
411                         if (s->ident == Id::basic_string)
412                         {
413                             // ::std::basic_string<char, ::std::char_traits<char>, ::std::allocator<char>>
414                             if (ti->tiargs->length == 3 &&
415                                 isChar((*ti->tiargs)[0]) &&
416                                 isChar_traits_char((*ti->tiargs)[1]) &&
417                                 isAllocator_char((*ti->tiargs)[2]))
418 
419                             {
420                                 buf->writestring("Ss");
421                                 return;
422                             }
423                             buf->writestring("Sb");      // ::std::basic_string
424                             template_args(ti);
425                             append(ti);
426                             return;
427                         }
428 
429                         // ::std::basic_istream<char, ::std::char_traits<char>>
430                         if (s->ident == Id::basic_istream &&
431                             char_std_char_traits_char(ti, "Si"))
432                             return;
433 
434                         // ::std::basic_ostream<char, ::std::char_traits<char>>
435                         if (s->ident == Id::basic_ostream &&
436                             char_std_char_traits_char(ti, "So"))
437                             return;
438 
439                         // ::std::basic_iostream<char, ::std::char_traits<char>>
440                         if (s->ident == Id::basic_iostream &&
441                             char_std_char_traits_char(ti, "Sd"))
442                             return;
443                     }
444                     buf->writestring("St");
445                 }
446                 else
447                     prefix_name(p);
448             }
449             source_name(si);
450             if (!isStd(si))
451             {
452                 /* Do this after the source_name() call to keep components[]
453                  * in the right order.
454                  * https://issues.dlang.org/show_bug.cgi?id=17947
455                  */
456                 append(si);
457             }
458         }
459     }
460 
cpp_mangle_name(Dsymbol * s,bool qualified)461     void cpp_mangle_name(Dsymbol *s, bool qualified)
462     {
463         //printf("cpp_mangle_name(%s, %d)\n", s->toChars(), qualified);
464         Dsymbol *p = s->toParent3();
465         Dsymbol *se = s;
466         bool write_prefix = true;
467         if (p && p->isTemplateInstance())
468         {
469             se = p;
470             if (find(p->isTemplateInstance()->tempdecl) >= 0)
471                 write_prefix = false;
472             p = p->toParent3();
473         }
474 
475         if (p && !p->isModule())
476         {
477             /* The N..E is not required if:
478              * 1. the parent is 'std'
479              * 2. 'std' is the initial qualifier
480              * 3. there is no CV-qualifier or a ref-qualifier for a member function
481              * ABI 5.1.8
482              */
483             if (isStd(p) && !qualified)
484             {
485                 TemplateInstance *ti = se->isTemplateInstance();
486                 if (s->ident == Id::allocator)
487                 {
488                     buf->writestring("Sa");      // "Sa" is short for ::std::allocator
489                     template_args(ti);
490                 }
491                 else if (s->ident == Id::basic_string)
492                 {
493                     // ::std::basic_string<char, ::std::char_traits<char>, ::std::allocator<char>>
494                     if (ti->tiargs->length == 3 &&
495                         isChar((*ti->tiargs)[0]) &&
496                         isChar_traits_char((*ti->tiargs)[1]) &&
497                         isAllocator_char((*ti->tiargs)[2]))
498 
499                     {
500                         buf->writestring("Ss");
501                         return;
502                     }
503                     buf->writestring("Sb");      // ::std::basic_string
504                     template_args(ti);
505                 }
506                 else
507                 {
508                     // ::std::basic_istream<char, ::std::char_traits<char>>
509                     if (s->ident == Id::basic_istream)
510                     {
511                         if (char_std_char_traits_char(ti, "Si"))
512                             return;
513                     }
514                     else if (s->ident == Id::basic_ostream)
515                     {
516                         if (char_std_char_traits_char(ti, "So"))
517                             return;
518                     }
519                     else if (s->ident == Id::basic_iostream)
520                     {
521                         if (char_std_char_traits_char(ti, "Sd"))
522                             return;
523                     }
524                     buf->writestring("St");
525                     source_name(se);
526                 }
527             }
528             else
529             {
530                 buf->writeByte('N');
531                 if (write_prefix)
532                     prefix_name(p);
533                 source_name(se);
534                 buf->writeByte('E');
535             }
536         }
537         else
538             source_name(se);
539         append(s);
540     }
541 
CV_qualifiers(Type * t)542     void CV_qualifiers(Type *t)
543     {
544         // CV-qualifiers are 'r': restrict, 'V': volatile, 'K': const
545         if (t->isConst())
546             buf->writeByte('K');
547     }
548 
mangle_variable(VarDeclaration * d,bool is_temp_arg_ref)549     void mangle_variable(VarDeclaration *d, bool is_temp_arg_ref)
550     {
551         // fake mangling for fields to fix https://issues.dlang.org/show_bug.cgi?id=16525
552         if (!(d->storage_class & (STCextern | STCfield | STCgshared)))
553         {
554             d->error("Internal Compiler Error: C++ static non-`__gshared` non-`extern` variables not supported");
555             fatal();
556         }
557 
558         Dsymbol *p = d->toParent3();
559         if (p && !p->isModule()) //for example: char Namespace1::beta[6] should be mangled as "_ZN10Namespace14betaE"
560         {
561             buf->writestring("_ZN");
562             prefix_name(p);
563             source_name(d);
564             buf->writeByte('E');
565         }
566         else //char beta[6] should mangle as "beta"
567         {
568             if (!is_temp_arg_ref)
569             {
570                 buf->writestring(d->ident->toChars());
571             }
572             else
573             {
574                 buf->writestring("_Z");
575                 source_name(d);
576             }
577         }
578     }
579 
mangle_function(FuncDeclaration * d)580     void mangle_function(FuncDeclaration *d)
581     {
582         //printf("mangle_function(%s)\n", d->toChars());
583         /*
584          * <mangled-name> ::= _Z <encoding>
585          */
586         buf->writestring("_Z");
587         this->mangle_function_encoding(d);
588     }
589 
mangle_function_encoding(FuncDeclaration * d)590     void mangle_function_encoding(FuncDeclaration *d)
591     {
592         //printf("mangle_function_encoding(%s)\n", d->toChars());
593         /*
594          * <encoding> ::= <function name> <bare-function-type>
595          *            ::= <data name>
596          *            ::= <special-name>
597          */
598         TypeFunction *tf = (TypeFunction *)d->type;
599 
600         if (getFuncTemplateDecl(d))
601         {
602             /* It's an instance of a function template
603              */
604             TemplateInstance *ti = d->parent->isTemplateInstance();
605             assert(ti);
606             Dsymbol *p = ti->toParent3();
607             if (p && !p->isModule() && tf->linkage == LINKcpp)
608             {
609                 buf->writeByte('N');
610                 CV_qualifiers(d->type);
611                 prefix_name(p);
612                 if (d->isCtorDeclaration())
613                     buf->writestring("C1");
614                 else if (d->isDtorDeclaration())
615                     buf->writestring("D1");
616                 else
617                     source_name(ti);
618                 buf->writeByte('E');
619             }
620             else
621                 source_name(ti);
622             headOfType(tf->nextOf());  // mangle return type
623         }
624         else
625         {
626             Dsymbol *p = d->toParent3();
627             if (p && !p->isModule() && tf->linkage == LINKcpp)
628             {
629                 /* <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
630                  *               ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
631                  */
632                 buf->writeByte('N');
633                 CV_qualifiers(d->type);
634 
635                 /* <prefix> ::= <prefix> <unqualified-name>
636                  *          ::= <template-prefix> <template-args>
637                  *          ::= <template-param>
638                  *          ::= # empty
639                  *          ::= <substitution>
640                  *          ::= <prefix> <data-member-prefix>
641                  */
642                 prefix_name(p);
643                 //printf("p: %s\n", buf.peekChars());
644 
645                 if (d->isCtorDeclaration())
646                 {
647                     buf->writestring("C1");
648                 }
649                 else if (d->isDtorDeclaration())
650                 {
651                     buf->writestring("D1");
652                 }
653                 else
654                 {
655                     source_name(d);
656                 }
657                 buf->writeByte('E');
658             }
659             else
660             {
661                 source_name(d);
662             }
663         }
664 
665         if (tf->linkage == LINKcpp) //Template args accept extern "C" symbols with special mangling
666         {
667             assert(tf->ty == Tfunction);
668             mangleFunctionParameters(tf->parameterList.parameters,
669                                      tf->parameterList.varargs);
670         }
671     }
672 
mangleFunctionParameters(Parameters * parameters,int varargs)673     void mangleFunctionParameters(Parameters *parameters, int varargs)
674     {
675         struct ParamsCppMangle
676         {
677             int numparams;
678             CppMangleVisitor *mangler;
679 
680             static int dg(void *ctx, size_t, Parameter *fparam)
681             {
682                 ParamsCppMangle *p = (ParamsCppMangle *)ctx;
683                 CppMangleVisitor *mangler = p->mangler;
684                 Type *t = target.cpp.parameterType(fparam);
685                 if (t->ty == Tsarray)
686                 {
687                     // Static arrays in D are passed by value; no counterpart in C++
688                     t->error(mangler->loc, "Internal Compiler Error: unable to pass static array `%s` to extern(C++) function, use pointer instead",
689                         t->toChars());
690                     fatal();
691                 }
692                 mangler->headOfType(t);
693                 p->numparams++;
694                 return 0;
695             }
696         };
697 
698         ParamsCppMangle p;
699         p.numparams = 0;
700         p.mangler = this;
701 
702         if (parameters)
703             Parameter_foreach(parameters, &ParamsCppMangle::dg, (void*)&p);
704 
705         if (varargs)
706             buf->writeByte('z');
707         else if (!p.numparams)
708             buf->writeByte('v'); // encode (void) parameters
709     }
710 
711 public:
CppMangleVisitor(OutBuffer * buf,Loc loc)712     CppMangleVisitor(OutBuffer *buf, Loc loc)
713         : components(), buf(buf), loc(loc)
714     {
715     }
716 
717     /*****
718      * Entry point. Append mangling to buf[]
719      * Params:
720      *  s = symbol to mangle
721      */
mangleOf(Dsymbol * s)722     void mangleOf(Dsymbol *s)
723     {
724         if (VarDeclaration *vd = s->isVarDeclaration())
725         {
726             mangle_variable(vd, false);
727         }
728         else if (FuncDeclaration *fd = s->isFuncDeclaration())
729         {
730             mangle_function(fd);
731         }
732         else
733         {
734             assert(0);
735         }
736     }
737 
738     /****** The rest is type mangling ************/
739 
error(Type * t)740     void error(Type *t)
741     {
742         const char *p;
743         if (t->isImmutable())
744             p = "`immutable` ";
745         else if (t->isShared())
746             p = "`shared` ";
747         else
748             p = "";
749         t->error(loc, "Internal Compiler Error: %stype `%s` can not be mapped to C++", p, t->toChars());
750         fatal(); //Fatal, because this error should be handled in frontend
751     }
752 
753     /****************************
754      * Mangle a type,
755      * treating it as a Head followed by a Tail.
756      * Params:
757      *  t = Head of a type
758      */
headOfType(Type * t)759     void headOfType(Type *t)
760     {
761         if (t->ty == Tclass)
762         {
763             mangleTypeClass((TypeClass*)t, true);
764         }
765         else
766         {
767             // For value types, strip const/immutable/shared from the head of the type
768             t->mutableOf()->unSharedOf()->accept(this);
769         }
770     }
771 
visit(Type * t)772     void visit(Type *t)
773     {
774         error(t);
775     }
776 
777     /******
778      * Write out 1 or 2 character basic type mangling.
779      * Handle const and substitutions.
780      * Params:
781      *  t = type to mangle
782      *  p = if not 0, then character prefix
783      *  c = mangling character
784      */
writeBasicType(Type * t,char p,char c)785     void writeBasicType(Type *t, char p, char c)
786     {
787         // Only do substitutions for non-fundamental types.
788         if (!isFundamentalType(t) || t->isConst())
789         {
790             if (substitute(t))
791                 return;
792             else
793                 append(t);
794         }
795         CV_qualifiers(t);
796         if (p)
797             buf->writeByte(p);
798         buf->writeByte(c);
799     }
800 
visit(TypeNull * t)801     void visit(TypeNull *t)
802     {
803         if (t->isImmutable() || t->isShared())
804             return error(t);
805 
806         writeBasicType(t, 'D', 'n');
807     }
808 
visit(TypeNoreturn * t)809     void visit(TypeNoreturn *t)
810     {
811         if (t->isImmutable() || t->isShared())
812             return error(t);
813 
814         writeBasicType(t, 0, 'v');      // mangle like `void`
815     }
816 
visit(TypeBasic * t)817     void visit(TypeBasic *t)
818     {
819         if (t->isImmutable() || t->isShared())
820             return error(t);
821 
822         // Handle any target-specific basic types.
823         if (const char *tm = target.cpp.typeMangle(t))
824         {
825             // Only do substitutions for non-fundamental types.
826             if (!isFundamentalType(t) || t->isConst())
827             {
828                 if (substitute(t))
829                     return;
830                 else
831                     append(t);
832             }
833             CV_qualifiers(t);
834             buf->writestring(tm);
835             return;
836         }
837 
838         /* <builtin-type>:
839          * v        void
840          * w        wchar_t
841          * b        bool
842          * c        char
843          * a        signed char
844          * h        unsigned char
845          * s        short
846          * t        unsigned short
847          * i        int
848          * j        unsigned int
849          * l        long
850          * m        unsigned long
851          * x        long long, __int64
852          * y        unsigned long long, __int64
853          * n        __int128
854          * o        unsigned __int128
855          * f        float
856          * d        double
857          * e        long double, __float80
858          * g        __float128
859          * z        ellipsis
860          * Dd       64 bit IEEE 754r decimal floating point
861          * De       128 bit IEEE 754r decimal floating point
862          * Df       32 bit IEEE 754r decimal floating point
863          * Dh       16 bit IEEE 754r half-precision floating point
864          * Di       char32_t
865          * Ds       char16_t
866          * u <source-name>  # vendor extended type
867          */
868 
869         char c;
870         char p = 0;
871         switch (t->ty)
872         {
873             case Tvoid:                 c = 'v';        break;
874             case Tint8:                 c = 'a';        break;
875             case Tuns8:                 c = 'h';        break;
876             case Tint16:                c = 's';        break;
877             case Tuns16:                c = 't';        break;
878             case Tint32:                c = 'i';        break;
879             case Tuns32:                c = 'j';        break;
880             case Tfloat32:              c = 'f';        break;
881             case Tint64:
882                 c = (target.c.longsize == 8 ? 'l' : 'x');
883                 break;
884             case Tuns64:
885                 c = (target.c.longsize == 8 ? 'm' : 'y');
886                 break;
887             case Tint128:                c = 'n';       break;
888             case Tuns128:                c = 'o';       break;
889             case Tfloat64:               c = 'd';       break;
890             case Tfloat80:               c = 'e';       break;
891             case Tbool:                  c = 'b';       break;
892             case Tchar:                  c = 'c';       break;
893             case Twchar:                 c = 't';       break;  // unsigned short (perhaps use 'Ds' ?
894             case Tdchar:                 c = 'w';       break;  // wchar_t (UTF-32) (perhaps use 'Di' ?
895             case Timaginary32:  p = 'G'; c = 'f';       break;  // 'G' means imaginary
896             case Timaginary64:  p = 'G'; c = 'd';       break;
897             case Timaginary80:  p = 'G'; c = 'e';       break;
898             case Tcomplex32:    p = 'C'; c = 'f';       break;  // 'C' means complex
899             case Tcomplex64:    p = 'C'; c = 'd';       break;
900             case Tcomplex80:    p = 'C'; c = 'e';       break;
901 
902             default:
903                 return error(t);
904         }
905         writeBasicType(t, p, c);
906     }
907 
visit(TypeVector * t)908     void visit(TypeVector *t)
909     {
910         if (t->isImmutable() || t->isShared())
911             return error(t);
912 
913         if (substitute(t))
914             return;
915         append(t);
916         CV_qualifiers(t);
917 
918         // Handle any target-specific vector types.
919         if (const char *tm = target.cpp.typeMangle(t))
920         {
921             buf->writestring(tm);
922         }
923         else
924         {
925             assert(t->basetype && t->basetype->ty == Tsarray);
926             assert(((TypeSArray *)t->basetype)->dim);
927             buf->writestring("U8__vector"); //-- Gnu ABI v.3
928             t->basetype->nextOf()->accept(this);
929         }
930     }
931 
visit(TypeSArray * t)932     void visit(TypeSArray *t)
933     {
934         if (t->isImmutable() || t->isShared())
935             return error(t);
936 
937         if (!substitute(t))
938             append(t);
939         CV_qualifiers(t);
940         buf->writeByte('A');
941         buf->printf("%llu", t->dim ? t->dim->toInteger() : 0);
942         buf->writeByte('_');
943         t->next->accept(this);
944     }
945 
visit(TypePointer * t)946     void visit(TypePointer *t)
947     {
948         if (t->isImmutable() || t->isShared())
949             return error(t);
950 
951         if (substitute(t))
952             return;
953         CV_qualifiers(t);
954         buf->writeByte('P');
955         t->next->accept(this);
956         append(t);
957     }
958 
visit(TypeReference * t)959     void visit(TypeReference *t)
960     {
961         //printf("TypeReference %s\n", t->toChars());
962         if (substitute(t))
963             return;
964         buf->writeByte('R');
965         t->next->accept(this);
966         append(t);
967     }
968 
visit(TypeFunction * t)969     void visit(TypeFunction *t)
970     {
971         /*
972          *  <function-type> ::= F [Y] <bare-function-type> E
973          *  <bare-function-type> ::= <signature type>+
974          *  # types are possible return type, then parameter types
975          */
976 
977         /* ABI says:
978             "The type of a non-static member function is considered to be different,
979             for the purposes of substitution, from the type of a namespace-scope or
980             static member function whose type appears similar. The types of two
981             non-static member functions are considered to be different, for the
982             purposes of substitution, if the functions are members of different
983             classes. In other words, for the purposes of substitution, the class of
984             which the function is a member is considered part of the type of
985             function."
986 
987             BUG: Right now, types of functions are never merged, so our simplistic
988             component matcher always finds them to be different.
989             We should use Type::equals on these, and use different
990             TypeFunctions for non-static member functions, and non-static
991             member functions of different classes.
992          */
993         if (substitute(t))
994             return;
995         buf->writeByte('F');
996         if (t->linkage == LINKc)
997             buf->writeByte('Y');
998         Type *tn = t->next;
999         if (t->isref)
1000             tn  = tn->referenceTo();
1001         tn->accept(this);
1002         mangleFunctionParameters(t->parameterList.parameters,
1003                                  t->parameterList.varargs);
1004         buf->writeByte('E');
1005         append(t);
1006     }
1007 
visit(TypeStruct * t)1008     void visit(TypeStruct *t)
1009     {
1010         if (t->isImmutable() || t->isShared())
1011             return error(t);
1012 
1013         //printf("TypeStruct %s\n", t->toChars());
1014         doSymbol(t);
1015     }
1016 
1017 
visit(TypeEnum * t)1018     void visit(TypeEnum *t)
1019     {
1020         if (t->isImmutable() || t->isShared())
1021             return error(t);
1022 
1023         /* __c_(u)long(long) and others get special mangling
1024          */
1025         Identifier *id = t->sym->ident;
1026         //printf("enum id = '%s'\n", id->toChars());
1027         if (id == Id::__c_long)
1028             return writeBasicType(t, 0, 'l');
1029         else if (id == Id::__c_ulong)
1030             return writeBasicType(t, 0, 'm');
1031         else if (id == Id::__c_wchar_t)
1032             return writeBasicType(t, 0, 'w');
1033         else if (id == Id::__c_longlong)
1034             return writeBasicType(t, 0, 'x');
1035         else if (id == Id::__c_ulonglong)
1036             return writeBasicType(t, 0, 'y');
1037         else if (id == Id::__c_complex_float)
1038             return writeBasicType(t, 'C', 'f');
1039         else if (id == Id::__c_complex_double)
1040             return writeBasicType(t, 'C', 'd');
1041         else if (id == Id::__c_complex_real)
1042             return writeBasicType(t, 'C', 'e');
1043 
1044         doSymbol(t);
1045     }
1046 
1047     /****************
1048      * Write structs and enums.
1049      * Params:
1050      *  t = TypeStruct or TypeEnum
1051      */
doSymbol(Type * t)1052     void doSymbol(Type *t)
1053     {
1054         if (substitute(t))
1055             return;
1056         CV_qualifiers(t);
1057 
1058         // Handle any target-specific struct types.
1059         if (const char *tm = target.cpp.typeMangle(t))
1060         {
1061             buf->writestring(tm);
1062         }
1063         else
1064         {
1065             Dsymbol *s = t->toDsymbol(NULL);
1066             Dsymbol *p = s->toParent3();
1067             if (p && p->isTemplateInstance())
1068             {
1069                 /* https://issues.dlang.org/show_bug.cgi?id=17947
1070                  * Substitute the template instance symbol, not the struct/enum symbol
1071                  */
1072                 if (substitute(p))
1073                     return;
1074             }
1075             if (!substitute(s))
1076             {
1077                 cpp_mangle_name(s, t->isConst());
1078             }
1079         }
1080         if (t->isConst())
1081             append(t);
1082     }
1083 
visit(TypeClass * t)1084     void visit(TypeClass *t)
1085     {
1086         mangleTypeClass(t, false);
1087     }
1088 
1089     /************************
1090      * Mangle a class type.
1091      * If it's the head, treat the initial pointer as a value type.
1092      * Params:
1093      *  t = class type
1094      *  head = true for head of a type
1095      */
mangleTypeClass(TypeClass * t,bool head)1096     void mangleTypeClass(TypeClass *t, bool head)
1097     {
1098         if (t->isImmutable() || t->isShared())
1099             return error(t);
1100 
1101         /* Mangle as a <pointer to><struct>
1102          */
1103         if (substitute(t))
1104             return;
1105         if (!head)
1106             CV_qualifiers(t);
1107         buf->writeByte('P');
1108 
1109         CV_qualifiers(t);
1110 
1111         {
1112             Dsymbol *s = t->toDsymbol(NULL);
1113             Dsymbol *p = s->toParent3();
1114             if (p && p->isTemplateInstance())
1115             {
1116                  /* https://issues.dlang.org/show_bug.cgi?id=17947
1117                   * Substitute the template instance symbol, not the class symbol
1118                   */
1119                 if (substitute(p))
1120                     return;
1121             }
1122         }
1123 
1124         if (!substitute(t->sym))
1125         {
1126             cpp_mangle_name(t->sym, t->isConst());
1127         }
1128         if (t->isConst())
1129             append(NULL);  // C++ would have an extra type here
1130         append(t);
1131     }
1132 
mangle_typeinfo(Dsymbol * s)1133     const char *mangle_typeinfo(Dsymbol *s)
1134     {
1135         buf->writestring("_ZTI");
1136         cpp_mangle_name(s, false);
1137         return buf->extractChars();
1138     }
1139 };
1140 
toCppMangleItanium(Dsymbol * s)1141 const char *toCppMangleItanium(Dsymbol *s)
1142 {
1143     //printf("toCppMangleItanium(%s)\n", s->toChars());
1144     OutBuffer buf;
1145     CppMangleVisitor v(&buf, s->loc);
1146     v.mangleOf(s);
1147     return buf.extractChars();
1148 }
1149 
cppTypeInfoMangleItanium(Dsymbol * s)1150 const char *cppTypeInfoMangleItanium(Dsymbol *s)
1151 {
1152     //printf("cppTypeInfoMangleItanium(%s)\n", s->toChars());
1153     OutBuffer buf;
1154     buf.writestring("_ZTI");    // "TI" means typeinfo structure
1155     CppMangleVisitor v(&buf, s->loc);
1156     v.cpp_mangle_name(s, false);
1157     return buf.extractChars();
1158 }
1159 
cppThunkMangleItanium(FuncDeclaration * fd,int offset)1160 const char *cppThunkMangleItanium(FuncDeclaration *fd, int offset)
1161 {
1162     //printf("cppThunkMangleItanium(%s)\n", fd.toChars());
1163     OutBuffer buf;
1164     buf.printf("_ZThn%u_", offset);  // "Th" means thunk, "n%u" is the call offset
1165     CppMangleVisitor v(&buf, fd->loc);
1166     v.mangle_function_encoding(fd);
1167     return buf.extractChars();
1168 }
1169