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