name mangler, to help with extracting C++ symbols from dynamic
shared libraries.
+ * doc/Makefile.am, doc/libjit.texi, doc/mangling_rules.txt,
+ include/jit/jit-type.h, include/jit/jit-util.h, jit/jit-mangle.c,
+ jit/jit-type.c: continue the implementation of the C++ name
+ mangling routines.
+
2004-05-01 Rhys Weatherley <rweather@southern-storm.com.au>
* jit/jit-apply-x86.c, jit/jit-rules-x86.c, tools/gen-apply.c:
$(srcdir)/libjitext-init.texi \
$(srcdir)/libjitext-insn.texi \
$(srcdir)/libjitext-intrinsic.texi \
+ $(srcdir)/libjitext-mangle.texi \
$(srcdir)/libjitext-memory.texi \
$(srcdir)/libjitext-meta.texi \
$(srcdir)/libjitext-reg-alloc.texi \
$(srcdir)/libjitext-intrinsic.texi: $(top_srcdir)/jit/jit-intrinsic.c
$(SHELL) $(srcdir)/extract-docs.sh $< >$@
+$(srcdir)/libjitext-mangle.texi: $(top_srcdir)/jit/jit-mangle.c
+ $(SHELL) $(srcdir)/extract-docs.sh $< >$@
+
$(srcdir)/libjitext-memory.texi: $(top_srcdir)/jit/jit-memory.c
$(SHELL) $(srcdir)/extract-docs.sh $< >$@
@include libjitext-apply.texi
@include libjitext-walk.texi
@include libjitext-dynlib.texi
+@include libjitext-mangle.texi
@c -----------------------------------------------------------------------
--- /dev/null
+
+GCC 2.95.3 name mangling grammar (intuited from gcc sources):
+------------------------------------------------------------
+
+<global-function> ::= <name> '__F' <func-params>
+
+<member-function> ::= <name> '__' <class-name> <func-params>
+
+<ctor-function> ::= '__' <class-name> <func-params>
+
+<dtor-function> ::= '_' <joiner> '_' <class-name> <func-params>
+
+<joiner> ::= '.' | '$' # system-dependent joiner
+
+<class-name> ::= <qualified-name>
+
+<qualified-name> ::= <component>
+ ::= 'Q' <digit> <component>+
+ ::= 'Q' '_' <digit>+ '_' <component>+
+
+<component> ::= <digit>+ <identifier> # length-prefixed name
+
+<overload-item> ::= 'R' <type> # reference
+ ::= 'P' <type> # array or pointer type
+ ::= 'O' <type> '_' <type> # offset type
+ ::= 'M' <type> <modifiers> <function-type> # methods
+ ::= <function-type>
+ ::= <builtin-type>
+ ::= <qualified-name>
+
+<type> ::= <modifiers> <overload-item>
+
+<function-type> ::= 'F' <func-params> '_' <return-type>
+
+<func-params> ::= 'e' # () parameters
+ ::= 'v' # (void) parameters
+ ::= <parameter>+
+ ::= <parameter>+ 'e' # ends in "..."
+
+<return-type> ::= <type>
+
+<modifiers> ::= [C] [U] [V] [u] # const, unsigned, volatile, restrict
+
+<builtin-type> ::= 'i' # int
+ ::= 'l' # long
+ ::= 's' # short
+ ::= 'Sc' # signed char
+ ::= 'c' # char
+ ::= 'w' # wchar/java-char
+ ::= 'x' # long long
+ ::= 'b' # bool
+ ::= 'r' # long double
+ ::= 'd' # double
+ ::= 'f' # float
+ ::= 'J' <type> # complex <type>
+ ::= 'v' # void
+ ::= 'I' <bit-size> # integer of <bit-size> bits
+
+<bit-size> ::= <hex> <hex> # sizes < 256
+ ::= _ <hex>+ _ # sizes >= 256
+
+<parameter> ::= <type>
+ ::= <repeat-count> <backref>
+
+<repeat-count> ::= 'T' # single repeat
+ ::= 'N' <digit> # repeats of 2..9
+ ::= 'N' <number> '_' # repeats of 10 or more
+ ::= 'n' <digit> # alt-style, repeats of 1..9
+ ::= 'n' <number> '_' # alt-style, repeats of 10+
+
+<backref> ::= <digit> # backrefs 0..9
+ ::= <number> '_' # backrefs of 10 or more
+
+GCC 3.2 name mangling grammar (extracted from gcc sources):
+----------------------------------------------------------
+
+<substitution> ::= St
+ # ::std
+
+ ::= Sa
+ # ::std::allocator
+
+ ::= Sb
+ # ::std::basic_string
+
+ ::= Ss
+ # ::std::basic_string<char,
+ ::std::char_traits<char>,
+ ::std::allocator<char> >
+
+ ::= Si
+ # ::std::basic_istream<char, ::std::char_traits<char> >
+
+ ::= So
+ # ::std::basic_ostream<char, ::std::char_traits<char> >
+
+ ::= Sd
+ # ::std::basic_iostream<char, ::std::char_traits<char> >
+
+ ::= S <seq-id> _ # base 36 sequence id
+ ::= S_
+
+<mangled-name> ::= _Z <encoding>
+
+<encoding> ::= <function name> <bare-function-type>
+ ::= <data name>
+
+<name> ::= <unscoped-name>
+ ::= <unscoped-template-name> <template-args>
+ ::= <nested-name>
+ ::= <local-name>
+
+ If IGNORE_LOCAL_SCOPE option to <name> is non-zero, this production of
+ <name> is called from <local-name>, which mangles the enclosing scope
+ elsewhere and then uses this function to mangle just the part
+ underneath the function scope. So don't use the <local-name>
+ production, to avoid an infinite recursion.
+
+<unscoped-name> ::= <unqualified-name>
+ ::= St <unqualified-name> # ::std::
+
+<unscoped-template-name> ::= <unscoped-name>
+ ::= <substitution>
+
+<nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
+ ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
+
+<CV-qualifiers> ::= [r] [V] [K]
+
+<prefix> ::= <prefix> <unqualified-name>>
+ ::= <template-prefix> <template-args>
+ ::= # empty
+ ::= <substitution>
+
+<template-prefix> ::= <prefix> <template component>
+ ::= <substitution>
+
+<unqualified-name> ::= <operator-name>
+ ::= <special-name>
+ ::= <source-name>
+
+<source-name> ::= </length/ number> <identifier>
+
+<number> ::= [n] </decimal integer/>
+
+<identifier> ::= </unqualified source code identifier>
+
+<special-name> ::= C1 # complete object constructor
+ ::= C2 # base object constructor
+ ::= C3 # complete object allocating constructor
+ ::= D0 # deleting (in-charge) destructor
+ ::= D1 # complete object (in-charge) destructor
+ ::= D2 # base object (not-in-charge) destructor
+ ::= CT <type> <offset number> _ <base type>
+ ::= Th <offset number> _ <base encoding>
+ ::= Tv <offset number> _ <vcall offset number> _
+ <base encoding>
+
+<discriminator> := _ <number>
+
+<local-name> := Z <function encoding> E <entity name> [<discriminator>]
+ := Z <function encoding> E s [<discriminator>]
+
+<type> ::= <builtin-type>
+ ::= <function-type>
+ ::= <class-enum-type>
+ ::= <array-type>
+ ::= <pointer-to-member-type>
+ ::= <template-param>
+ ::= <substitution>
+ ::= <CV-qualifier>
+ ::= P <type> # pointer-to
+ ::= R <type> # reference-to
+ ::= C <type> # complex pair (C 2000)
+ ::= G <type> # imaginary (C 2000) [not supported]
+ ::= U <source-name> <type> # vendor extended type qualifier
+
+<builtin-type> ::= v # void
+ ::= b # bool
+ ::= w # wchar_t
+ ::= c # char
+ ::= a # signed char
+ ::= h # unsigned char
+ ::= s # short
+ ::= t # unsigned short
+ ::= i # int
+ ::= j # unsigned int
+ ::= l # long
+ ::= m # unsigned long
+ ::= x # long long, __int64
+ ::= y # unsigned long long, __int64
+ ::= n # __int128
+ ::= o # unsigned __int128
+ ::= f # float
+ ::= d # double
+ ::= e # long double, __float80
+ ::= g # __float128 [not supported]
+ ::= u <source-name> # vendor extended type */
+
+<function-type> ::= F [Y] <bare-function-type> E
+
+<bare-function-type> ::= </signature/ type>+
+
+<class-enum-type> ::= <name>
+
+<template-args> ::= I <template-arg>+ E
+
+<expression> ::= <unary operator-name> <expression>
+ ::= <binary operator-name> <expression> <expression>
+ ::= <expr-primary>
+
+<expr-primary> ::= <template-param>
+ ::= L <type> <value number> E # literal
+ ::= L <mangled-name> E # external name
+
+<template-arg> ::= <type> # type
+ ::= L <type> </value/ number> E # literal
+ ::= LZ <name> E # external name
+ ::= X <expression> E # expression
+
+ Literal subcase of non-terminal <template-arg>.
+
+ "Literal arguments, e.g. "A<42L>", are encoded with their type
+ and value. Negative integer values are preceded with "n"; for
+ example, "A<-42L>" becomes "1AILln42EE". The bool value false is
+ encoded as 0, true as 1. If floating-point arguments are accepted
+ as an extension, their values should be encoded using a
+ fixed-length lowercase hexadecimal string corresponding to the
+ internal representation (IEEE on IA-64), high-order bytes first,
+ without leading zeroes. For example: "Lfbff000000E" is -1.0f."
+
+<template-template-arg> ::= <name>
+ ::= <substitution>
+
+<array-type> ::= A [</dimension/ number>] _ </element/ type>
+ ::= A <expression> _ </element/ type>
+
+ "Array types encode the dimension (number of elements) and the
+ element type. For variable length arrays, the dimension (but not
+ the '_' separator) is omitted."
+
+<pointer-to-member-type> ::= M </class/ type> </member/ type>
+
+<template-param> ::= T </parameter/ number> _
+
+<template-template-param> ::= <template-param>
+ ::= <substitution>
+
+MSVC 6.0 name mangling rules (determined by trial and error):
+------------------------------------------------------------
+
+<global-function> ::= '?' <name> '@@Y' <callconv> <return-type> <parameters>
+
+<member-function> ::= '?' <name> '@' <class-name> '@@' <access>
+ [<const>] <callconv> <return-type> <parameters>
+
+<ctor-function> ::= '??0' <class-name> '@@' <access> <const> <callconv>
+ '@' <parameters>
+
+<dtor-function> ::= '??1' <class-name> '@@' <access> <const> <callconv>
+ '@' <parameters>
+
+<access> ::= 'Q' # public instance
+ ::= 'I' # protected instance
+ ::= 'A' # private instance
+ ::= 'S' # public static
+ ::= 'K' # protected static
+ ::= 'C' # private static
+ ::= 'U' # public virtual
+ ::= 'M' # protected virtual
+ ::= 'E' # private virtual
+
+<callconv> ::= 'A' # cdecl
+ ::= 'E' # thiscall
+ ::= 'G' # stdcall
+ ::= 'I' # fastcall
+
+<const> ::= 'A' # non-const method (instance only)
+ ::= 'B' # const method (instance only)
+
+<return-type> ::= 'X' # void
+ ::= <type>
+
+<parameters> ::= 'XZ' # () or (void)
+ ::= <type>+ '@Z' # 1 or more parameters
+ ::= <type>+ 'ZZ' # 1 or more, followed by ...
+
+<func-ptr> ::= <callconv> <return-type> <parameters>
+
+<type> ::= <builtin-type>
+ ::= 'PA' <type> # pointer to <type>
+ ::= 'PB' <type> # const pointer to <type>
+ ::= 'PC' <type> # volatile pointer to <type>
+ ::= 'PD' <type> # const volatile pointer to <type>
+ ::= 'P6' <func-ptr> # function pointer type
+ ::= 'AA' <type> # reference to <type>
+ ::= 'AB' <type> # const reference to <type>
+ ::= 'AC' <type> # volatile reference to <type>
+ ::= 'AD' <type> # const volatile reference to <type>
+ ::= 'T' <name> '@@' # union name
+ ::= 'U' <name> '@@' # struct name
+ ::= 'V' <name> '@@' # class name
+ ::= 'W' <digit> <name> '@@' # enum of a given byte size
+ ::= <digit> # backref to identifier 'n' in name
+
+<builtin-type> ::= 'D' # char
+ ::= 'C' # signed char
+ ::= 'E' # unsigned char
+ ::= 'F' # short
+ ::= 'G' # unsigned short
+ ::= 'H' # int
+ ::= 'I' # unsigned int
+ ::= 'J' # long
+ ::= 'K' # unsigned long
+ ::= '_J' # __int64
+ ::= '_K' # unsigned __int64
+ ::= 'M' # float
+ ::= 'N' # double
+ ::= 'O' # long double
+
+<class-name> ::= <name>
+ ::= <identifier> '@' <name>
+ ::= <digit> <name>
+ # namespaces listed in reverse order
+ # i.e. "X::Y::Z" becomes "Z@Y@X".
+
+<name> ::= <identifier>
+ ::= <digit> # backref to identifier 'n' in name
*/
#define JIT_TYPETAG_NAME 10000
#define JIT_TYPETAG_STRUCT_NAME 10001
-#define JIT_TYPETAG_CONST 10002
-#define JIT_TYPETAG_VOLATILE 10003
-#define JIT_TYPETAG_REFERENCE 10004
-#define JIT_TYPETAG_OUTPUT 10005
-#define JIT_TYPETAG_RESTRICT 10006
-#define JIT_TYPETAG_SYS_BOOL 10007
-#define JIT_TYPETAG_SYS_CHAR 10008
-#define JIT_TYPETAG_SYS_SCHAR 10009
-#define JIT_TYPETAG_SYS_UCHAR 10010
-#define JIT_TYPETAG_SYS_SHORT 10011
-#define JIT_TYPETAG_SYS_USHORT 10012
-#define JIT_TYPETAG_SYS_INT 10013
-#define JIT_TYPETAG_SYS_UINT 10014
-#define JIT_TYPETAG_SYS_LONG 10015
-#define JIT_TYPETAG_SYS_ULONG 10016
-#define JIT_TYPETAG_SYS_LONGLONG 10017
-#define JIT_TYPETAG_SYS_ULONGLONG 10018
-#define JIT_TYPETAG_SYS_FLOAT 10019
-#define JIT_TYPETAG_SYS_DOUBLE 10020
-#define JIT_TYPETAG_SYS_LONGDOUBLE 10021
+#define JIT_TYPETAG_UNION_NAME 10002
+#define JIT_TYPETAG_ENUM_NAME 10003
+#define JIT_TYPETAG_CONST 10004
+#define JIT_TYPETAG_VOLATILE 10005
+#define JIT_TYPETAG_REFERENCE 10006
+#define JIT_TYPETAG_OUTPUT 10007
+#define JIT_TYPETAG_RESTRICT 10008
+#define JIT_TYPETAG_SYS_BOOL 10009
+#define JIT_TYPETAG_SYS_CHAR 10010
+#define JIT_TYPETAG_SYS_SCHAR 10011
+#define JIT_TYPETAG_SYS_UCHAR 10012
+#define JIT_TYPETAG_SYS_SHORT 10013
+#define JIT_TYPETAG_SYS_USHORT 10014
+#define JIT_TYPETAG_SYS_INT 10015
+#define JIT_TYPETAG_SYS_UINT 10016
+#define JIT_TYPETAG_SYS_LONG 10017
+#define JIT_TYPETAG_SYS_ULONG 10018
+#define JIT_TYPETAG_SYS_LONGLONG 10019
+#define JIT_TYPETAG_SYS_ULONGLONG 10020
+#define JIT_TYPETAG_SYS_FLOAT 10021
+#define JIT_TYPETAG_SYS_DOUBLE 10022
+#define JIT_TYPETAG_SYS_LONGDOUBLE 10023
/*
* ABI types for function signatures.
const char *jit_dynlib_get_suffix(void) JIT_NOTHROW;
void jit_dynlib_set_debug(int flag) JIT_NOTHROW;
+/*
+ * C++ name mangling definitions.
+ */
+#define JIT_MANGLE_PUBLIC 0x0001
+#define JIT_MANGLE_PROTECTED 0x0002
+#define JIT_MANGLE_PRIVATE 0x0003
+#define JIT_MANGLE_STATIC 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
+#define JIT_MANGLE_BASE 0x0200
+char *jit_mangle_global_function
+ (const char *name, jit_type_t signature, int form) JIT_NOTHROW;
+char *jit_mangle_member_function
+ (const char *class_name, const char *name,
+ jit_type_t signature, int form, int flags) JIT_NOTHROW;
+
#ifdef __cplusplus
};
#endif
/*@
-@cindex jit-mangle.h
+@cindex Name mangling
Sometimes you want to retrieve a C++ method from a dynamic library
using @code{jit_dynlib_get_symbol}. Unfortunately, C++ name mangling
* Useful encoding characters.
*/
static char const hexchars[16] = "0123456789ABCDEF";
+static char const b36chars[36] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
/*
* Name mangling output context.
unsigned int buf_len;
unsigned int buf_max;
int out_of_memory;
+ char **names;
+ unsigned int num_names;
+ unsigned int max_names;
};
/*
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);
add_string(mangler, str);
}
+/*
+ * Add a name to the name list in "mangler". Returns the index
+ * of a previous occurrence, or -1 if there was no previous version.
+ */
+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;
+}
+
/*
* Get a system integer type of a particular size.
*/
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);
+/*
+ * Special prefixes for gcc 2.x rules.
+ */
+#define GCC2_CTOR_PREFIX "__"
+#define GCC2_DTOR_PREFIX "_._" /* Could be "_$_" on some systems */
+
/*
* Mangle a function signature, using gcc 2.x rules.
*/
}
}
+/*
+ * Mangle a qualified name, using gcc 2.x rules.
+ */
+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];
+
+ /* Bail out if we don't have a name at all */
+ if(!name)
+ {
+ return;
+ }
+
+ /* Count the number of components */
+ 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;
+ }
+ }
+ }
+
+ /* Output the component count */
+ 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));
+ }
+
+ /* Output the components in the name */
+ 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;
+ }
+ }
+}
+
/*
* Mangle a type, using gcc 2.x rules.
*/
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:
{
/* Output the qualified name of the type */
- /* TODO */
+ mangle_name_gcc2
+ (mangler, (const char *)jit_type_get_tagged_data(type));
}
break;
}
}
+/*
+ * Mangle a substitution reference.
+ */
+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, '_');
+}
+
+/*
+ * Mangle a qualified name, using gcc 3.x rules.
+ */
+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)
+ {
+ /* We have a substitution for the whole name */
+ 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)
+ {
+ /* Extract the next component */
+ index = posn;
+ while(index < len)
+ {
+ if(name[index] == '.' || name[index] == ':')
+ {
+ break;
+ }
+ ++index;
+ }
+
+ /* Determine if we have a substitution for the current prefix */
+ 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++]);
+ }
+ }
+
+ /* Move on to the next component */
+ 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');
+ }
+}
+
/*
* Mangle a type, using gcc 3.x rules.
*/
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:
{
/* Output the qualified name of the type */
- /* TODO */
+ mangle_name_gcc3
+ (mangler, (const char *)jit_type_get_tagged_data(type), 0);
}
break;
}
}
+/*
+ * Mangle a qualified name, using MSVC 6.0 rules.
+ */
+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, '@');
+ }
+ }
+}
+
/*
* Mangle a type, using MSVC 6.0 rules.
*/
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:
{
- /* Output the qualified name of the type */
- /* TODO */
+ 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;
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}.
* @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.
+ * The method is a virtual instance method. If neither
+ * @code{JIT_MANGLE_STATIC} nor @code{JIT_MANGLE_VIRTUAL} are supplied,
+ * then the method is assumed to be a non-virtual instance method.
*
* @vindex JIT_MANGLE_CONST
* @item JIT_MANGLE_CONST
* @vindex JIT_MANGLE_IS_DTOR
* @item JIT_MANGLE_IS_DTOR
* The method is a destructor. The @code{name} parameter will be ignored.
+ *
+ * @vindex JIT_MANGLE_BASE
+ * @item JIT_MANGLE_BASE
+ * Fetch the "base" constructor or destructor entry point, rather than
+ * the "complete" entry point.
* @end table
*
* The @code{class_name} may include namespace and nested parent qualifiers
#ifdef MANGLING_FORM_GCC_2
case MANGLING_FORM_GCC_2:
{
- /* TODO */
+ 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:
{
- /* TODO */
+ 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:
{
- /* TODO */
+ 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)
+ {
+ /* static protected */
+ add_ch(&mangler, 'K');
+ }
+ else if((flags & JIT_MANGLE_VIRTUAL) != 0)
+ {
+ /* virtual protected */
+ add_ch(&mangler, 'M');
+ }
+ else
+ {
+ /* instance protected */
+ add_ch(&mangler, 'I');
+ }
+ }
+ else if((flags & 0x07) == JIT_MANGLE_PRIVATE)
+ {
+ if((flags & JIT_MANGLE_STATIC) != 0)
+ {
+ /* static private */
+ add_ch(&mangler, 'C');
+ }
+ else if((flags & JIT_MANGLE_VIRTUAL) != 0)
+ {
+ /* virtual private */
+ add_ch(&mangler, 'E');
+ }
+ else
+ {
+ /* instance private */
+ add_ch(&mangler, 'A');
+ }
+ }
+ else
+ {
+ if((flags & JIT_MANGLE_STATIC) != 0)
+ {
+ /* static public */
+ add_ch(&mangler, 'S');
+ }
+ else if((flags & JIT_MANGLE_VIRTUAL) != 0)
+ {
+ /* virtual public */
+ add_ch(&mangler, 'U');
+ }
+ else
+ {
+ /* instance public */
+ 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
* name to display for the type.
*
* @vindex JIT_TYPETAG_STRUCT_NAME
+ * @vindex JIT_TYPETAG_UNION_NAME
+ * @vindex JIT_TYPETAG_ENUM_NAME
* @item JIT_TYPETAG_STRUCT_NAME
+ * @itemx JIT_TYPETAG_UNION_NAME
+ * @itemx JIT_TYPETAG_ENUM_NAME
* The @code{data} pointer is a @code{char *} string indicating a friendly
- * name to display for a @code{struct} or @code{union} type. This is
- * for languages like C that have separate naming scopes for typedef's and
- * structures.
+ * name to display for a @code{struct}, @code{union}, or @code{enum} type.
+ * This is for languages like C that have separate naming scopes for
+ * typedef's and structures.
*
* @vindex JIT_TYPETAG_CONST
* @item JIT_TYPETAG_CONST