From c1539e6613c54165c30688764a2d52494419356b Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Mon, 3 May 2004 06:32:22 +0000 Subject: [PATCH] Add the beginnings of a C++ name mangler, to help with extracting C++ symbols from dynamic shared libraries. --- ChangeLog | 4 + jit/Makefile.am | 1 + jit/jit-mangle.c | 1082 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1087 insertions(+) create mode 100644 jit/jit-mangle.c diff --git a/ChangeLog b/ChangeLog index decc427..05a2a0d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,10 @@ types so that they can be distinguished from the fixed-sized types when it is necessary to do so. + * jit/Makefile.am, jit/jit-mangle.c: add the beginnings of a C++ + name mangler, to help with extracting C++ symbols from dynamic + shared libraries. + 2004-05-01 Rhys Weatherley * jit/jit-apply-x86.c, jit/jit-rules-x86.c, tools/gen-apply.c: diff --git a/jit/Makefile.am b/jit/Makefile.am index 1002134..f11f9d6 100644 --- a/jit/Makefile.am +++ b/jit/Makefile.am @@ -28,6 +28,7 @@ libjit_a_SOURCES = \ jit-interp.cpp \ jit-intrinsic.c \ jit-live.c \ + jit-mangle.c \ jit-memory.c \ jit-memory.h \ jit-meta.c \ diff --git a/jit/jit-mangle.c b/jit/jit-mangle.c new file mode 100644 index 0000000..ad19bcc --- /dev/null +++ b/jit/jit-mangle.c @@ -0,0 +1,1082 @@ +/* + * jit-mangle.c - Perform C++ name mangling. + * + * Copyright (C) 2004 Southern Storm Software, Pty Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "jit-internal.h" +#include +#include + +/*@ + +@cindex jit-mangle.h + +Sometimes you want to retrieve a C++ method from a dynamic library +using @code{jit_dynlib_get_symbol}. Unfortunately, C++ name mangling +rules differ from one system to another, making this process very +error-prone. + +The functions that follow try to help. They aren't necessarily fool-proof, +but they should work in the most common cases. The only alternative is +to wrap your C++ library with C functions, so that the names are predictable. + +The basic idea is that you supply a description of the C++ method that +you wish to access, and these functions return a number of candidate forms +that you can try with @code{jit_dynlib_get_symbol}. If one form fails, +you move on and try the next form, until either symbol lookup succeeds +or until all forms have been exhausted. + +@noindent +The following code demonstrates how to resolve a global function: + +@example +jit_dynlib_handle_t handle; +jit_type_t signature; +int form = 0; +void *address = 0; +char *mangled; + +while((mangled = jit_mangle_global_function + ("foo", signature, form)) != 0) +@{ + address = jit_dynlib_get_symbol(handle, mangled); + if(address != 0) + @{ + break; + @} + jit_free(mangled); + ++form; +@} + +if(address) +@{ + printf("%s = 0x%lx\n", mangled, (long)address); +@} +else +@{ + printf("could not resolve foo\n"); +@} +@end example + +This mechanism typically cannot be used to obtain the entry points for +@code{inline} methods. You will need to make other arrangements to +simulate the behaviour of inline methods, or recompile your dynamic C++ +library in a mode that explicitly exports inlines. + +C++ method names are very picky about types. On 32-bit systems, +@code{int} and @code{long} are the same size, but they are mangled +to different characters. To ensure that the correct function is +picked, you should use @code{jit_type_sys_int}, @code{jit_type_sys_long}, etc +instead of the platform independent types. If you do use a platform +independent type like @code{jit_type_int}, this library will try to +guess which system type you mean, but the guess will most likely be wrong. + +@*/ + +/* + * Useful encoding characters. + */ +static char const hexchars[16] = "0123456789ABCDEF"; + +/* + * Name mangling output context. + */ +typedef struct jit_mangler *jit_mangler_t; +struct jit_mangler +{ + char *buf; + unsigned int buf_len; + unsigned int buf_max; + int out_of_memory; +}; + +/* + * Initialize a mangling context. + */ +static void init_mangler(jit_mangler_t mangler) +{ + mangler->buf = 0; + mangler->buf_len = 0; + mangler->buf_max = 0; + mangler->out_of_memory = 0; +} + +/* + * End a mangling operation, and return the final string. + */ +static char *end_mangler(jit_mangler_t mangler) +{ + if(!(mangler->buf) || mangler->out_of_memory) + { + jit_free(mangler->buf); + return 0; + } + return mangler->buf; +} + +/* + * Add a character to a mangling buffer. + */ +static void add_ch(jit_mangler_t mangler, int ch) +{ + char *new_buf; + if(mangler->buf_len >= mangler->buf_max) + { + if(mangler->out_of_memory) + { + return; + } + new_buf = (char *)jit_realloc + (mangler->buf, mangler->buf_len + 32); + if(!new_buf) + { + mangler->out_of_memory = 1; + return; + } + mangler->buf = new_buf; + mangler->buf_max += 32; + } + mangler->buf[(mangler->buf_len)++] = (char)ch; +} + +/* + * Add a string to a mangling buffer. + */ +static void add_string(jit_mangler_t mangler, const char *str) +{ + while(*str != '\0') + { + add_ch(mangler, *str++); + } +} + +/* + * Add a length-prefixed string to a mangling buffer. + */ +static void add_len_string(jit_mangler_t mangler, const char *str) +{ + char buf[32]; + sprintf(buf, "%u", jit_strlen(str)); + add_string(mangler, buf); + add_string(mangler, str); +} + +/* + * Get a system integer type of a particular size. + */ +static jit_type_t get_system_type(jit_type_t type, int size, int is_signed) +{ + if(size == sizeof(int)) + { + if(is_signed) + return jit_type_sys_int; + else + return jit_type_sys_uint; + } + else if(size == sizeof(long)) + { + if(is_signed) + return jit_type_sys_long; + else + return jit_type_sys_ulong; + } + else if(size == sizeof(jit_long)) + { + if(is_signed) + return jit_type_sys_longlong; + else + return jit_type_sys_ulonglong; + } + else if(size == sizeof(short)) + { + if(is_signed) + return jit_type_sys_short; + else + return jit_type_sys_ushort; + } + else if(size == sizeof(char)) + { + #ifdef __CHAR_UNSIGNED__ + if(is_signed) + return jit_type_sys_schar; + else + return jit_type_sys_char; + #else + if(is_signed) + return jit_type_sys_char; + else + return jit_type_sys_uchar; + #endif + } + else + { + return type; + } +} + +/* + * Convert a fixed-sized integer type into a system-specific type. + */ +static jit_type_t fix_system_types(jit_type_t type) +{ + if(!type) + { + return 0; + } + switch(type->kind) + { + case JIT_TYPE_SBYTE: + return get_system_type(type, sizeof(jit_sbyte), 1); + case JIT_TYPE_UBYTE: + return get_system_type(type, sizeof(jit_ubyte), 0); + case JIT_TYPE_SHORT: + return get_system_type(type, sizeof(jit_short), 1); + case JIT_TYPE_USHORT: + return get_system_type(type, sizeof(jit_ushort), 0); + case JIT_TYPE_INT: + return get_system_type(type, sizeof(jit_int), 1); + case JIT_TYPE_UINT: + return get_system_type(type, sizeof(jit_uint), 0); + case JIT_TYPE_NINT: + return get_system_type(type, sizeof(jit_nint), 1); + case JIT_TYPE_NUINT: + return get_system_type(type, sizeof(jit_nuint), 0); + case JIT_TYPE_LONG: + return get_system_type(type, sizeof(jit_long), 1); + case JIT_TYPE_ULONG: + return get_system_type(type, sizeof(jit_long), 0); + } + return type; +} + +/* + * Determine if a type is an unsigned integer value. + */ +static int is_unsigned(jit_type_t type) +{ + type = jit_type_remove_tags(type); + if(type) + { + if(type->kind == JIT_TYPE_UBYTE || + type->kind == JIT_TYPE_USHORT || + type->kind == JIT_TYPE_UINT || + type->kind == JIT_TYPE_NUINT || + type->kind == JIT_TYPE_ULONG) + { + return 1; + } + } + return 0; +} + +/* + * Forward declarations. + */ +static void mangle_type_gcc2(jit_mangler_t mangler, jit_type_t type); +static void mangle_type_gcc3(jit_mangler_t mangler, jit_type_t type); + +/* + * Mangle a function signature, using gcc 2.x rules. + */ +static void mangle_signature_gcc2(jit_mangler_t mangler, jit_type_t type) +{ + unsigned int num_params; + unsigned int param; + num_params = jit_type_num_params(type); + if(num_params == 0 && jit_type_get_abi(type) != jit_abi_vararg) + { + add_ch(mangler, 'v'); + } + for(param = 0; param < num_params; ++param) + { + mangle_type_gcc2(mangler, jit_type_get_param(type, param)); + } + if(jit_type_get_abi(type) == jit_abi_vararg) + { + add_ch(mangler, 'e'); + } +} + +/* + * Mangle a type, using gcc 2.x rules. + */ +static void mangle_type_gcc2(jit_mangler_t mangler, jit_type_t type) +{ + int kind; + + /* Bail out if the type is invalid */ + if(!type) + { + return; + } + + /* Handle "const", "unsigned", "volatile", and "restrict" prefixes */ + if(jit_type_has_tag(type, JIT_TYPETAG_CONST)) + { + add_ch(mangler, 'C'); + } + if(is_unsigned(type) && !jit_type_has_tag(type, JIT_TYPETAG_SYS_CHAR)) + { + add_ch(mangler, 'U'); + } + if(jit_type_has_tag(type, JIT_TYPETAG_VOLATILE)) + { + add_ch(mangler, 'V'); + } + if(jit_type_has_tag(type, JIT_TYPETAG_RESTRICT)) + { + add_ch(mangler, 'u'); + } + + /* Strip the prefixes that we just output, together with tag kinds + that we don't handle specially ourselves */ + while(jit_type_is_tagged(type)) + { + kind = jit_type_get_tagged_kind(type); + if(kind == JIT_TYPETAG_CONST || + kind == JIT_TYPETAG_VOLATILE || + kind == JIT_TYPETAG_RESTRICT) + { + type = jit_type_get_tagged_type(type); + } + else if(kind < JIT_TYPETAG_NAME || + kind > JIT_TYPETAG_SYS_LONGDOUBLE) + { + type = jit_type_get_tagged_type(type); + } + else + { + break; + } + } + + /* Handle the inner-most part of the type */ + if(type->kind >= JIT_TYPE_SBYTE && type->kind <= JIT_TYPE_ULONG) + { + type = fix_system_types(type); + } + switch(type->kind) + { + case JIT_TYPE_VOID: add_ch(mangler, 'v'); break; + + case JIT_TYPE_SBYTE: + case JIT_TYPE_UBYTE: + case JIT_TYPE_SHORT: + case JIT_TYPE_USHORT: + case JIT_TYPE_INT: + case JIT_TYPE_UINT: + case JIT_TYPE_NINT: + case JIT_TYPE_NUINT: + case JIT_TYPE_LONG: + case JIT_TYPE_ULONG: + { + /* Will only happen if the primitive numeric type + does not correspond to one of the system types */ + jit_nuint size = jit_type_get_size(type); + add_ch(mangler, 'I'); + add_ch(mangler, hexchars[(size >> 4) & 0x0F]); + add_ch(mangler, hexchars[size & 0x0F]); + } + break; + + case JIT_TYPE_FLOAT32: add_ch(mangler, 'f'); break; + case JIT_TYPE_FLOAT64: add_ch(mangler, 'd'); break; + #ifdef JIT_NFLOAT_IS_DOUBLE + case JIT_TYPE_NFLOAT: add_ch(mangler, 'd'); break; + #else + case JIT_TYPE_NFLOAT: add_ch(mangler, 'r'); break; + #endif + + case JIT_TYPE_STRUCT: + case JIT_TYPE_UNION: + { + /* These should have been tagged with a name */ + add_ch(mangler, '?'); + } + break; + + case JIT_TYPE_SIGNATURE: + { + add_ch(mangler, 'F'); + mangle_signature_gcc2(mangler, type); + add_ch(mangler, '_'); + mangle_type_gcc2(mangler, jit_type_get_return(type)); + } + break; + + case JIT_TYPE_PTR: + { + add_ch(mangler, 'P'); + mangle_type_gcc2(mangler, jit_type_get_ref(type)); + } + break; + + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_NAME: + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_STRUCT_NAME: + { + /* Output the qualified name of the type */ + /* TODO */ + } + break; + + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_REFERENCE: + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_OUTPUT: + { + add_ch(mangler, 'R'); + mangle_type_gcc2 + (mangler, jit_type_get_ref(jit_type_remove_tags(type))); + } + break; + + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_BOOL: + add_ch(mangler, 'b'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_CHAR: + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_UCHAR: + add_ch(mangler, 'c'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_SCHAR: + add_ch(mangler, 'S'); + add_ch(mangler, 'c'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_SHORT: + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_USHORT: + add_ch(mangler, 's'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_INT: + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_UINT: + add_ch(mangler, 'i'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_LONG: + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_ULONG: + add_ch(mangler, 'l'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_LONGLONG: + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_ULONGLONG: + add_ch(mangler, 'x'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_FLOAT: + add_ch(mangler, 'f'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_DOUBLE: + add_ch(mangler, 'd'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_LONGDOUBLE: + add_ch(mangler, 'r'); break; + + default: break; + } +} + +/* + * Mangle a function signature, using gcc 3.x rules. + */ +static void mangle_signature_gcc3(jit_mangler_t mangler, jit_type_t type) +{ + unsigned int num_params; + unsigned int param; + num_params = jit_type_num_params(type); + if(num_params == 0 && jit_type_get_abi(type) != jit_abi_vararg) + { + add_ch(mangler, 'v'); + } + for(param = 0; param < num_params; ++param) + { + mangle_type_gcc3(mangler, jit_type_get_param(type, param)); + } + if(jit_type_get_abi(type) == jit_abi_vararg) + { + add_ch(mangler, 'z'); + } +} + +/* + * Mangle a type, using gcc 3.x rules. + */ +static void mangle_type_gcc3(jit_mangler_t mangler, jit_type_t type) +{ + int kind; + + /* Bail out if the type is invalid */ + if(!type) + { + return; + } + + /* Handle "const", "volatile", and "restrict" prefixes */ + if(jit_type_has_tag(type, JIT_TYPETAG_RESTRICT)) + { + add_ch(mangler, 'r'); + } + if(jit_type_has_tag(type, JIT_TYPETAG_VOLATILE)) + { + add_ch(mangler, 'V'); + } + if(jit_type_has_tag(type, JIT_TYPETAG_CONST)) + { + add_ch(mangler, 'K'); + } + + /* Strip the prefixes that we just output, together with tag kinds + that we don't handle specially ourselves */ + while(jit_type_is_tagged(type)) + { + kind = jit_type_get_tagged_kind(type); + if(kind == JIT_TYPETAG_CONST || + kind == JIT_TYPETAG_VOLATILE || + kind == JIT_TYPETAG_RESTRICT) + { + type = jit_type_get_tagged_type(type); + } + else if(kind < JIT_TYPETAG_NAME || + kind > JIT_TYPETAG_SYS_LONGDOUBLE) + { + type = jit_type_get_tagged_type(type); + } + else + { + break; + } + } + + /* Handle the inner-most part of the type */ + if(type->kind >= JIT_TYPE_SBYTE && type->kind <= JIT_TYPE_ULONG) + { + type = fix_system_types(type); + } + switch(type->kind) + { + case JIT_TYPE_VOID: add_ch(mangler, 'v'); break; + + case JIT_TYPE_SBYTE: + case JIT_TYPE_UBYTE: + case JIT_TYPE_SHORT: + case JIT_TYPE_USHORT: + case JIT_TYPE_INT: + case JIT_TYPE_UINT: + case JIT_TYPE_NINT: + case JIT_TYPE_NUINT: + case JIT_TYPE_LONG: + case JIT_TYPE_ULONG: + { + /* Will only happen if the primitive numeric type + does not correspond to one of the system types */ + jit_nuint size = jit_type_get_size(type); + if(is_unsigned) + add_string(mangler, "uU"); + else + add_string(mangler, "uI"); + add_ch(mangler, hexchars[(size >> 4) & 0x0F]); + add_ch(mangler, hexchars[size & 0x0F]); + } + break; + + case JIT_TYPE_FLOAT32: add_ch(mangler, 'f'); break; + case JIT_TYPE_FLOAT64: add_ch(mangler, 'd'); break; + #ifdef JIT_NFLOAT_IS_DOUBLE + case JIT_TYPE_NFLOAT: add_ch(mangler, 'd'); break; + #else + case JIT_TYPE_NFLOAT: add_ch(mangler, 'e'); break; + #endif + + case JIT_TYPE_STRUCT: + case JIT_TYPE_UNION: + { + /* These should have been tagged with a name */ + add_ch(mangler, '?'); + } + break; + + case JIT_TYPE_SIGNATURE: + { + add_ch(mangler, 'F'); + mangle_type_gcc3(mangler, jit_type_get_return(type)); + mangle_signature_gcc3(mangler, type); + add_ch(mangler, 'E'); + } + break; + + case JIT_TYPE_PTR: + { + add_ch(mangler, 'P'); + mangle_type_gcc3(mangler, jit_type_get_ref(type)); + } + break; + + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_NAME: + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_STRUCT_NAME: + { + /* Output the qualified name of the type */ + /* TODO */ + } + break; + + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_REFERENCE: + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_OUTPUT: + { + add_ch(mangler, 'R'); + mangle_type_gcc3 + (mangler, jit_type_get_ref(jit_type_remove_tags(type))); + } + break; + + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_BOOL: + add_ch(mangler, 'b'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_CHAR: + add_ch(mangler, 'c'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_SCHAR: + add_ch(mangler, 'a'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_UCHAR: + add_ch(mangler, 'h'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_SHORT: + add_ch(mangler, 's'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_USHORT: + add_ch(mangler, 't'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_INT: + add_ch(mangler, 'i'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_UINT: + add_ch(mangler, 'j'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_LONG: + add_ch(mangler, 'l'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_ULONG: + add_ch(mangler, 'm'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_LONGLONG: + add_ch(mangler, 'x'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_ULONGLONG: + add_ch(mangler, 'y'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_FLOAT: + add_ch(mangler, 'f'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_DOUBLE: + add_ch(mangler, 'd'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_LONGDOUBLE: + add_ch(mangler, 'e'); break; + + default: break; + } +} + +#if defined(JIT_WIN32_PLATFORM) + +/* + * Forward declaration. + */ +static void mangle_type_msvc6(jit_mangler_t mangler, jit_type_t type); + +/* + * Mangle a function signature, using MSVC 6.0 rules. + */ +static void mangle_signature_msvc6(jit_mangler_t mangler, jit_type_t type, + int output_return, int is_this_call, + int has_explicit_this) +{ + unsigned int num_params; + unsigned int param; + jit_abi_t abi = jit_type_get_abi(type); + if(is_this_call) + { + add_ch(mangler, 'E'); + } + else if(abi == jit_abi_stdcall) + { + add_ch(mangler, 'G'); + } + else if(abi == jit_abi_fastcall) + { + add_ch(mangler, 'I'); + } + else + { + add_ch(mangler, 'A'); + } + if(output_return) + { + /* Ordinary function with an explicit return type */ + mangle_type_msvc6(mangler, jit_type_get_return(type)); + } + else + { + /* Constructor or destructor, with no explicit return type */ + add_ch(mangler, '@'); + } + num_params = jit_type_num_params(type); + if(num_params == 0 && abi != jit_abi_vararg) + { + add_ch(mangler, 'X'); + add_ch(mangler, 'Z'); + return; + } + for(param = (has_explicit_this ? 1 : 0); param < num_params; ++param) + { + mangle_type_msvc6(mangler, jit_type_get_param(type, param)); + } + if(abi == jit_abi_vararg) + { + add_ch(mangler, 'Z'); + add_ch(mangler, 'Z'); + } + else + { + add_ch(mangler, '@'); + add_ch(mangler, 'Z'); + } +} + +/* + * Mangle a type, using MSVC 6.0 rules. + */ +static void mangle_type_msvc6(jit_mangler_t mangler, jit_type_t type) +{ + int kind; + jit_type_t sub_type; + + /* Bail out if the type is invalid */ + if(!type) + { + return; + } + + /* Strip tag kinds that we don't handle specially ourselves */ + while(jit_type_is_tagged(type)) + { + kind = jit_type_get_tagged_kind(type); + if(kind < JIT_TYPETAG_NAME || + kind > JIT_TYPETAG_SYS_LONGDOUBLE) + { + type = jit_type_get_tagged_type(type); + } + else + { + break; + } + } + + /* Handle the inner-most part of the type */ + if(type->kind >= JIT_TYPE_SBYTE && type->kind <= JIT_TYPE_ULONG) + { + type = fix_system_types(type); + } + switch(type->kind) + { + case JIT_TYPE_VOID: add_ch(mangler, 'X'); break; + + case JIT_TYPE_SBYTE: + case JIT_TYPE_UBYTE: + case JIT_TYPE_SHORT: + case JIT_TYPE_USHORT: + case JIT_TYPE_INT: + case JIT_TYPE_UINT: + case JIT_TYPE_NINT: + case JIT_TYPE_NUINT: + case JIT_TYPE_LONG: + case JIT_TYPE_ULONG: + { + /* Shouldn't happen, as "fix_system_types" resolved them above */ + } + break; + + case JIT_TYPE_FLOAT32: add_ch(mangler, 'M'); break; + case JIT_TYPE_FLOAT64: add_ch(mangler, 'N'); break; + #ifdef JIT_NFLOAT_IS_DOUBLE + case JIT_TYPE_NFLOAT: add_ch(mangler, 'N'); break; + #else + case JIT_TYPE_NFLOAT: add_ch(mangler, 'O'); break; + #endif + + case JIT_TYPE_STRUCT: + case JIT_TYPE_UNION: + { + /* These should have been tagged with a name */ + add_ch(mangler, '?'); + } + break; + + case JIT_TYPE_SIGNATURE: + { + add_string(mangler, "P6"); + mangle_signature_msvc6(mangler, type, 1, 0, 0); + } + break; + + case JIT_TYPE_PTR: + { + add_ch(mangler, 'P'); + sub_type = jit_type_get_ref(type); + if(jit_type_has_tag(sub_type, JIT_TYPETAG_CONST)) + { + if(jit_type_has_tag(sub_type, JIT_TYPETAG_VOLATILE)) + { + add_ch(mangler, 'D'); + } + else + { + add_ch(mangler, 'B'); + } + } + else if(jit_type_has_tag(sub_type, JIT_TYPETAG_VOLATILE)) + { + add_ch(mangler, 'C'); + } + else + { + add_ch(mangler, 'A'); + } + mangle_type_msvc6(mangler, sub_type); + } + break; + + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_NAME: + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_STRUCT_NAME: + { + /* Output the qualified name of the type */ + /* TODO */ + } + break; + + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_REFERENCE: + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_OUTPUT: + { + add_ch(mangler, 'A'); + sub_type = jit_type_get_ref(jit_type_remove_tags(type)); + if(jit_type_has_tag(sub_type, JIT_TYPETAG_CONST)) + { + if(jit_type_has_tag(sub_type, JIT_TYPETAG_VOLATILE)) + { + add_ch(mangler, 'D'); + } + else + { + add_ch(mangler, 'B'); + } + } + else if(jit_type_has_tag(sub_type, JIT_TYPETAG_VOLATILE)) + { + add_ch(mangler, 'C'); + } + else + { + add_ch(mangler, 'A'); + } + mangle_type_msvc6(mangler, sub_type); + } + break; + + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_CONST: + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_VOLATILE: + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_RESTRICT: + { + /* These are handled in the pointer and reference cases */ + mangle_type_msvc6(mangler, jit_type_get_tagged_type(type)); + } + break; + + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_BOOL: + add_ch(mangler, 'D'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_CHAR: + add_ch(mangler, 'D'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_SCHAR: + add_ch(mangler, 'C'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_UCHAR: + add_ch(mangler, 'E'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_SHORT: + add_ch(mangler, 'F'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_USHORT: + add_ch(mangler, 'G'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_INT: + add_ch(mangler, 'H'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_UINT: + add_ch(mangler, 'I'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_LONG: + add_ch(mangler, 'J'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_ULONG: + add_ch(mangler, 'K'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_LONGLONG: + add_string(mangler, "_J"); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_ULONGLONG: + add_string(mangler, "_K"); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_FLOAT: + add_ch(mangler, 'M'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_DOUBLE: + add_ch(mangler, 'N'); break; + case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_SYS_LONGDOUBLE: + add_ch(mangler, 'O'); break; + + default: break; + } +} + +#endif /* JIT_WIN32_PLATFORM */ + +/* + * Name mangling forms, in the order in which they should be tried. + * We try to arrange for the most likely to be tried first. + */ +#if defined(JIT_WIN32_PLATFORM) + #define MANGLING_FORM_MSVC_6 0 + #if defined(__GNUC__) && (__GNUC__ >= 3) + #define MANGLING_FORM_GCC_3 1 + #define MANGLING_FORM_GCC_2 2 + #else + #define MANGLING_FORM_GCC_2 1 + #define MANGLING_FORM_GCC_3 2 + #endif +#elif defined(__GNUC__) && (__GNUC__ >= 3) + #define MANGLING_FORM_GCC_3 0 + #define MANGLING_FORM_GCC_2 1 +#else + #define MANGLING_FORM_GCC_2 0 + #define MANGLING_FORM_GCC_3 1 +#endif + +/*@ + * @deftypefun {char *} jit_mangle_global_function ({const char *} name, jit_type_t signature, int form) + * Mangle the name of a global C++ function using the specified @code{form}. + * Returns NULL if out of memory, or if the form is not supported. + * @end deftypefun +@*/ +char *jit_mangle_global_function + (const char *name, jit_type_t signature, int form) +{ + struct jit_mangler mangler; + init_mangler(&mangler); + switch(form) + { + #ifdef MANGLING_FORM_GCC_2 + case MANGLING_FORM_GCC_2: + { + add_string(&mangler, name); + add_string(&mangler, "__F"); + mangle_signature_gcc2(&mangler, signature); + } + break; + #endif + + #ifdef MANGLING_FORM_GCC_3 + case MANGLING_FORM_GCC_3: + { + add_string(&mangler, "_Z"); + add_len_string(&mangler, name); + mangle_signature_gcc3(&mangler, signature); + } + break; + #endif + + #ifdef MANGLING_FORM_MSVC_6 + case MANGLING_FORM_MSVC_6: + { + add_ch(&mangler, '?'); + add_string(&mangler, name); + add_string(&mangler, "@@Y"); + mangle_signature_msvc6(&mangler, signature, 1, 0, 0); + } + break; + #endif + } + return end_mangler(&mangler); +} + +#define JIT_MANGLE_PUBLIC 0x0001 +#define JIT_MANGLE_PROTECTED 0x0002 +#define JIT_MANGLE_PRIVATE 0x0003 +#define JIT_MANGLE_STATIC 0x0000 +#define JIT_MANGLE_INSTANCE 0x0008 +#define JIT_MANGLE_VIRTUAL 0x0010 +#define JIT_MANGLE_CONST 0x0020 +#define JIT_MANGLE_EXPLICIT_THIS 0x0040 +#define JIT_MANGLE_IS_CTOR 0x0080 +#define JIT_MANGLE_IS_DTOR 0x0100 + +/*@ + * @deftypefun {char *} jit_mangle_member_function ({const char *} class_name, {const char *} name, jit_type_t signature, int form, int flags) + * Mangle the name of a C++ member function using the specified @code{form}. + * Returns NULL if out of memory, or if the form is not supported. + * The following flags may be specified to modify the mangling rules: + * + * @table @code + * @vindex JIT_MANGLE_PUBLIC + * @item JIT_MANGLE_PUBLIC + * The method has @code{public} access within its containing class. + * + * @vindex JIT_MANGLE_PROTECTED + * @item JIT_MANGLE_PROTECTED + * The method has @code{protected} access within its containing class. + * + * @vindex JIT_MANGLE_PRIVATE + * @item JIT_MANGLE_PRIVATE + * The method has @code{private} access within its containing class. + * + * @vindex JIT_MANGLE_STATIC + * @item JIT_MANGLE_STATIC + * The method is @code{static}. + * + * @vindex JIT_MANGLE_INSTANCE + * @item JIT_MANGLE_INSTANCE + * The method is a non-virtual instance method. + * + * @vindex JIT_MANGLE_VIRTUAL + * @item JIT_MANGLE_VIRTUAL + * The method is a virtual instance method. + * + * @vindex JIT_MANGLE_CONST + * @item JIT_MANGLE_CONST + * The method is an instance method with the @code{const} qualifier. + * + * @vindex JIT_MANGLE_EXPLICIT_THIS + * @item JIT_MANGLE_EXPLICIT_THIS + * The @code{signature} includes an extra pointer parameter at the start + * that indicates the type of the @code{this} pointer. This parameter won't + * be included in the final mangled name. + * + * @vindex JIT_MANGLE_IS_CTOR + * @item JIT_MANGLE_IS_CTOR + * The method is a constructor. The @code{name} parameter will be ignored. + * + * @vindex JIT_MANGLE_IS_DTOR + * @item JIT_MANGLE_IS_DTOR + * The method is a destructor. The @code{name} parameter will be ignored. + * @end table + * + * The @code{class_name} may include namespace and nested parent qualifiers + * by separating them with @code{::} or @code{.}. Class names that involve + * template parameters are not supported yet. + * @end deftypefun +@*/ +char *jit_mangle_member_function + (const char *class_name, const char *name, + jit_type_t signature, int form, int flags) +{ + struct jit_mangler mangler; + init_mangler(&mangler); + switch(form) + { + #ifdef MANGLING_FORM_GCC_2 + case MANGLING_FORM_GCC_2: + { + /* TODO */ + } + break; + #endif + + #ifdef MANGLING_FORM_GCC_3 + case MANGLING_FORM_GCC_3: + { + /* TODO */ + } + break; + #endif + + #ifdef MANGLING_FORM_MSVC_6 + case MANGLING_FORM_MSVC_6: + { + /* TODO */ + } + break; + #endif + } + return end_mangler(&mangler); +} -- 2.47.3