main: rework preprocessor invocation
[cparser] / mangle.c
1 /*
2  * This file is part of cparser.
3  * Copyright (C) 2007-2009 Matthias Braun <matze@braunis.de>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18  * 02111-1307, USA.
19  */
20 #include <config.h>
21
22 #include <libfirm/firm.h>
23 #include <string.h>
24
25 #include "entity_t.h"
26 #include "type_t.h"
27 #include "symbol_t.h"
28 #include "mangle.h"
29 #include "diagnostic.h"
30 #include "ast2firm.h"
31 #include "lang_features.h"
32 #include "adt/error.h"
33
34 static struct obstack obst;
35
36 static void mangle_type(type_t *type);
37
38 static char get_atomic_type_mangle(atomic_type_kind_t kind)
39 {
40         switch (kind) {
41         case ATOMIC_TYPE_VOID:        return 'v';
42         case ATOMIC_TYPE_WCHAR_T:     return 'w';
43         case ATOMIC_TYPE_BOOL:        return 'b';
44         case ATOMIC_TYPE_CHAR:        return 'c';
45         case ATOMIC_TYPE_SCHAR:       return 'a';
46         case ATOMIC_TYPE_UCHAR:       return 'h';
47         case ATOMIC_TYPE_INT:         return 'i';
48         case ATOMIC_TYPE_UINT:        return 'j';
49         case ATOMIC_TYPE_SHORT:       return 's';
50         case ATOMIC_TYPE_USHORT:      return 't';
51         case ATOMIC_TYPE_LONG:        return 'l';
52         case ATOMIC_TYPE_ULONG:       return 'm';
53         case ATOMIC_TYPE_LONGLONG:    return 'x';
54         case ATOMIC_TYPE_ULONGLONG:   return 'y';
55         case ATOMIC_TYPE_LONG_DOUBLE: return 'e';
56         case ATOMIC_TYPE_FLOAT:       return 'f';
57         case ATOMIC_TYPE_DOUBLE:      return 'd';
58         }
59         panic("invalid atomic type");
60 }
61
62 static void mangle_atomic_type(const atomic_type_t *type)
63 {
64         obstack_1grow(&obst, get_atomic_type_mangle(type->akind));
65 }
66
67 static void mangle_pointer_type(const pointer_type_t *type)
68 {
69         obstack_1grow(&obst, 'P');
70         mangle_type(type->points_to);
71 }
72
73 static void mangle_reference_type(const reference_type_t *type)
74 {
75         obstack_1grow(&obst, 'R');
76         mangle_type(type->refers_to);
77 }
78
79 static void mangle_parameters(const function_type_t *type)
80 {
81         if (type->unspecified_parameters)
82                 panic("can't mangle unspecified parameter types");
83         if (type->kr_style_parameters)
84                 panic("can't mangle kr_style_parameters type");
85
86         const function_parameter_t *parameter = type->parameters;
87         if (parameter != NULL) {
88                 for ( ; parameter != NULL; parameter = parameter->next) {
89                         mangle_type(parameter->type);
90                 }
91                 if (type->variadic) {
92                         obstack_1grow(&obst, 'z');
93                 }
94         } else {
95                 obstack_1grow(&obst, 'v');
96         }
97 }
98
99 static void mangle_function_type(const function_type_t *type)
100 {
101         obstack_1grow(&obst, 'F');
102         if (type->linkage == LINKAGE_C) {
103                 obstack_1grow(&obst, 'Y');
104         }
105
106         mangle_type(type->return_type);
107         mangle_parameters(type);
108
109         obstack_1grow(&obst, 'E');
110 }
111
112 static void print_name(const char* name)
113 {
114         obstack_printf(&obst, "%u%s", (unsigned)strlen(name), name);
115 }
116
117 static void mangle_class_type(const compound_type_t *type)
118 {
119         const symbol_t *sym = type->compound->base.symbol;
120         if (sym == NULL) {
121                 if (type->compound->alias == NULL)
122                         panic("mangling anonymous type");
123                 sym = type->compound->alias->base.symbol;
124         }
125         print_name(sym->string);
126 }
127
128 static void mangle_enum_type(const enum_type_t *type)
129 {
130         const symbol_t *sym = type->enume->base.symbol;
131         if (sym == NULL) {
132                 if (type->enume->alias == NULL)
133                         panic("mangling anonymous type");
134                 sym = type->enume->alias->base.symbol;
135         }
136         print_name(sym->string);
137 }
138
139 static void mangle_array_type(const array_type_t *type)
140 {
141         if (type->is_vla) {
142                 obstack_1grow(&obst, 'A');
143                 obstack_1grow(&obst, '_');
144         } else if (type->size_constant) {
145                 obstack_printf(&obst, "A%u_", (unsigned) type->size);
146         } else {
147                 panic("mangling of non-constant sized array types not implemented yet");
148         }
149         mangle_type(type->element_type);
150 }
151
152 static void mangle_complex_type(const atomic_type_t *type)
153 {
154         obstack_1grow(&obst, 'C');
155         obstack_1grow(&obst, get_atomic_type_mangle(type->akind));
156 }
157
158 static void mangle_imaginary_type(const atomic_type_t *type)
159 {
160         obstack_1grow(&obst, 'G');
161         obstack_1grow(&obst, get_atomic_type_mangle(type->akind));
162 }
163
164 static void mangle_qualifiers(type_qualifiers_t qualifiers)
165 {
166 #if 0 /* Do not mangle restrict qualifiers.  GCC doesn't either */
167         if (qualifiers & TYPE_QUALIFIER_RESTRICT)
168                 obstack_1grow(&obst, 'r');
169 #endif
170         if (qualifiers & TYPE_QUALIFIER_VOLATILE)
171                 obstack_1grow(&obst, 'V');
172         if (qualifiers & TYPE_QUALIFIER_CONST)
173                 obstack_1grow(&obst, 'K');
174
175         /* handle MS extended qualifiers? */
176 }
177
178 static void mangle_type(type_t *orig_type)
179 {
180         type_t *type = skip_typeref(orig_type);
181
182         mangle_qualifiers(type->base.qualifiers);
183
184         switch (type->kind) {
185         case TYPE_ATOMIC:
186                 mangle_atomic_type(&type->atomic);
187                 return;
188         case TYPE_POINTER:
189                 mangle_pointer_type(&type->pointer);
190                 return;
191         case TYPE_REFERENCE:
192                 mangle_reference_type(&type->reference);
193                 return;
194         case TYPE_FUNCTION:
195                 mangle_function_type(&type->function);
196                 return;
197         case TYPE_COMPOUND_STRUCT:
198         case TYPE_COMPOUND_UNION:
199                 mangle_class_type(&type->compound);
200                 return;
201         case TYPE_ENUM:
202                 mangle_enum_type(&type->enumt);
203                 return;
204         case TYPE_ARRAY:
205                 mangle_array_type(&type->array);
206                 return;
207         case TYPE_COMPLEX:
208                 mangle_complex_type(&type->atomic);
209                 return;
210         case TYPE_IMAGINARY:
211                 mangle_imaginary_type(&type->atomic);
212                 return;
213         case TYPE_ERROR:
214                 panic("error type encountered while mangling");
215         case TYPE_TYPEDEF:
216         case TYPE_TYPEOF:
217                 panic("typeref not resolved while manging?!?");
218         }
219         panic("invalid type encountered while mangling");
220 }
221
222 static void mangle_namespace(entity_t *entity)
223 {
224         for (entity_t *e = entity->base.parent_entity; e != NULL;
225              e = e->base.parent_entity) {
226             /* TODO: we need something similar (or the same?) for classes */
227                 if (e->kind == ENTITY_NAMESPACE) {
228                         mangle_namespace(e);
229                         print_name(e->base.symbol->string);
230                         return;
231                 }
232         }
233 }
234
235 static void mangle_entity(entity_t *entity)
236 {
237         obstack_1grow(&obst, '_');
238         obstack_1grow(&obst, 'Z');
239
240         if (entity->base.parent_entity != NULL) {
241                 obstack_1grow(&obst, 'N');
242                 mangle_namespace(entity);
243         }
244
245         print_name(entity->base.symbol->string);
246
247         if (entity->kind == ENTITY_FUNCTION) {
248                 mangle_parameters(&entity->declaration.type->function);
249         }
250 }
251
252 static ident *make_id_from_obst(void)
253 {
254         size_t  size = obstack_object_size(&obst);
255         char   *str  = obstack_finish(&obst);
256         ident  *id   = new_id_from_chars(str, size);
257         obstack_free(&obst, str);
258         return id;
259 }
260
261 /**
262  * Mangles an entity linker (ld) name for win32 usage.
263  *
264  * @param ent          the entity to be mangled
265  * @param declaration  the declaration
266  */
267 ident *create_name_win32(entity_t *entity)
268 {
269         struct obstack *o = &obst;
270
271         assert(is_declaration(entity));
272
273         if (entity->kind == ENTITY_FUNCTION) {
274                 type_t *type = skip_typeref(entity->declaration.type);
275                 assert(is_type_function(type));
276
277                 if (entity->declaration.modifiers & DM_DLLIMPORT)
278                         /* add prefix for imported symbols */
279                         obstack_printf(o, "__imp_");
280
281                 cc_kind_t cc = type->function.calling_convention;
282
283                 /* calling convention prefix */
284                 switch (cc) {
285                 case CC_DEFAULT:
286                 case CC_CDECL:
287                 case CC_STDCALL:  obstack_1grow(o, '_'); break;
288                 case CC_FASTCALL: obstack_1grow(o, '@'); break;
289                 default:          panic("unhandled calling convention");
290                 }
291
292                 switch (type->function.linkage) {
293                 case LINKAGE_C:
294                         obstack_printf(o, "%s", entity->base.symbol->string);
295                         break;
296
297                 case LINKAGE_CXX:
298                         mangle_entity(entity);
299                         break;
300                 }
301
302                 /* calling convention suffix */
303                 switch (cc) {
304                 case CC_DEFAULT:
305                 case CC_CDECL:
306                         break;
307
308                 case CC_STDCALL:
309                 case CC_FASTCALL: {
310                         ir_type  *irtype = get_ir_type(entity->declaration.type);
311                         unsigned size    = 0;
312                         for (int i = get_method_n_params(irtype) - 1; i >= 0; --i) {
313                                 size += get_type_size_bytes(get_method_param_type(irtype, i));
314                         }
315                         obstack_printf(o, "@%u", size);
316                         break;
317                 }
318
319                 default:
320                         panic("unhandled calling convention");
321                 }
322         } else {
323                 obstack_printf(o, "_%s", entity->base.symbol->string);
324         }
325
326         return make_id_from_obst();
327 }
328
329 /**
330  * Mangles an entity linker (ld) name for Linux ELF usage.
331  *
332  * @param ent          the entity to be mangled
333  * @param declaration  the declaration
334  */
335 ident *create_name_linux_elf(entity_t *entity)
336 {
337         const char *name = entity->base.symbol->string;
338
339         if (entity->kind == ENTITY_FUNCTION) {
340                 type_t *type = skip_typeref(entity->declaration.type);
341                 assert(is_type_function(type));
342                 switch (type->function.linkage) {
343                         case LINKAGE_C:
344                                 if (entity->function.actual_name != NULL)
345                                         name = entity->function.actual_name->string;
346                                 break;
347                         case LINKAGE_CXX:
348                                 // TODO What about __REDIRECT/actual_name with mangling?
349                                 mangle_entity(entity);
350                                 return make_id_from_obst();
351                 }
352         }
353
354         return new_id_from_str(name);
355 }
356
357 /**
358  * Mangles an entity linker (ld) name for Mach-O usage.
359  *
360  * @param ent          the entity to be mangled
361  * @param declaration  the declaration
362  */
363 ident *create_name_macho(entity_t *entity)
364 {
365         if (entity->kind == ENTITY_FUNCTION) {
366                 type_t *type = skip_typeref(entity->declaration.type);
367                 assert(is_type_function(type));
368
369                 switch (type->function.linkage) {
370                         default:
371                                 if (entity->function.actual_name != NULL)
372                                         return new_id_from_str(entity->function.actual_name->string);
373                                 break;
374                 }
375         }
376
377         obstack_printf(&obst, "_%s", entity->base.symbol->string);
378         return make_id_from_obst();
379 }
380
381 void init_mangle(void)
382 {
383         obstack_init(&obst);
384 }
385
386 void exit_mangle(void)
387 {
388         obstack_free(&obst, NULL);
389 }