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