summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorMatthias Braun <matze@braunis.de>2017-02-13 06:45:27 +0100
committerMatthias Braun <matze@braunis.de>2017-02-13 09:02:11 +0100
commita8fa75ab9d4c00dc7ed0a112b317afccd8b6bfa2 (patch)
tree127fbb60eb9a7746d9fb006a92524b8a38d8c40a /src
parent44d7c29b3012cd5d8db0a82c446fcaff5949f7b3 (diff)
Unifying name mangling
No need to have an own mangling scheme for each target.
Diffstat (limited to 'src')
-rw-r--r--src/driver/predefs.c3
-rw-r--r--src/driver/target.c19
-rw-r--r--src/driver/target.h2
-rw-r--r--src/firm/ast2firm.c7
-rw-r--r--src/firm/ast2firm.h4
-rw-r--r--src/firm/mangle.c195
-rw-r--r--src/firm/mangle.h5
7 files changed, 77 insertions, 158 deletions
diff --git a/src/driver/predefs.c b/src/driver/predefs.c
index fb0dd82..12fc1b2 100644
--- a/src/driver/predefs.c
+++ b/src/driver/predefs.c
@@ -347,7 +347,8 @@ void add_predefined_macros(void)
add_define_int("__pic__", target.pic_mode);
}
- add_define("__USER_LABEL_PREFIX__", target.user_label_prefix, false);
+ char user_label_prefix_str[] = { target.user_label_prefix, '\0' };
+ add_define("__USER_LABEL_PREFIX__", user_label_prefix_str, false);
add_define("__REGISTER_PREFIX__", "", false);
/* TODO: GCC_HAVE_SYNC_COMPARE_AND_SWAP_XX */
diff --git a/src/driver/target.c b/src/driver/target.c
index d1c47b1..551664c 100644
--- a/src/driver/target.c
+++ b/src/driver/target.c
@@ -22,7 +22,6 @@
target_t target = {
.biggest_alignment = 16,
.pic_mode = -1,
- .user_label_prefix = "",
};
const char *multilib_directory_target_triple;
unsigned target_size_override;
@@ -95,10 +94,10 @@ void target_adjust_types_and_dialect(void)
static ident *compilerlib_name_mangle(ident *id, ir_type *mt)
{
(void)mt;
- char const *const prefix = target.user_label_prefix;
- if (*prefix == '\0')
+ char const prefix = target.user_label_prefix;
+ if (prefix == '\0')
return id; /* Shortcut for empty prefix */
- return new_id_fmt("%s%s", prefix, id);
+ return new_id_fmt("%c%s", prefix, id);
}
/** Add a target specific preprocessor define. */
@@ -135,7 +134,6 @@ static bool cond_is_little_endian(void)
static void init_generic_elf(void)
{
driver_default_exe_output = "a.out";
- set_create_ld_ident(create_name_elf);
target.object_format = OBJECT_FORMAT_ELF;
set_be_option("ia32-struct_in_reg=no");
}
@@ -312,8 +310,7 @@ bsd:
init_generic_elf();
} else if (strstart(os, "darwin")) {
driver_default_exe_output = "a.out";
- set_create_ld_ident(create_name_macho);
- target.user_label_prefix = "_";
+ target.user_label_prefix = '_';
target.object_format = OBJECT_FORMAT_MACH_O;
target.pic_mode = 2;
set_be_option("ia32-stackalign=4");
@@ -347,7 +344,6 @@ bsd:
ppdefc("WIN32", "1", cond_not_strict);
if (pointer_size == 8) {
set_be_option("amd64-x64abi=yes");
- set_create_ld_ident(create_name_win64);
ppdef( "_WIN64", "1");
ppdef( "__WIN64", "1");
ppdef( "__WIN64__", "1");
@@ -360,8 +356,7 @@ bsd:
dialect.pointer_sized_uint = ATOMIC_TYPE_ULONGLONG;
} else {
assert(pointer_size == 4);
- set_create_ld_ident(create_name_win32);
- target.user_label_prefix = "_";
+ target.user_label_prefix = '_';
dialect.pointer_sized_int = ATOMIC_TYPE_INT;
dialect.pointer_sized_uint = ATOMIC_TYPE_UINT;
dialect.support_fastcall_stdcall = true;
@@ -374,12 +369,10 @@ bsd:
ppdef("__midipix__", "1");
if (pointer_size == 8) {
set_be_option("amd64-x64abi=yes");
- set_create_ld_ident(create_name_win64);
ppdef("__NT64", "1");
} else {
assert(pointer_size == 4);
- set_create_ld_ident(create_name_win32);
- target.user_label_prefix = "_";
+ target.user_label_prefix = '_';
ppdef("__NT32", "1");
}
} else {
diff --git a/src/driver/target.h b/src/driver/target.h
index 526968e..989a206 100644
--- a/src/driver/target.h
+++ b/src/driver/target.h
@@ -37,7 +37,7 @@ typedef struct target_t {
*/
unsigned int modulo_shift;
float_int_conversion_overflow_style_t float_int_overflow;
- const char *user_label_prefix;
+ char user_label_prefix;
unsigned char biggest_alignment;
/** position independent code generation mode */
int pic_mode : 4;
diff --git a/src/firm/ast2firm.c b/src/firm/ast2firm.c
index a7a1912..1466beb 100644
--- a/src/firm/ast2firm.c
+++ b/src/firm/ast2firm.c
@@ -564,13 +564,6 @@ static const struct {
static ident *rts_idents[ARRAY_SIZE(rts_data)];
-static create_ld_ident_func create_ld_ident = create_name_elf;
-
-void set_create_ld_ident(ident *(*func)(entity_t*))
-{
- create_ld_ident = func;
-}
-
static bool declaration_is_definition(const entity_t *entity)
{
switch (entity->kind) {
diff --git a/src/firm/ast2firm.h b/src/firm/ast2firm.h
index 1a1f41f..ba11876 100644
--- a/src/firm/ast2firm.h
+++ b/src/firm/ast2firm.h
@@ -14,8 +14,4 @@ void translation_unit_to_firm(translation_unit_t *unit);
void exit_ast2firm(void);
-typedef ident* (*create_ld_ident_func)(entity_t *entity);
-
-void set_create_ld_ident(create_ld_ident_func func);
-
#endif
diff --git a/src/firm/mangle.c b/src/firm/mangle.c
index a65a002..0dd42a6 100644
--- a/src/firm/mangle.c
+++ b/src/firm/mangle.c
@@ -7,12 +7,13 @@
#include <libfirm/firm.h>
#include <string.h>
-#include "adt/panic.h"
#include "adt/obst.h"
+#include "adt/panic.h"
#include "ast/dialect.h"
#include "ast/entity_t.h"
#include "ast/symbol_t.h"
#include "ast/type_t.h"
+#include "driver/target.h"
static struct obstack obst;
@@ -206,9 +207,9 @@ static void mangle_type(type_t *orig_type)
panic("invalid type encountered while mangling");
}
-static void mangle_namespace(entity_t *entity)
+static void mangle_namespace(entity_t const *const entity)
{
- for (entity_t *e = entity->base.parent_entity; e != NULL;
+ for (entity_t const *e = entity->base.parent_entity; e != NULL;
e = e->base.parent_entity) {
/* TODO: we need something similar (or the same?) for classes */
if (e->kind == ENTITY_NAMESPACE) {
@@ -219,7 +220,7 @@ static void mangle_namespace(entity_t *entity)
}
}
-static void mangle_entity(entity_t *entity)
+static void mangle_cxx_entity(entity_t const *const entity)
{
obstack_1grow(&obst, '_');
obstack_1grow(&obst, 'Z');
@@ -236,159 +237,97 @@ static void mangle_entity(entity_t *entity)
}
}
-static ident *make_id_from_obst(void)
+static char get_cc_prefix(cc_kind_t const cc)
{
- size_t size = obstack_object_size(&obst);
- char *str = obstack_finish(&obst);
- ident *id = new_id_from_chars(str, size);
- obstack_free(&obst, str);
- return id;
+ /* calling convention prefix */
+ switch (cc) {
+ case CC_THISCALL:
+ case CC_DEFAULT:
+ case CC_CDECL: return 0;
+ case CC_STDCALL: return '_';
+ case CC_FASTCALL: return '@';
+ }
+ panic("unknown calling convention");
}
-ident *create_name_win64(entity_t *entity)
+ident *create_ld_ident(entity_t const *const entity)
{
- const char *name = entity->base.symbol->string;
+ assert(obstack_object_size(&obst) == 0);
+ /* Special case: No mangling if actual_name is set */
if (entity->kind == ENTITY_FUNCTION) {
-#ifndef NDEBUG
- type_t *type = skip_typeref(entity->declaration.type);
- assert(is_type_function(type));
- assert(type->function.linkage == LINKAGE_C &&
- "Only C name mangling is implemented");
-#endif
- if (entity->declaration.modifiers & DM_DLLIMPORT) {
- /* add prefix for imported symbols */
- obstack_printf(&obst, "__imp_%s",
- entity->function.actual_name->string);
- return make_id_from_obst();
- }
- if (entity->function.actual_name != NULL)
- name = entity->function.actual_name->string;
+ symbol_t *actual_name = entity->function.actual_name;
+ if (actual_name != NULL && entity->function.btk != BUILTIN_LIBC
+ && entity->function.btk != BUILTIN_LIBC_CHECK)
+ return new_id_from_str(actual_name->string);
}
- return new_id_from_str(name);
-
-}
-
-/**
- * Mangles an entity linker (ld) name for win32 usage.
- *
- * @param ent the entity to be mangled
- * @param declaration the declaration
- */
-ident *create_name_win32(entity_t *entity)
-{
- struct obstack *o = &obst;
-
- assert(is_declaration(entity));
+ if (target.user_label_prefix != 0)
+ obstack_1grow(&obst, target.user_label_prefix);
+ bool mangle_cxx;
+ unsigned size_suffix = ~0u;
if (entity->kind == ENTITY_FUNCTION) {
type_t *type = skip_typeref(entity->declaration.type);
assert(is_type_function(type));
if (entity->declaration.modifiers & DM_DLLIMPORT)
/* add prefix for imported symbols */
- obstack_printf(o, "__imp_");
-
- cc_kind_t cc = type->function.calling_convention;
+ obstack_printf(&obst, "__imp_");
- /* calling convention prefix */
- switch (cc) {
- case CC_DEFAULT:
- case CC_CDECL:
- case CC_STDCALL: obstack_1grow(o, '_'); break;
- case CC_FASTCALL: obstack_1grow(o, '@'); break;
- default: panic("unhandled calling convention");
- }
+ cc_kind_t const cc = type->function.calling_convention;
+ char const cc_prefix = get_cc_prefix(cc);
+ if (cc_prefix != 0)
+ obstack_1grow(&obst, cc_prefix);
switch (type->function.linkage) {
- case LINKAGE_C:
- obstack_printf(o, "%s", entity->base.symbol->string);
- break;
-
case LINKAGE_CXX:
- mangle_entity(entity);
- break;
+ mangle_cxx = true;
+ default:
+ mangle_cxx = false;
}
- /* calling convention suffix */
- switch (cc) {
- case CC_DEFAULT:
- case CC_CDECL:
- break;
-
- case CC_STDCALL:
- case CC_FASTCALL: {
- unsigned size = 0;
- for (function_parameter_t const* i = type->function.parameters; i; i = i->next) {
- size += get_ctype_size(i->type);
+ if (cc == CC_STDCALL || cc == CC_FASTCALL) {
+ size_suffix = 0;
+ for (function_parameter_t const* i = type->function.parameters;
+ i != NULL; i = i->next) {
+ size_suffix += get_ctype_size(i->type);
}
- obstack_printf(o, "@%u", size);
- break;
- }
-
- default:
- panic("unhandled calling convention");
}
} else {
- obstack_printf(o, "_%s", entity->base.symbol->string);
+ /* Mangle with C++ rules if it has a namespace */
+ mangle_cxx = entity->base.parent_entity != NULL
+ && entity->base.parent_entity->kind == ENTITY_NAMESPACE;
}
- return make_id_from_obst();
-}
-
-/**
- * Mangles an entity linker (ld) name for Linux ELF usage.
- *
- * @param ent the entity to be mangled
- * @param declaration the declaration
- */
-ident *create_name_elf(entity_t *entity)
-{
- const char *name = entity->base.symbol->string;
-
- if (entity->kind == ENTITY_FUNCTION) {
- type_t *type = skip_typeref(entity->declaration.type);
- assert(is_type_function(type));
- switch (type->function.linkage) {
- case LINKAGE_C:
- if (entity->function.actual_name != NULL)
- name = entity->function.actual_name->string;
- break;
- case LINKAGE_CXX:
- // TODO What about __REDIRECT/actual_name with mangling?
- mangle_entity(entity);
- return make_id_from_obst();
+ /* Shortcut: No mangling necessary */
+ if (mangle_cxx) {
+ mangle_cxx_entity(entity);
+ } else {
+ const char *name = entity->base.symbol->string;
+ if (entity->kind == ENTITY_FUNCTION
+ && (entity->function.btk == BUILTIN_LIBC
+ || entity->function.btk == BUILTIN_LIBC_CHECK)) {
+ symbol_t *actual_name = entity->function.actual_name;
+ assert(actual_name != NULL);
+ name = actual_name->string;
}
+ /* Shortcut: No mangling at all */
+ if (obstack_object_size(&obst) == 0 && size_suffix == 0)
+ return new_id_from_str(name);
+
+ size_t len = strlen(name);
+ obstack_grow(&obst, name, len);
+ if (size_suffix != ~0u)
+ obstack_printf(&obst, "@%u", size_suffix);
}
- return new_id_from_str(name);
-}
-
-/**
- * Mangles an entity linker (ld) name for Mach-O usage.
- *
- * @param ent the entity to be mangled
- * @param declaration the declaration
- */
-ident *create_name_macho(entity_t *entity)
-{
- const char *name;
- if (entity->kind == ENTITY_FUNCTION
- && entity->function.actual_name != NULL) {
- name = entity->function.actual_name->string;
- if (entity->function.btk == BUILTIN_LIBC ||
- entity->function.btk == BUILTIN_LIBC_CHECK)
- goto mangle;
- goto nomangle;
- }
-
- name = entity->base.symbol->string;
-mangle:
- obstack_printf(&obst, "_%s", name);
- return make_id_from_obst();
-nomangle:
- return new_id_from_str(name);
+ /* Create libfirm ident from string on obstack */
+ size_t size = obstack_object_size(&obst);
+ char *str = obstack_finish(&obst);
+ ident *id = new_id_from_chars(str, size);
+ obstack_free(&obst, str);
+ return id;
}
void init_mangle(void)
diff --git a/src/firm/mangle.h b/src/firm/mangle.h
index a2a606c..c585b89 100644
--- a/src/firm/mangle.h
+++ b/src/firm/mangle.h
@@ -9,10 +9,7 @@
#include "ast/entity.h"
-ident *create_name_elf(entity_t *entity);
-ident *create_name_macho(entity_t *entity);
-ident *create_name_win32(entity_t *entity);
-ident *create_name_win64(entity_t *entity);
+ident *create_ld_ident(entity_t const *entity);
void init_mangle(void);
void exit_mangle(void);