- %zu is not supported on windows
[cparser] / mangle.c
1 /*
2  * This file is part of cparser.
3  * Copyright (C) 2007-2008 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_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 in mangler");
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_parameters(const function_type_t *type)
74 {
75         if (type->unspecified_parameters)
76                 panic("can't mangle unspecified parameter types");
77         if (type->kr_style_parameters)
78                 panic("can't mangle kr_style_parameters type");
79
80         const function_parameter_t *parameter = type->parameters;
81         if (parameter != NULL) {
82                 for ( ; parameter != NULL; parameter = parameter->next) {
83                         mangle_type(parameter->type);
84                 }
85                 if (type->variadic) {
86                         obstack_1grow(&obst, 'z');
87                 }
88         } else {
89                 obstack_1grow(&obst, 'v');
90         }
91 }
92
93 static void mangle_function_type(const function_type_t *type)
94 {
95         obstack_1grow(&obst, 'F');
96         if (type->linkage == LINKAGE_C) {
97                 obstack_1grow(&obst, 'Y');
98         }
99
100         mangle_type(type->return_type);
101         mangle_parameters(type);
102
103         obstack_1grow(&obst, 'E');
104 }
105
106 static void mangle_class_enum_type(const entity_base_t *ent)
107 {
108         const symbol_t *sym = ent->symbol;
109         if (sym != NULL) {
110                 const char *name = sym->string;
111                 obstack_printf(&obst, SIZET_FMT "%s", strlen(name), name);
112         } else {
113                 /* TODO need the first typedef name here */
114                 panic("mangling of unnamed class/enum types not implemented yet");
115         }
116 }
117
118 static void mangle_array_type(const array_type_t *type)
119 {
120         if (type->is_vla) {
121                 obstack_1grow(&obst, 'A');
122                 obstack_1grow(&obst, '_');
123         } else if (type->size_constant) {
124                 obstack_printf(&obst, "A" SIZET_FMT "_", type->size);
125         } else {
126                 panic("mangling of non-constant sized array types not implemented yet");
127         }
128         mangle_type(type->element_type);
129 }
130
131 static void mangle_complex_type(const complex_type_t *type)
132 {
133         obstack_1grow(&obst, 'C');
134         obstack_1grow(&obst, get_atomic_type_mangle(type->akind));
135 }
136
137 static void mangle_imaginary_type(const imaginary_type_t *type)
138 {
139         obstack_1grow(&obst, 'G');
140         obstack_1grow(&obst, get_atomic_type_mangle(type->akind));
141 }
142
143 static void mangle_qualifiers(type_qualifiers_t qualifiers)
144 {
145         if (qualifiers & TYPE_QUALIFIER_RESTRICT)
146                 obstack_1grow(&obst, 'r');
147         if (qualifiers & TYPE_QUALIFIER_VOLATILE)
148                 obstack_1grow(&obst, 'V');
149         if (qualifiers & TYPE_QUALIFIER_CONST)
150                 obstack_1grow(&obst, 'K');
151
152         /* handle MS extended qualifiers? */
153 }
154
155 static void mangle_type(type_t *orig_type)
156 {
157         type_t *type = skip_typeref(orig_type);
158
159         mangle_qualifiers(type->base.qualifiers);
160
161         switch (type->kind) {
162         case TYPE_ATOMIC:
163                 mangle_atomic_type(&type->atomic);
164                 return;
165         case TYPE_POINTER:
166                 mangle_pointer_type(&type->pointer);
167                 return;
168         case TYPE_FUNCTION:
169                 mangle_function_type(&type->function);
170                 return;
171         case TYPE_COMPOUND_STRUCT:
172         case TYPE_COMPOUND_UNION:
173                 mangle_class_enum_type(&type->compound.compound->base);
174                 return;
175         case TYPE_ENUM:
176                 mangle_class_enum_type(&type->enumt.enume->base);
177                 return;
178         case TYPE_ARRAY:
179                 mangle_array_type(&type->array);
180                 return;
181         case TYPE_COMPLEX:
182                 mangle_complex_type(&type->complex);
183                 return;
184         case TYPE_IMAGINARY:
185                 mangle_imaginary_type(&type->imaginary);
186                 return;
187         case TYPE_INVALID:
188                 panic("invalid type encountered while mangling");
189         case TYPE_ERROR:
190                 panic("error type encountered while mangling");
191         case TYPE_BUILTIN:
192         case TYPE_TYPEDEF:
193         case TYPE_TYPEOF:
194                 panic("typeref not resolved while manging?!?");
195
196         case TYPE_BITFIELD:
197                 panic("no mangling for this type implemented yet");
198                 break;
199         }
200         panic("invalid type encountered while mangling");
201 }
202
203 static void mangle_entity(entity_t *entity)
204 {
205         obstack_1grow(&obst, '_');
206         obstack_1grow(&obst, 'Z');
207
208         /* TODO: mangle scope */
209
210         const char *name = entity->base.symbol->string;
211         obstack_printf(&obst, SIZET_FMT "%s", strlen(name), name);
212
213         if (entity->kind == ENTITY_FUNCTION) {
214                 mangle_parameters(&entity->declaration.type->function);
215         }
216 }
217
218 static ident *make_id_from_obst(void)
219 {
220         size_t  size = obstack_object_size(&obst);
221         char   *str  = obstack_finish(&obst);
222         ident  *id   = new_id_from_chars(str, size);
223         obstack_free(&obst, str);
224         return id;
225 }
226
227 /**
228  * Mangles an entity linker (ld) name for win32 usage.
229  *
230  * @param ent          the entity to be mangled
231  * @param declaration  the declaration
232  */
233 ident *create_name_win32(entity_t *entity)
234 {
235         struct obstack *o = &obst;
236
237         assert(is_declaration(entity));
238
239         if (entity->declaration.modifiers & DM_DLLIMPORT) {
240                 /* add prefix for imported symbols */
241                 obstack_printf(o, "__imp_");
242         }
243
244         if (entity->kind == ENTITY_FUNCTION) {
245                 cc_kind_t cc = entity->declaration.type->function.calling_convention;
246
247                 /* calling convention prefix */
248                 switch (cc) {
249                         case CC_DEFAULT:
250                         case CC_CDECL:
251                         case CC_STDCALL:  obstack_1grow(o, '_'); break;
252                         case CC_FASTCALL: obstack_1grow(o, '@'); break;
253                         default:          panic("unhandled calling convention");
254                 }
255
256                 switch (entity->declaration.type->function.linkage) {
257                         case LINKAGE_INVALID:
258                                 break;
259
260                         case LINKAGE_C:
261                                 obstack_printf(o, "%s", entity->base.symbol->string);
262                                 break;
263
264                         case LINKAGE_CXX:
265                                 mangle_entity(entity);
266                                 break;
267                 }
268
269                 /* calling convention suffix */
270                 switch (cc) {
271                         case CC_DEFAULT:
272                         case CC_CDECL:
273                                 break;
274
275                         case CC_STDCALL:
276                         case CC_FASTCALL: {
277                                 ir_type  *irtype = get_ir_type(entity->declaration.type);
278                                 unsigned size    = 0;
279                                 for (int i = get_method_n_params(irtype) - 1; i >= 0; --i) {
280                                         size += get_type_size_bytes(get_method_param_type(irtype, i));
281                                 }
282                                 obstack_printf(o, "@%u", size);
283                                 break;
284                         }
285
286                         default:
287                                 panic("unhandled calling convention");
288                 }
289         } else {
290                 obstack_printf(o, "_%s", entity->base.symbol->string);
291         }
292
293         return make_id_from_obst();
294 }
295
296 /**
297  * Mangles an entity linker (ld) name for Linux ELF usage.
298  *
299  * @param ent          the entity to be mangled
300  * @param declaration  the declaration
301  */
302 ident *create_name_linux_elf(entity_t *entity)
303 {
304         bool needs_mangling = false;
305
306         if (entity->kind == ENTITY_FUNCTION) {
307                 switch (entity->declaration.type->function.linkage) {
308                         case LINKAGE_INVALID: break;
309                         case LINKAGE_C:       break;
310                         case LINKAGE_CXX:     needs_mangling = true; break;
311                 }
312         }
313
314         if (needs_mangling) {
315                 mangle_entity(entity);
316                 return make_id_from_obst();
317         }
318
319         return new_id_from_str(entity->base.symbol->string);
320 }
321
322 /**
323  * Mangles an entity linker (ld) name for Mach-O usage.
324  *
325  * @param ent          the entity to be mangled
326  * @param declaration  the declaration
327  */
328 ident *create_name_macho(entity_t *entity)
329 {
330         obstack_printf(&obst, "_%s", entity->base.symbol->string);
331         return make_id_from_obst();
332 }
333
334 void init_mangle(void)
335 {
336         obstack_init(&obst);
337 }
338
339 void exit_mangle(void)
340 {
341         obstack_free(&obst, NULL);
342 }