Simplify further.
[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_function_type(const function_type_t *type)
74 {
75         obstack_1grow(&obst, 'F');
76         if (type->linkage == LINKAGE_C) {
77                 obstack_1grow(&obst, 'Y');
78         }
79
80         mangle_type(type->return_type);
81
82         function_parameter_t *parameter = type->parameters;
83         for ( ; parameter != NULL; parameter = parameter->next) {
84                 mangle_type(parameter->type);
85         }
86         if (type->variadic) {
87                 obstack_1grow(&obst, 'z');
88         }
89         if (type->unspecified_parameters)
90                 panic("can't mangle unspecified parameter types");
91         if (type->kr_style_parameters)
92                 panic("can't mangle kr_style_parameters type");
93
94         obstack_1grow(&obst, 'E');
95 }
96
97 static void mangle_qualifiers(type_qualifiers_t qualifiers)
98 {
99         if (qualifiers & TYPE_QUALIFIER_CONST)
100                 obstack_1grow(&obst, 'K');
101         if (qualifiers & TYPE_QUALIFIER_VOLATILE)
102                 obstack_1grow(&obst, 'V');
103         if (qualifiers & TYPE_QUALIFIER_RESTRICT)
104                 obstack_1grow(&obst, 'r');
105
106         /* handle MS extended qualifiers? */
107 }
108
109 static void mangle_type(type_t *orig_type)
110 {
111         type_t *type = skip_typeref(orig_type);
112
113         mangle_qualifiers(type->base.qualifiers);
114
115         switch (type->kind) {
116         case TYPE_ATOMIC:
117                 mangle_atomic_type(&type->atomic);
118                 return;
119         case TYPE_POINTER:
120                 mangle_pointer_type(&type->pointer);
121                 return;
122         case TYPE_FUNCTION:
123                 mangle_function_type(&type->function);
124                 return;
125         case TYPE_INVALID:
126                 panic("invalid type encountered while mangling");
127         case TYPE_ERROR:
128                 panic("error type encountered while mangling");
129         case TYPE_BUILTIN:
130         case TYPE_TYPEDEF:
131         case TYPE_TYPEOF:
132                 panic("typeref not resolved while manging?!?");
133
134         case TYPE_BITFIELD:
135         case TYPE_COMPLEX:
136         case TYPE_IMAGINARY:
137         case TYPE_COMPOUND_STRUCT:
138         case TYPE_COMPOUND_UNION:
139         case TYPE_ENUM:
140         case TYPE_ARRAY:
141                 panic("no mangling for this type implemented yet");
142                 break;
143         }
144         panic("invalid type encountered while mangling");
145 }
146
147 static void mangle_entity(entity_t *entity)
148 {
149         obstack_1grow(&obst, '_');
150         obstack_1grow(&obst, 'Z');
151
152         /* TODO: mangle scope */
153
154         symbol_t *symbol = entity->base.symbol;
155         obstack_printf(&obst, "%u%s", strlen(symbol->string), symbol->string);
156
157         if (entity->kind == ENTITY_FUNCTION) {
158                 mangle_type(entity->declaration.type);
159         }
160 }
161
162 static ident *make_id_from_obst(void)
163 {
164         size_t  size = obstack_object_size(&obst);
165         char   *str  = obstack_finish(&obst);
166         ident  *id   = new_id_from_chars(str, size);
167         obstack_free(&obst, str);
168         return id;
169 }
170
171 /**
172  * Mangles an entity linker (ld) name for win32 usage.
173  *
174  * @param ent          the entity to be mangled
175  * @param declaration  the declaration
176  */
177 ident *create_name_win32(entity_t *entity)
178 {
179         struct obstack *o = &obst;
180
181         assert(is_declaration(entity));
182
183         if (entity->declaration.modifiers & DM_DLLIMPORT) {
184                 /* add prefix for imported symbols */
185                 obstack_printf(o, "__imp_");
186         }
187
188         if (entity->kind == ENTITY_FUNCTION) {
189                 cc_kind_t cc = entity->declaration.type->function.calling_convention;
190
191                 /* calling convention prefix */
192                 switch (cc) {
193                         case CC_DEFAULT:
194                         case CC_CDECL:
195                         case CC_STDCALL:  obstack_1grow(o, '_'); break;
196                         case CC_FASTCALL: obstack_1grow(o, '@'); break;
197                         default:          panic("unhandled calling convention");
198                 }
199
200                 switch (entity->declaration.type->function.linkage) {
201                         case LINKAGE_INVALID:
202                                 break;
203
204                         case LINKAGE_C:
205                                 obstack_printf(o, "%s", entity->base.symbol->string);
206                                 break;
207
208                         case LINKAGE_CXX:
209                                 mangle_entity(entity);
210                                 break;
211                 }
212
213                 /* calling convention suffix */
214                 switch (cc) {
215                         case CC_DEFAULT:
216                         case CC_CDECL:
217                                 break;
218
219                         case CC_STDCALL:
220                         case CC_FASTCALL: {
221                                 ir_type *irtype = get_ir_type(entity->declaration.type);
222                                 size_t   size   = 0;
223                                 for (int i = get_method_n_params(irtype) - 1; i >= 0; --i) {
224                                         size += get_type_size_bytes(get_method_param_type(irtype, i));
225                                 }
226                                 obstack_printf(o, "@%zu\n", size);
227                                 break;
228                         }
229
230                         default:
231                                 panic("unhandled calling convention");
232                 }
233         } else {
234                 obstack_printf(o, "_%s", entity->base.symbol->string);
235         }
236
237         return make_id_from_obst();
238 }
239
240 /**
241  * Mangles an entity linker (ld) name for Linux ELF usage.
242  *
243  * @param ent          the entity to be mangled
244  * @param declaration  the declaration
245  */
246 ident *create_name_linux_elf(entity_t *entity)
247 {
248         bool needs_mangling = false;
249
250         if (entity->kind == ENTITY_FUNCTION) {
251                 switch (entity->declaration.type->function.linkage) {
252                         case LINKAGE_INVALID: break;
253                         case LINKAGE_C:       break;
254                         case LINKAGE_CXX:     needs_mangling = true; break;
255                 }
256         }
257
258         if (needs_mangling) {
259                 mangle_entity(entity);
260                 return make_id_from_obst();
261         }
262
263         return new_id_from_str(entity->base.symbol->string);
264 }
265
266 /**
267  * Mangles an entity linker (ld) name for Mach-O usage.
268  *
269  * @param ent          the entity to be mangled
270  * @param declaration  the declaration
271  */
272 ident *create_name_macho(entity_t *entity)
273 {
274         obstack_printf(&obst, "_%s", entity->base.symbol->string);
275         return make_id_from_obst();
276 }
277
278 void init_mangle(void)
279 {
280         obstack_init(&obst);
281 }
282
283 void exit_mangle(void)
284 {
285         obstack_free(&obst, NULL);
286 }