#include <jit/jit-dynamic.h>
#include <jit/jit.h>
#include <config.h>
#include <stdio.h>
static char const hexchars[16] = "0123456789ABCDEF";
static char const b36chars[36] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
typedef struct jit_mangler *jit_mangler_t;
struct jit_mangler
{
char *buf;
unsigned int buf_len;
unsigned int buf_max;
int out_of_memory;
char **names;
unsigned int num_names;
unsigned int max_names;
};
static void init_mangler(jit_mangler_t mangler)
{
mangler->buf = 0;
mangler->buf_len = 0;
mangler->buf_max = 0;
mangler->out_of_memory = 0;
mangler->names = 0;
mangler->num_names = 0;
mangler->max_names = 0;
}
static char *end_mangler(jit_mangler_t mangler)
{
unsigned int index;
for(index = 0; index < mangler->num_names; ++index)
{
jit_free(mangler->names[index]);
}
jit_free(mangler->names);
if(!(mangler->buf) || mangler->out_of_memory)
{
jit_free(mangler->buf);
return 0;
}
return mangler->buf;
}
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;
}
static void add_string(jit_mangler_t mangler, const char *str)
{
while(*str != '\0')
{
add_ch(mangler, *str++);
}
}
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);
}
static int add_name(jit_mangler_t mangler, const char *name,
unsigned int name_len)
{
unsigned int index;
unsigned int len;
char **new_names;
for(index = 0; index < mangler->num_names; ++index)
{
len = jit_strlen(mangler->names[index]);
if(len == name_len && !jit_strncmp(name, mangler->names[index], len))
{
return (int)index;
}
}
if(mangler->num_names >= mangler->max_names)
{
if(mangler->out_of_memory)
{
return -1;
}
new_names = (char **)jit_realloc
(mangler->names, (mangler->num_names + 8));
if(!new_names)
{
mangler->out_of_memory = 1;
return -1;
}
mangler->names = new_names;
mangler->max_names += 8;
}
mangler->names[mangler->num_names] = jit_strndup(name, name_len);
if(!(mangler->names[mangler->num_names]))
{
mangler->out_of_memory = 1;
}
else
{
++(mangler->num_names);
}
return -1;
}
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;
}
}
static jit_type_t fix_system_types(jit_type_t type)
{
if(!type)
{
return 0;
}
switch(jit_type_get_kind(type))
{
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;
}
static int is_unsigned(jit_type_t type)
{
int kind = jit_type_get_kind(jit_type_remove_tags(type));
if(kind == JIT_TYPE_UBYTE ||
kind == JIT_TYPE_USHORT ||
kind == JIT_TYPE_UINT ||
kind == JIT_TYPE_NUINT ||
kind == JIT_TYPE_ULONG)
{
return 1;
}
return 0;
}
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);
#define GCC2_CTOR_PREFIX "__"
#define GCC2_DTOR_PREFIX "_._"
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');
}
}
static void mangle_name_gcc2(jit_mangler_t mangler, const char *name)
{
unsigned int len;
unsigned int posn;
unsigned int index;
unsigned int count;
char buf[32];
if(!name)
{
return;
}
len = jit_strlen(name);
count = 1;
for(posn = 0; posn < len; ++posn)
{
if(name[posn] == '.')
{
++count;
}
else if(name[posn] == ':')
{
if((posn + 1) < len && name[posn + 1] == ':')
{
++count;
++posn;
}
}
}
if(count > 9)
{
add_ch(mangler, 'Q');
add_ch(mangler, '_');
sprintf(buf, "%u", count);
add_string(mangler, buf);
add_ch(mangler, '_');
}
else if(count > 1)
{
add_ch(mangler, 'Q');
add_ch(mangler, (int)('0' + count));
}
posn = 0;
while(posn < len)
{
index = posn;
while(index < len)
{
if(name[index] == '.' || name[index] == ':')
{
break;
}
++index;
}
sprintf(buf, "%u", index - posn);
add_string(mangler, buf);
while(posn < index)
{
add_ch(mangler, name[posn++]);
}
if(posn < len && name[posn] == ':')
{
if((posn + 1) < len && name[posn + 1] == ':')
{
posn += 2;
}
else
{
++posn;
}
}
else if(posn < len && name[posn] == '.')
{
++posn;
}
}
}
static void mangle_type_gcc2(jit_mangler_t mangler, jit_type_t type)
{
int kind;
if(!type)
{
return;
}
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');
}
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;
}
}
kind = jit_type_get_kind(type);
if(kind >= JIT_TYPE_SBYTE && kind <= JIT_TYPE_ULONG)
{
type = fix_system_types(type);
}
switch(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:
{
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:
{
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:
case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_UNION_NAME:
case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_ENUM_NAME:
{
mangle_name_gcc2
(mangler, (const char *)jit_type_get_tagged_data(type));
}
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;
}
}
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');
}
}
static void mangle_substitution_gcc3(jit_mangler_t mangler, int name_index)
{
char buf[32];
unsigned int index;
add_ch(mangler, 'S');
if(name_index > 0)
{
--name_index;
index = sizeof(buf) - 1;
buf[index] = '\0';
while(name_index != 0)
{
buf[--index] = b36chars[name_index % 36];
name_index /= 36;
}
while(index == (sizeof(buf) - 1))
{
buf[--index] = '0';
}
add_string(mangler, buf + index);
}
add_ch(mangler, '_');
}
static void mangle_name_gcc3(jit_mangler_t mangler, const char *name,
const char *member_name)
{
unsigned int len;
unsigned int posn;
unsigned int index;
int name_index;
int name_index2;
char buf[32];
int multiple;
if(!name)
{
return;
}
len = jit_strlen(name);
name_index = add_name(mangler, name, len);
if(name_index != -1)
{
mangle_substitution_gcc3(mangler, name_index);
return;
}
multiple = (jit_strchr(name, '.') != 0 || jit_strchr(name, ':') != 0 ||
member_name != 0);
if(multiple)
{
add_ch(mangler, 'N');
}
posn = 0;
name_index = -1;
while(posn < len)
{
index = posn;
while(index < len)
{
if(name[index] == '.' || name[index] == ':')
{
break;
}
++index;
}
name_index2 = add_name(mangler, name, index);
if(name_index2 != -1)
{
name_index = name_index2;
posn = index;
}
else
{
if(name_index != -1)
{
mangle_substitution_gcc3(mangler, name_index);
name_index = -1;
}
sprintf(buf, "%u", index - posn);
add_string(mangler, buf);
while(posn < index)
{
add_ch(mangler, name[posn++]);
}
}
if(posn < len && name[posn] == ':')
{
if((posn + 1) < len && name[posn + 1] == ':')
{
posn += 2;
}
else
{
++posn;
}
}
else if(posn < len && name[posn] == '.')
{
++posn;
}
}
if(member_name)
{
add_len_string(mangler, member_name);
}
if(multiple)
{
add_ch(mangler, 'E');
}
}
static void mangle_type_gcc3(jit_mangler_t mangler, jit_type_t type)
{
int kind;
if(!type)
{
return;
}
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');
}
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;
}
}
kind = jit_type_get_kind(type);
if(kind >= JIT_TYPE_SBYTE && kind <= JIT_TYPE_ULONG)
{
type = fix_system_types(type);
}
switch(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:
{
jit_nuint size = jit_type_get_size(type);
if(is_unsigned(type))
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:
{
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:
case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_UNION_NAME:
case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_ENUM_NAME:
{
mangle_name_gcc3
(mangler, (const char *)jit_type_get_tagged_data(type), 0);
}
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)
static void mangle_type_msvc6(jit_mangler_t mangler, jit_type_t type);
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)
{
mangle_type_msvc6(mangler, jit_type_get_return(type));
}
else
{
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');
}
}
static void mangle_name_msvc6(jit_mangler_t mangler, const char *name)
{
unsigned int len;
unsigned int posn;
unsigned int index;
int name_index;
int output_at;
if(!name)
{
return;
}
len = jit_strlen(name);
while(len > 0)
{
posn = len - 1;
while(posn > 0 && name[posn] != '.' && name[posn] != ':')
{
--posn;
}
++posn;
name_index = add_name(mangler, name + posn, len - posn);
if(name_index == -1 || name_index > 9)
{
for(index = posn; index < len; ++index)
{
add_ch(mangler, name[index]);
}
output_at = 1;
}
else
{
add_ch(mangler, '0' + name_index);
output_at = 0;
}
if(posn > 0 && name[posn - 1] == ':')
{
--posn;
if(posn > 0 && name[posn - 1] == ':')
{
--posn;
}
}
else if(posn > 0 && name[posn - 1] == '.')
{
--posn;
}
len = posn;
if(len > 0 && output_at)
{
add_ch(mangler, '@');
}
}
}
static void mangle_type_msvc6(jit_mangler_t mangler, jit_type_t type)
{
int kind;
jit_type_t sub_type;
if(!type)
{
return;
}
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;
}
}
kind = jit_type_get_kind(type);
if(kind >= JIT_TYPE_SBYTE && kind <= JIT_TYPE_ULONG)
{
type = fix_system_types(type);
}
switch(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:
{
}
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:
{
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:
{
add_ch(mangler, 'V');
mangle_name_msvc6
(mangler, (const char *)jit_type_get_tagged_data(type));
add_string(mangler, "@@");
}
break;
case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_STRUCT_NAME:
{
add_ch(mangler, 'U');
mangle_name_msvc6
(mangler, (const char *)jit_type_get_tagged_data(type));
add_string(mangler, "@@");
}
break;
case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_UNION_NAME:
{
add_ch(mangler, 'T');
mangle_name_msvc6
(mangler, (const char *)jit_type_get_tagged_data(type));
add_string(mangler, "@@");
}
break;
case JIT_TYPE_FIRST_TAGGED + JIT_TYPETAG_ENUM_NAME:
{
add_ch(mangler, 'W');
add_ch(mangler, (int)('0' + jit_type_get_size(type)));
mangle_name_msvc6
(mangler, (const char *)jit_type_get_tagged_data(type));
add_string(mangler, "@@");
}
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:
{
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
#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
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);
}
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:
{
if((flags & JIT_MANGLE_IS_CTOR) != 0)
{
add_string(&mangler, GCC2_CTOR_PREFIX);
mangle_name_gcc2(&mangler, class_name);
mangle_signature_gcc2(&mangler, signature);
}
else if((flags & JIT_MANGLE_IS_DTOR) != 0)
{
add_string(&mangler, GCC2_DTOR_PREFIX);
mangle_name_gcc2(&mangler, class_name);
}
else
{
add_string(&mangler, name);
add_string(&mangler, "__");
mangle_signature_gcc2(&mangler, signature);
}
}
break;
#endif
#ifdef MANGLING_FORM_GCC_3
case MANGLING_FORM_GCC_3:
{
if((flags & JIT_MANGLE_IS_CTOR) != 0)
{
add_string(&mangler, "_Z");
if((flags & JIT_MANGLE_BASE) != 0)
{
mangle_name_gcc3(&mangler, class_name, "C2");
}
else
{
mangle_name_gcc3(&mangler, class_name, "C1");
}
mangle_signature_gcc3(&mangler, signature);
}
else if((flags & JIT_MANGLE_IS_DTOR) != 0)
{
add_string(&mangler, "_Z");
if((flags & JIT_MANGLE_BASE) != 0)
{
mangle_name_gcc3(&mangler, class_name, "D2");
}
else
{
mangle_name_gcc3(&mangler, class_name, "D1");
}
mangle_signature_gcc3(&mangler, signature);
}
else
{
add_string(&mangler, "_Z");
mangle_name_gcc3(&mangler, class_name, name);
mangle_signature_gcc3(&mangler, signature);
}
}
break;
#endif
#ifdef MANGLING_FORM_MSVC_6
case MANGLING_FORM_MSVC_6:
{
if((flags & JIT_MANGLE_IS_CTOR) != 0)
{
add_string(&mangler, "??0");
mangle_name_msvc6(&mangler, class_name);
}
else if((flags & JIT_MANGLE_IS_DTOR) != 0)
{
add_string(&mangler, "??1");
mangle_name_msvc6(&mangler, class_name);
}
else
{
add_ch(&mangler, '?');
add_string(&mangler, name);
add_ch(&mangler, '@');
mangle_name_msvc6(&mangler, class_name);
}
add_string(&mangler, "@@");
if((flags & 0x07) == JIT_MANGLE_PROTECTED)
{
if((flags & JIT_MANGLE_STATIC) != 0)
{
add_ch(&mangler, 'K');
}
else if((flags & JIT_MANGLE_VIRTUAL) != 0)
{
add_ch(&mangler, 'M');
}
else
{
add_ch(&mangler, 'I');
}
}
else if((flags & 0x07) == JIT_MANGLE_PRIVATE)
{
if((flags & JIT_MANGLE_STATIC) != 0)
{
add_ch(&mangler, 'C');
}
else if((flags & JIT_MANGLE_VIRTUAL) != 0)
{
add_ch(&mangler, 'E');
}
else
{
add_ch(&mangler, 'A');
}
}
else
{
if((flags & JIT_MANGLE_STATIC) != 0)
{
add_ch(&mangler, 'S');
}
else if((flags & JIT_MANGLE_VIRTUAL) != 0)
{
add_ch(&mangler, 'U');
}
else
{
add_ch(&mangler, 'Q');
}
}
if((flags & JIT_MANGLE_STATIC) == 0)
{
if((flags & JIT_MANGLE_CONST) != 0)
{
add_ch(&mangler, 'B');
}
else
{
add_ch(&mangler, 'A');
}
}
mangle_signature_msvc6
(&mangler, signature,
(flags & (JIT_MANGLE_IS_CTOR | JIT_MANGLE_IS_DTOR)) == 0,
(flags & JIT_MANGLE_STATIC) == 0,
(flags & JIT_MANGLE_EXPLICIT_THIS) != 0);
}
break;
#endif
}
return end_mangler(&mangler);
}