Allow returning something of type void in a function that returns void
[delight/core.git] / d-cppmngl.cc
blob59e823f696e1af395e57f6550032fef93cfe0d92
1 /* GDC -- D front-end for GCC
2 Copyright (C) 2007 David Friedman
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "d-gcc-includes.h"
21 // from DMD
22 #include "total.h"
23 #include "init.h"
24 #include "symbol.h"
25 #include "d-lang.h"
26 #include "d-codegen.h"
28 // Declared in dmd/mangle.c
29 char *cpp_mangle(Dsymbol *s);
31 static void
32 to_base36(unsigned n, OutBuffer * buf)
34 static const char base_36_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
36 if (! n)
38 buf->writeByte('0');
39 return;
42 char cbuf[64];
43 char *p = cbuf + sizeof(cbuf);
45 while (n && p > cbuf)
47 unsigned d = n / 36;
48 *--p = base_36_digits[n - d * 36];
49 n = d;
51 buf->write(p, sizeof(cbuf) - (p - cbuf));
54 struct CppMangleState
56 Dsymbol * topSymbol;
57 Array substitutions;
59 private:
60 bool _hasSubstitute(void * p, OutBuffer * buf)
62 for (unsigned i = 0; i < substitutions.dim; ++i)
63 if ( substitutions.data[i] == p )
65 if (buf)
67 buf->writeByte('S');
68 if (i)
69 to_base36(i - 1, buf);
70 buf->writeByte('_');
72 return true;
74 return false;
76 public:
77 bool hasSubstitute(Type * type, OutBuffer * buf)
79 return _hasSubstitute(type, buf);
81 bool hasSubstitute(Dsymbol * sym, OutBuffer * buf)
83 return _hasSubstitute(sym, buf);
85 void add(Dsymbol * sym)
87 substitutions.push(sym);
89 void add(Type * typ)
91 substitutions.push(typ);
95 static void
96 cpp_mangle_arguments(TypeFunction * tf, OutBuffer * buf, CppMangleState *cms)
98 bool have_some_args = false;
100 if (tf->parameters)
102 size_t dim = Argument::dim(tf->parameters);
103 for (size_t i = 0; i < dim; i++)
104 { Argument *arg = Argument::getNth(tf->parameters, i);
106 have_some_args = true;
107 if (arg->storageClass & (STClazy))
109 // DMD does not report an error...
110 cms->topSymbol->error("cannot represent lazy parameter in C++");
112 else if (arg->storageClass & (STCout | STCref))
114 arg->type->referenceTo()->toCppMangle(buf, cms);
115 continue;
117 else if (arg->type->ty == Tsarray)
119 /* C++ would encode as pointer-to-elem-type, but DMD encodes
120 as pointer-to-array-type. */
121 arg->type->pointerTo()->toCppMangle(buf, cms);
122 continue;
125 // %% const/invariant not translated?
127 arg->type->toCppMangle(buf, cms);
130 if (tf->varargs == 1)
131 buf->writeByte('z');
132 else if (! have_some_args)
133 buf->writeByte('v');
136 static void
137 cpp_mangle1(Dsymbol *sthis, OutBuffer * buf, CppMangleState * cms)
139 if (cms->hasSubstitute(sthis, buf))
140 return;
142 Dsymbol * s = sthis;
143 bool is_nested_ident = false;
144 FuncDeclaration * fd;
145 Array pfxs;
150 if ( s != sthis && s->isFuncDeclaration() )
152 buf->writeByte('Z');
153 cpp_mangle1(s, buf, cms);
154 buf->writeByte('E');
155 break;
157 if (s != sthis)
158 is_nested_ident = true;
159 pfxs.push(s);
161 s = s->parent; // %% ?
162 } while (s && ! s->isModule());
164 if (is_nested_ident)
165 buf->writeByte('N');
167 unsigned ii;
168 for (ii = 0; ii < pfxs.dim; ++ii)
170 s = (Dsymbol *) pfxs.data[ii];
171 if (cms->hasSubstitute(s, buf))
172 break;
174 while (ii > 0)
176 s = (Dsymbol *) pfxs.data[--ii];
177 if (s->ident)
179 buf->printf("%d", (int) s->ident->len);
180 buf->write(s->ident->string, s->ident->len);
182 else
183 buf->writeByte('0');
184 if (! s->isFuncDeclaration())
185 cms->add(s);
188 if (is_nested_ident)
189 buf->writeByte('E');
191 if ( (fd = sthis->isFuncDeclaration()) )
193 cpp_mangle_arguments((TypeFunction *) fd->type, buf, cms);
197 char *
198 cpp_mangle(Dsymbol *s)
200 OutBuffer o;
201 CppMangleState cms;
203 cms.topSymbol = s;
205 o.writestring("_Z");
206 cpp_mangle1(s, & o, & cms);
207 o.toChars();
209 return (char*) o.extractData();
212 void
213 Type::toCppMangle(OutBuffer *buf, CppMangleState *cms)
215 //error("cannot represent type '%s' in C++", toChars());
216 // DMD uses D type mangle.
218 if (! cms->hasSubstitute(this, buf))
220 OutBuffer o;
221 toDecoBuffer(& o, 0);
222 buf->printf("%d", (int) o.offset);
223 buf->write(& o);
225 cms->add(this);
229 static void
230 cpp_mangle_fp(Type * t, const char * mngl, OutBuffer *buf, CppMangleState *cms)
232 if (! cms->hasSubstitute(t, buf))
234 buf->writestring(mngl);
236 cms->add(t);
240 void
241 TypeBasic::toCppMangle(OutBuffer *buf, CppMangleState *cms)
243 char c;
244 const char * s;
245 switch (ty)
247 case Tvoid: c = 'v'; break;
248 case Tint8: c = 'a'; break;
249 case Tuns8: c = 'h'; break;
250 case Tint16: c = 's'; break;
251 case Tuns16: c = 't'; break;
252 case Tint32: c = 'i'; break;
253 case Tuns32: c = 'j'; break;
254 case Tint64: c = 'x'; break;
255 case Tuns64: c = 'y'; break;
256 case Tfloat32: c = 'f'; break;
257 case Tfloat64: c = 'd'; break;
258 case Tfloat80: c = 'e'; break; // %% could change in the future when D real vs. C long double type is corrected
260 case Timaginary32: s = "Gf"; goto do_fp;
261 case Timaginary64: s = "Gd"; goto do_fp;
262 case Timaginary80: s = "Ge"; goto do_fp; // %% ditto
263 case Tcomplex32: s = "Cf"; goto do_fp;
264 case Tcomplex64: s = "Cd"; goto do_fp;
265 case Tcomplex80: s = "Ce"; // %% ditto
266 do_fp:
267 cpp_mangle_fp(this, s, buf, cms);
268 return;
270 case Tbool: c = 'b'; break;
272 case Tchar: c = 'c'; break;
273 #ifdef WCHAR_TYPE_SIZE
274 case Twchar:
275 if (WCHAR_TYPE_SIZE == 16)
276 c = 'w';
277 else
278 c = 't';
279 break;
280 case Tdchar:
281 if (WCHAR_TYPE_SIZE == 32)
282 c = 'w';
283 else
284 c = 'j';
285 break;
286 #else
287 case Twchar: c = 't'; break;
288 case Tdchar: c = 'j'; break;
289 #endif
291 default:
292 Type::toCppMangle(buf, cms);
293 return;
295 buf->writeByte(c);
298 void
299 TypeSArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
301 if (! cms->hasSubstitute(this, buf))
303 if (dim)
304 buf->printf("A%"PRIuMAX, dim->toInteger());
305 buf->writeByte('_');
306 if (next)
307 next->toCppMangle(buf, cms);
309 assert(! cms->hasSubstitute(this, NULL));
311 cms->add(this);
315 void
316 TypeDArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
318 return Type::toCppMangle(buf, cms);
321 void
322 TypeAArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
324 return Type::toCppMangle(buf, cms);
327 void
328 TypePointer::toCppMangle(OutBuffer *buf, CppMangleState *cms)
330 if (! cms->hasSubstitute(this, buf))
332 buf->writeByte('P');
333 if (next)
334 next->toCppMangle(buf, cms);
336 assert(! cms->hasSubstitute(this, NULL));
338 cms->add(this);
342 void
343 TypeReference::toCppMangle(OutBuffer *buf, CppMangleState *cms)
345 if (! cms->hasSubstitute(this, buf))
347 buf->writeByte('R');
348 if (next)
349 next->toCppMangle(buf, cms);
351 assert(! cms->hasSubstitute(this, NULL));
353 cms->add(this);
357 void
358 TypeFunction::toCppMangle(OutBuffer *buf, CppMangleState *cms)
360 if (! cms->hasSubstitute(this, buf))
362 buf->writeByte('F');
363 if (next)
364 next->toCppMangle(buf, cms);
365 cpp_mangle_arguments(this, buf, cms);
366 buf->writeByte('E');
368 assert(! cms->hasSubstitute(this, NULL));
370 cms->add(this);
374 void
375 TypeDelegate::toCppMangle(OutBuffer *buf, CppMangleState *cms)
377 Type::toCppMangle(buf, cms);
380 void
381 TypeStruct::toCppMangle(OutBuffer *buf, CppMangleState *cms)
383 cpp_mangle1(sym, buf, cms);
386 void
387 TypeEnum::toCppMangle(OutBuffer *buf, CppMangleState *cms)
389 cpp_mangle1(sym, buf, cms);
392 void
393 TypeTypedef::toCppMangle(OutBuffer *buf, CppMangleState *cms)
395 // DMD uses the D mangled typedef name.
396 Type::toCppMangle(buf, cms);
399 void
400 TypeClass::toCppMangle(OutBuffer *buf, CppMangleState *cms)
402 if (! cms->hasSubstitute(this, buf))
404 buf->writeByte('P');
405 cpp_mangle1(sym, buf, cms);
407 assert(! cms->hasSubstitute(this, NULL));
409 cms->add(this);