2 * This file is part of cparser.
3 * Copyright (C) 2012 Matthias Braun <matze@braunis.de>
7 #include <libfirm/firm.h>
14 #include "diagnostic.h"
16 #include "lang_features.h"
17 #include "adt/error.h"
19 static struct obstack obst;
21 static void mangle_type(type_t *type);
23 static char get_atomic_type_mangle(atomic_type_kind_t 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';
44 panic("invalid atomic type");
47 static void mangle_atomic_type(const atomic_type_t *type)
49 obstack_1grow(&obst, get_atomic_type_mangle(type->akind));
52 static void mangle_pointer_type(const pointer_type_t *type)
54 obstack_1grow(&obst, 'P');
55 mangle_type(type->points_to);
58 static void mangle_reference_type(const reference_type_t *type)
60 obstack_1grow(&obst, 'R');
61 mangle_type(type->refers_to);
64 static void mangle_parameters(const function_type_t *type)
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");
71 const function_parameter_t *parameter = type->parameters;
72 if (parameter != NULL) {
73 for ( ; parameter != NULL; parameter = parameter->next) {
74 mangle_type(parameter->type);
77 obstack_1grow(&obst, 'z');
80 obstack_1grow(&obst, 'v');
84 static void mangle_function_type(const function_type_t *type)
86 obstack_1grow(&obst, 'F');
87 if (type->linkage == LINKAGE_C) {
88 obstack_1grow(&obst, 'Y');
91 mangle_type(type->return_type);
92 mangle_parameters(type);
94 obstack_1grow(&obst, 'E');
97 static void print_name(const char* name)
99 obstack_printf(&obst, "%u%s", (unsigned)strlen(name), name);
102 static void mangle_class_type(const compound_type_t *type)
104 const symbol_t *sym = type->compound->base.symbol;
106 if (type->compound->alias == NULL)
107 panic("mangling anonymous type");
108 sym = type->compound->alias->base.symbol;
110 print_name(sym->string);
113 static void mangle_enum_type(const enum_type_t *type)
115 const symbol_t *sym = type->enume->base.symbol;
117 if (type->enume->alias == NULL)
118 panic("mangling anonymous type");
119 sym = type->enume->alias->base.symbol;
121 print_name(sym->string);
124 static void mangle_array_type(const array_type_t *type)
127 obstack_1grow(&obst, 'A');
128 obstack_1grow(&obst, '_');
129 } else if (type->size_constant) {
130 obstack_printf(&obst, "A%u_", (unsigned) type->size);
132 panic("mangling of non-constant sized array types not implemented yet");
134 mangle_type(type->element_type);
137 static void mangle_complex_type(const atomic_type_t *type)
139 obstack_1grow(&obst, 'C');
140 obstack_1grow(&obst, get_atomic_type_mangle(type->akind));
143 static void mangle_imaginary_type(const atomic_type_t *type)
145 obstack_1grow(&obst, 'G');
146 obstack_1grow(&obst, get_atomic_type_mangle(type->akind));
149 static void mangle_qualifiers(type_qualifiers_t qualifiers)
151 #if 0 /* Do not mangle restrict qualifiers. GCC doesn't either */
152 if (qualifiers & TYPE_QUALIFIER_RESTRICT)
153 obstack_1grow(&obst, 'r');
155 if (qualifiers & TYPE_QUALIFIER_VOLATILE)
156 obstack_1grow(&obst, 'V');
157 if (qualifiers & TYPE_QUALIFIER_CONST)
158 obstack_1grow(&obst, 'K');
160 /* handle MS extended qualifiers? */
163 static void mangle_type(type_t *orig_type)
165 type_t *type = skip_typeref(orig_type);
167 mangle_qualifiers(type->base.qualifiers);
169 switch (type->kind) {
171 mangle_atomic_type(&type->atomic);
174 mangle_pointer_type(&type->pointer);
177 mangle_reference_type(&type->reference);
180 mangle_function_type(&type->function);
182 case TYPE_COMPOUND_STRUCT:
183 case TYPE_COMPOUND_UNION:
184 mangle_class_type(&type->compound);
187 mangle_enum_type(&type->enumt);
190 mangle_array_type(&type->array);
193 mangle_complex_type(&type->atomic);
196 mangle_imaginary_type(&type->atomic);
199 panic("error type encountered while mangling");
202 panic("typeref not resolved while manging?!?");
204 panic("invalid type encountered while mangling");
207 static void mangle_namespace(entity_t *entity)
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) {
214 print_name(e->base.symbol->string);
220 static void mangle_entity(entity_t *entity)
222 obstack_1grow(&obst, '_');
223 obstack_1grow(&obst, 'Z');
225 if (entity->base.parent_entity != NULL) {
226 obstack_1grow(&obst, 'N');
227 mangle_namespace(entity);
230 print_name(entity->base.symbol->string);
232 if (entity->kind == ENTITY_FUNCTION) {
233 mangle_parameters(&entity->declaration.type->function);
237 static ident *make_id_from_obst(void)
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);
247 * Mangles an entity linker (ld) name for win32 usage.
249 * @param ent the entity to be mangled
250 * @param declaration the declaration
252 ident *create_name_win32(entity_t *entity)
254 struct obstack *o = &obst;
256 assert(is_declaration(entity));
258 if (entity->kind == ENTITY_FUNCTION) {
259 type_t *type = skip_typeref(entity->declaration.type);
260 assert(is_type_function(type));
262 if (entity->declaration.modifiers & DM_DLLIMPORT)
263 /* add prefix for imported symbols */
264 obstack_printf(o, "__imp_");
266 cc_kind_t cc = type->function.calling_convention;
268 /* calling convention prefix */
272 case CC_STDCALL: obstack_1grow(o, '_'); break;
273 case CC_FASTCALL: obstack_1grow(o, '@'); break;
274 default: panic("unhandled calling convention");
277 switch (type->function.linkage) {
279 obstack_printf(o, "%s", entity->base.symbol->string);
283 mangle_entity(entity);
287 /* calling convention suffix */
295 ir_type *irtype = get_ir_type(entity->declaration.type);
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));
300 obstack_printf(o, "@%u", size);
305 panic("unhandled calling convention");
308 obstack_printf(o, "_%s", entity->base.symbol->string);
311 return make_id_from_obst();
315 * Mangles an entity linker (ld) name for Linux ELF usage.
317 * @param ent the entity to be mangled
318 * @param declaration the declaration
320 ident *create_name_linux_elf(entity_t *entity)
322 const char *name = entity->base.symbol->string;
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) {
329 if (entity->function.actual_name != NULL)
330 name = entity->function.actual_name->string;
333 // TODO What about __REDIRECT/actual_name with mangling?
334 mangle_entity(entity);
335 return make_id_from_obst();
339 return new_id_from_str(name);
343 * Mangles an entity linker (ld) name for Mach-O usage.
345 * @param ent the entity to be mangled
346 * @param declaration the declaration
348 ident *create_name_macho(entity_t *entity)
350 if (entity->kind == ENTITY_FUNCTION) {
351 type_t *type = skip_typeref(entity->declaration.type);
352 assert(is_type_function(type));
354 switch (type->function.linkage) {
356 if (entity->function.actual_name != NULL)
357 return new_id_from_str(entity->function.actual_name->string);
362 obstack_printf(&obst, "_%s", entity->base.symbol->string);
363 return make_id_from_obst();
366 void init_mangle(void)
371 void exit_mangle(void)
373 obstack_free(&obst, NULL);