2 * This file is part of cparser.
3 * Copyright (C) 2007-2008 Matthias Braun <matze@braunis.de>
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.
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.
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
22 #include <libfirm/firm.h>
29 #include "diagnostic.h"
31 #include "lang_features.h"
32 #include "adt/error.h"
34 static ident *id_underscore;
36 static symbol_t *sym_C;
37 static symbol_t *sym_stdcall;
38 static struct obstack obst;
40 static void mangle_type(type_t *type);
42 static const char *get_atomic_type_mangle(atomic_type_kind_t kind)
45 case ATOMIC_TYPE_INVALID: break;
46 case ATOMIC_TYPE_VOID: return "v";
47 case ATOMIC_TYPE_BOOL: return "b";
48 case ATOMIC_TYPE_CHAR: return "c";
49 case ATOMIC_TYPE_SCHAR: return "a";
50 case ATOMIC_TYPE_UCHAR: return "h";
51 case ATOMIC_TYPE_INT: return "i";
52 case ATOMIC_TYPE_UINT: return "j";
53 case ATOMIC_TYPE_SHORT: return "s";
54 case ATOMIC_TYPE_USHORT: return "t";
55 case ATOMIC_TYPE_LONG: return "l";
56 case ATOMIC_TYPE_ULONG: return "m";
57 case ATOMIC_TYPE_LONGLONG: return "x";
58 case ATOMIC_TYPE_ULONGLONG: return "y";
59 case ATOMIC_TYPE_LONG_DOUBLE: return "e";
60 case ATOMIC_TYPE_FLOAT: return "f";
61 case ATOMIC_TYPE_DOUBLE: return "d";
63 panic("invalid atomic type in mangler");
66 static void mangle_atomic_type(const atomic_type_t *type)
68 obstack_printf(&obst, "%s", get_atomic_type_mangle(type->akind));
71 static void mangle_pointer_type(const pointer_type_t *type)
73 obstack_printf(&obst, "P");
74 mangle_type(type->points_to);
77 static void mangle_function_type(const function_type_t *type)
79 obstack_printf(&obst, "F");
80 if (type->linkage == sym_C) {
81 obstack_printf(&obst, "Y");
84 mangle_type(type->return_type);
86 function_parameter_t *parameter = type->parameters;
87 for ( ; parameter != NULL; parameter = parameter->next) {
88 mangle_type(parameter->type);
91 obstack_printf(&obst, "z");
93 if (type->unspecified_parameters)
94 panic("can't mangle unspecified parameter types");
95 if (type->kr_style_parameters)
96 panic("can't mangle kr_style_parameters type");
98 obstack_printf(&obst, "E");
101 static void mangle_qualifiers(type_qualifiers_t qualifiers)
103 if (qualifiers & TYPE_QUALIFIER_CONST)
104 obstack_printf(&obst, "K");
105 if (qualifiers & TYPE_QUALIFIER_VOLATILE)
106 obstack_printf(&obst, "V");
107 if (qualifiers & TYPE_QUALIFIER_RESTRICT)
108 obstack_printf(&obst, "r");
110 /* handle MS extended qualifiers? */
113 static void mangle_type(type_t *orig_type)
115 type_t *type = skip_typeref(orig_type);
117 mangle_qualifiers(type->base.qualifiers);
119 switch (type->kind) {
121 mangle_atomic_type(&type->atomic);
124 mangle_pointer_type(&type->pointer);
127 mangle_function_type(&type->function);
130 panic("invalid type encountered while mangling");
132 panic("error type encountered while mangling");
136 panic("typeref not resolved while manging?!?");
141 case TYPE_COMPOUND_STRUCT:
142 case TYPE_COMPOUND_UNION:
145 panic("no mangling for this type implemented yet");
148 panic("invalid type encountered while mangling");
153 * Mangles an entity linker (ld) name for win32 usage.
155 * @param ent the entity to be mangled
156 * @param declaration the declaration
158 ident *create_name_win32(entity_t *entity)
160 ident *id = new_id_from_str(entity->base.symbol->string);
162 if (entity->kind == ENTITY_FUNCTION) {
163 if (entity->declaration.type->function.linkage == sym_stdcall) {
165 ir_type *irtype = get_ir_type(entity->declaration.type);
167 for (int i = get_method_n_params(irtype) - 1; i >= 0; --i) {
168 size += get_type_size_bytes(get_method_param_type(irtype, i));
171 snprintf(buf, sizeof(buf), "@%d", size);
172 return id_mangle3("_", id, buf);
175 /* always add an underscore in win32 */
176 id = id_mangle(id_underscore, id);
179 assert(is_declaration(entity));
180 decl_modifiers_t decl_modifiers = entity->declaration.modifiers;
181 if (decl_modifiers & DM_DLLIMPORT) {
182 /* add prefix for imported symbols */
183 id = id_mangle(id_imp, id);
188 static void mangle_entity(entity_t *entity)
190 assert(obstack_object_size(&obst) == 0);
191 obstack_printf(&obst, "_Z");
193 /* TODO: mangle scope */
195 symbol_t *symbol = entity->base.symbol;
196 obstack_printf(&obst, "%u%s", strlen(symbol->string), symbol->string);
198 if (entity->kind == ENTITY_FUNCTION) {
199 mangle_type(entity->declaration.type);
204 * Mangles an entity linker (ld) name for Linux ELF usage.
206 * @param ent the entity to be mangled
207 * @param declaration the declaration
209 ident *create_name_linux_elf(entity_t *entity)
211 bool needs_mangling = false;
213 if (entity->kind == ENTITY_FUNCTION && (c_mode & _CXX)) {
214 symbol_t *linkage = entity->declaration.type->function.linkage;
216 if (linkage == NULL) {
217 needs_mangling = true;
218 } else if (linkage != sym_C) {
219 errorf(&entity->base.source_position,
220 "Unknown linkage type \"%Y\" found\n", linkage);
224 if (needs_mangling) {
225 mangle_entity(entity);
226 obstack_1grow(&obst, '\0');
227 char *str = obstack_finish(&obst);
229 ident *id = new_id_from_str(str);
230 obstack_free(&obst, str);
235 return new_id_from_str(entity->base.symbol->string);
239 * Mangles an entity linker (ld) name for Mach-O usage.
241 * @param ent the entity to be mangled
242 * @param declaration the declaration
244 ident *create_name_macho(entity_t *entity)
246 ident *id = new_id_from_str(entity->base.symbol->string);
247 return id_mangle(id_underscore, id);
250 void init_mangle(void)
252 id_underscore = new_id_from_chars("_", 1);
253 id_imp = new_id_from_chars("__imp_", 6);
254 sym_C = symbol_table_insert("C");
255 sym_stdcall = symbol_table_insert("stdcall");
260 void exit_mangle(void)
262 obstack_free(&obst, NULL);