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