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