]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Continue the implementation of the C++ name mangling routines.
authorRhys Weatherley <rweather@southern-storm.com.au>
Mon, 3 May 2004 11:12:37 +0000 (11:12 +0000)
committerRhys Weatherley <rweather@southern-storm.com.au>
Mon, 3 May 2004 11:12:37 +0000 (11:12 +0000)
ChangeLog
doc/Makefile.am
doc/libjit.texi
doc/mangling_rules.txt [new file with mode: 0644]
include/jit/jit-type.h
include/jit/jit-util.h
jit/jit-mangle.c
jit/jit-type.c

index 05a2a0d7b2777f9bdfbe5d7b5df5ec027fae3b85..4d1035fd3eae81dfe0340b42be4544b833867acc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
        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:
index d24d152307408108615b32c617c4da94fb713a69..f536ef6bf40062aa6638bd42dc468426fab69465 100644 (file)
@@ -15,6 +15,7 @@ libjit_TEXINFOS = \
        $(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 \
@@ -60,6 +61,9 @@ $(srcdir)/libjitext-insn.texi: $(top_srcdir)/jit/jit-insn.c
 $(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 $< >$@
 
index 8fd4c35c49e081495a9f1045606132079c871764..47d7db5d32e646b17cc26e03152ea730de0dd328 100644 (file)
@@ -1003,6 +1003,7 @@ that it itself uses internally, but which may also be useful to front ends.
 @include libjitext-apply.texi
 @include libjitext-walk.texi
 @include libjitext-dynlib.texi
+@include libjitext-mangle.texi
 
 @c -----------------------------------------------------------------------
 
diff --git a/doc/mangling_rules.txt b/doc/mangling_rules.txt
new file mode 100644 (file)
index 0000000..b90bd62
--- /dev/null
@@ -0,0 +1,328 @@
+
+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
index d85aaad950c56960f930971a50e3a887f7aaff26..03ec5578255e3115f69fcb44a45872f5f74bb9c6 100644 (file)
@@ -71,26 +71,28 @@ extern jit_type_t const jit_type_sys_long_double;
  */
 #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.
index 167487d24b4afee7cad25f17cf7331b4f455dbf4..0a4427260ed1274014e1a233d0707229c2263d43 100644 (file)
@@ -89,6 +89,25 @@ void *jit_dynlib_get_symbol
 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
index ad19bccd0670e9060dfdab260ca6c636d7da5278..83e839e7869a88ae038d5e364f9ef6bc9bc8ac41 100644 (file)
@@ -24,7 +24,7 @@
 
 /*@
 
-@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
@@ -92,6 +92,7 @@ guess which system type you mean, but the guess will most likely be wrong.
  * Useful encoding characters.
  */
 static char const hexchars[16] = "0123456789ABCDEF";
+static char const b36chars[36] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
 /*
  * Name mangling output context.
@@ -103,6 +104,9 @@ struct jit_mangler
        unsigned int    buf_len;
        unsigned int    buf_max;
        int                             out_of_memory;
+       char              **names;
+       unsigned int    num_names;
+       unsigned int    max_names;
 };
 
 /*
@@ -114,6 +118,9 @@ static void init_mangler(jit_mangler_t mangler)
        mangler->buf_len = 0;
        mangler->buf_max = 0;
        mangler->out_of_memory = 0;
+       mangler->names = 0;
+       mangler->num_names = 0;
+       mangler->max_names = 0;
 }
 
 /*
@@ -121,6 +128,12 @@ static void init_mangler(jit_mangler_t mangler)
  */
 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);
@@ -176,6 +189,52 @@ static void add_len_string(jit_mangler_t mangler, const char *str)
        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.
  */
@@ -290,6 +349,12 @@ static int is_unsigned(jit_type_t type)
 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.
  */
@@ -312,6 +377,94 @@ static void mangle_signature_gcc2(jit_mangler_t mangler, jit_type_t type)
        }
 }
 
+/*
+ * 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.
  */
@@ -428,9 +581,12 @@ static void mangle_type_gcc2(jit_mangler_t mangler, jit_type_t type)
 
                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;
 
@@ -496,6 +652,128 @@ static void mangle_signature_gcc3(jit_mangler_t mangler, jit_type_t type)
        }
 }
 
+/*
+ * 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.
  */
@@ -611,9 +889,12 @@ static void mangle_type_gcc3(jit_mangler_t mangler, jit_type_t type)
 
                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;
 
@@ -727,6 +1008,63 @@ static void mangle_signature_msvc6(jit_mangler_t mangler, jit_type_t type,
        }
 }
 
+/*
+ * 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.
  */
@@ -831,10 +1169,39 @@ static void mangle_type_msvc6(jit_mangler_t mangler, jit_type_t 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:
                {
-                       /* 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;
 
@@ -980,17 +1347,6 @@ char *jit_mangle_global_function
        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}.
@@ -1014,13 +1370,11 @@ char *jit_mangle_global_function
  * @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
@@ -1039,6 +1393,11 @@ char *jit_mangle_global_function
  * @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
@@ -1057,7 +1416,23 @@ char *jit_mangle_member_function
        #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
@@ -1065,7 +1440,38 @@ char *jit_mangle_member_function
        #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
@@ -1073,7 +1479,94 @@ char *jit_mangle_member_function
        #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
index dba48822a31807035de593053f556214391ba771..f9c923a7d32af965753c5c6d04b02098a2b7fba1 100644 (file)
@@ -692,11 +692,15 @@ jit_type_t jit_type_create_pointer(jit_type_t type, int incref)
  * 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