#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "jcf.h"
#include "tree.h"
#include "java-tree.h"
#include "obstack.h"
#include "toplev.h"
#include "obstack.h"
#include "ggc.h"
static void mangle_field_decl (tree);
static void mangle_method_decl (tree);
static void mangle_type (tree);
static void mangle_pointer_type (tree);
static void mangle_array_type (tree);
static int mangle_record_type (tree, int);
static int find_compression_pointer_match (tree);
static int find_compression_array_match (tree);
static int find_compression_record_match (tree, tree *);
static int find_compression_array_template_match (tree);
static void set_type_package_list (tree);
static int entry_match_pointer_p (tree, int);
static void emit_compression_string (int);
static void init_mangling (struct obstack *);
static tree finish_mangling (void);
static void compression_table_add (tree);
static void mangle_member_name (tree);
struct obstack *mangle_obstack;
#define MANGLE_RAW_STRING(S) \
obstack_grow (mangle_obstack, (S), sizeof (S)-1)
static GTY(()) tree atms;
tree
java_mangle_decl (struct obstack *obstack, tree decl)
{
init_mangling (obstack);
switch (TREE_CODE (decl))
{
case VAR_DECL:
mangle_field_decl (decl);
break;
case FUNCTION_DECL:
mangle_method_decl (decl);
break;
default:
internal_error ("can't mangle %s", tree_code_name [TREE_CODE (decl)]);
}
return finish_mangling ();
}
tree
java_mangle_class_field (struct obstack *obstack, tree type)
{
init_mangling (obstack);
mangle_record_type (type, 0);
MANGLE_RAW_STRING ("6class$");
obstack_1grow (mangle_obstack, 'E');
return finish_mangling ();
}
tree
java_mangle_vtable (struct obstack *obstack, tree type)
{
init_mangling (obstack);
MANGLE_RAW_STRING ("TV");
mangle_record_type (type, 0);
obstack_1grow (mangle_obstack, 'E');
return finish_mangling ();
}
static void
mangle_field_decl (tree decl)
{
mangle_record_type (DECL_CONTEXT (decl), 0);
mangle_member_name (DECL_NAME (decl));
obstack_1grow (mangle_obstack, 'E');
}
static void
mangle_method_decl (tree mdecl)
{
tree method_name = DECL_NAME (mdecl);
tree arglist;
mangle_record_type (DECL_CONTEXT (mdecl), 0);
if (ID_INIT_P (method_name))
obstack_grow (mangle_obstack, "C1", 2);
else
mangle_member_name (method_name);
obstack_1grow (mangle_obstack, 'E');
arglist = TYPE_ARG_TYPES (TREE_TYPE (mdecl));
if (TREE_CODE (TREE_TYPE (mdecl)) == METHOD_TYPE)
arglist = TREE_CHAIN (arglist);
if (arglist == end_params_node)
obstack_1grow (mangle_obstack, 'v');
else
{
tree arg;
for (arg = arglist; arg != end_params_node; arg = TREE_CHAIN (arg))
mangle_type (TREE_VALUE (arg));
}
}
static void
mangle_member_name (tree name)
{
append_gpp_mangled_name (IDENTIFIER_POINTER (name),
IDENTIFIER_LENGTH (name));
if (cxx_keyword_p (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)))
obstack_1grow (mangle_obstack, '$');
}
static void
mangle_type (tree type)
{
switch (TREE_CODE (type))
{
char code;
case BOOLEAN_TYPE: code = 'b'; goto primitive;
case CHAR_TYPE: code = 'w'; goto primitive;
case VOID_TYPE: code = 'v'; goto primitive;
case INTEGER_TYPE:
if (type == promoted_short_type_node)
type = short_type_node;
if (type == promoted_byte_type_node)
type = byte_type_node;
switch (TYPE_PRECISION (type))
{
case 8: code = 'c'; goto primitive;
case 16: code = 's'; goto primitive;
case 32: code = 'i'; goto primitive;
case 64: code = 'x'; goto primitive;
default: goto bad_type;
}
primitive:
obstack_1grow (mangle_obstack, code);
break;
case REAL_TYPE:
switch (TYPE_PRECISION (type))
{
case 32: code = 'f'; goto primitive;
case 64: code = 'd'; goto primitive;
default: goto bad_type;
}
case POINTER_TYPE:
if (TYPE_ARRAY_P (TREE_TYPE (type)))
mangle_array_type (type);
else
mangle_pointer_type (type);
break;
bad_type:
default:
abort ();
}
}
static GTY(()) tree compression_table;
static int compression_next;
static int
find_compression_pointer_match (tree type)
{
int i;
for (i = compression_next-1; i >= 0; i--)
if (entry_match_pointer_p (type, i))
return i;
return -1;
}
static int
find_compression_array_match (tree type)
{
return find_compression_pointer_match (type);
}
static int
find_compression_array_template_match (tree string)
{
int i;
for (i = 0; i < compression_next; i++)
if (TREE_VEC_ELT (compression_table, i) == string)
return i;
return -1;
}
static int
find_compression_record_match (tree type, tree *next_current)
{
int i, match = -1;
tree current, saved_current = NULL_TREE;
current = TYPE_PACKAGE_LIST (type);
for (i = 0; i < compression_next; i++)
{
tree compression_entry = TREE_VEC_ELT (compression_table, i);
if (current && compression_entry == TREE_PURPOSE (current))
{
match = i;
saved_current = current;
current = TREE_CHAIN (current);
}
else
while (i < compression_next
&& TREE_CODE (compression_entry) == IDENTIFIER_NODE
&& compression_entry != atms)
compression_entry = TREE_VEC_ELT (compression_table, ++i);
}
if (!next_current)
return match;
if (match >= 0)
*next_current = TREE_CHAIN (saved_current);
if (match < 0)
*next_current = TYPE_PACKAGE_LIST (type);
return match;
}
static int
mangle_record_type (tree type, int for_pointer)
{
tree current;
int match;
int nadded_p = 0;
int qualified;
qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type)));
#define ADD_N() \
do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
if (TREE_CODE (type) != RECORD_TYPE)
abort ();
if (!TYPE_PACKAGE_LIST (type))
set_type_package_list (type);
match = find_compression_record_match (type, ¤t);
if (match >= 0)
{
if (for_pointer && current)
ADD_N();
emit_compression_string (match);
}
while (current)
{
compression_table_add (TREE_PURPOSE (current));
if ((qualified || !for_pointer) && !nadded_p)
ADD_N();
append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current)),
IDENTIFIER_LENGTH (TREE_VALUE (current)));
current = TREE_CHAIN (current);
}
return nadded_p;
#undef ADD_N
}
static void
mangle_pointer_type (tree type)
{
int match;
tree pointer_type;
if ((match = find_compression_pointer_match (type)) >= 0)
{
emit_compression_string (match);
return;
}
pointer_type = type;
type = TREE_TYPE (type);
if (TREE_CODE (type) != RECORD_TYPE)
abort ();
obstack_1grow (mangle_obstack, 'P');
if (mangle_record_type (type, 1))
obstack_1grow (mangle_obstack, 'E');
compression_table_add (pointer_type);
}
static void
mangle_array_type (tree p_type)
{
tree type, elt_type;
int match;
type = TREE_TYPE (p_type);
if (!type)
abort ();
elt_type = TYPE_ARRAY_ELEMENT (type);
if (!atms)
{
atms = get_identifier ("6JArray");
}
if ((match = find_compression_array_match (p_type)) >= 0)
{
emit_compression_string (match);
return;
}
obstack_1grow (mangle_obstack, 'P');
if ((match = find_compression_record_match (type, NULL)) > 0)
{
emit_compression_string (match);
return;
}
if ((match = find_compression_array_template_match (atms)) > 0)
emit_compression_string (match);
else
{
obstack_grow (mangle_obstack,
IDENTIFIER_POINTER (atms), IDENTIFIER_LENGTH (atms));
compression_table_add (atms);
}
obstack_1grow (mangle_obstack, 'I');
mangle_type (elt_type);
obstack_1grow (mangle_obstack, 'E');
compression_table_add (type);
compression_table_add (p_type);
}
static void
emit_compression_string (int i)
{
i -= 1;
obstack_1grow (mangle_obstack, 'S');
if (i >= 0)
{
static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
unsigned HOST_WIDE_INT n;
unsigned HOST_WIDE_INT m=1;
for (n = i; n >= 36; n /= 36, m *=36);
while (m > 0)
{
int digit = i / m;
obstack_1grow (mangle_obstack, digits [digit]);
i -= digit * m;
m /= 36;
}
}
obstack_1grow (mangle_obstack, '_');
}
static int
entry_match_pointer_p (tree type, int i)
{
tree t = TREE_VEC_ELT (compression_table, i);
while (TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (t) == POINTER_TYPE)
{
t = TREE_TYPE (t);
type = TREE_TYPE (type);
}
return (TREE_CODE (type) == RECORD_TYPE
&& TREE_CODE (t) == RECORD_TYPE
&& t == type);
}
static void
set_type_package_list (tree type)
{
int i;
const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
char *ptr;
int qualifications;
tree list = NULL_TREE, elt;
for (ptr = (char *)type_string, qualifications = 0; *ptr; ptr++)
if (*ptr == '.')
qualifications += 1;
for (ptr = (char *)type_string, i = 0; i < qualifications; ptr++)
{
if (ptr [0] == '.')
{
char c;
tree identifier;
c = ptr [0];
ptr [0] = '\0';
identifier = get_identifier (type_string);
ptr [0] = c;
elt = build_tree_list (identifier, identifier);
TREE_CHAIN (elt) = list;
list = elt;
type_string = ptr+1;
i += 1;
}
}
elt = build_tree_list (type, get_identifier (type_string));
TREE_CHAIN (elt) = list;
list = elt;
TYPE_PACKAGE_LIST (type) = nreverse (list);
}
static void
compression_table_add (tree type)
{
if (compression_next == TREE_VEC_LENGTH (compression_table))
{
tree new = make_tree_vec (2*compression_next);
int i;
for (i = 0; i < compression_next; i++)
TREE_VEC_ELT (new, i) = TREE_VEC_ELT (compression_table, i);
compression_table = new;
}
TREE_VEC_ELT (compression_table, compression_next++) = type;
}
static void
init_mangling (struct obstack *obstack)
{
mangle_obstack = obstack;
if (!compression_table)
compression_table = make_tree_vec (10);
else
abort ();
obstack_grow (mangle_obstack, "_Z", 2);
}
static tree
finish_mangling (void)
{
tree result;
if (!compression_table)
abort ();
compression_table = NULL_TREE;
compression_next = 0;
obstack_1grow (mangle_obstack, '\0');
result = get_identifier (obstack_base (mangle_obstack));
obstack_free (mangle_obstack, obstack_base (mangle_obstack));
#if 0
printf ("// %s\n", IDENTIFIER_POINTER (result));
#endif
return result;
}
#include "gt-java-mangle.h"