/* Functions related to building classes and their related objects.
- Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1996, 97-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
#include "system.h"
#include "tree.h"
#include "rtl.h"
+#include "flags.h"
#include "java-tree.h"
#include "jcf.h"
#include "obstack.h"
#include "toplev.h"
+#include "output.h"
+#include "parse.h"
static tree mangle_class_field PROTO ((tree class));
tree
mangled_classname (prefix, type)
- char *prefix;
- tree type;
+ const char *prefix;
+ tree type;
{
tree ident = TYPE_NAME (type);
if (TREE_CODE (ident) != IDENTIFIER_NODE)
ident = DECL_NAME (ident);
- return identifier_subst (ident, prefix, '/', '_', "");
+ return identifier_subst (ident, prefix, '.', '_', "");
}
tree
unmangle_classname (name, name_length)
const char *name; int name_length;
{
- return ident_subst (name, name_length, "", '/', '.', "");
+ tree to_return = ident_subst (name, name_length, "", '/', '.', "");
+ if (to_return != get_identifier ((char *)name))
+ QUALIFIED_P (to_return) = 1;
+ return to_return;
}
tree
add_interface_do (basetype_vec, interface_class, i);
}
+#if 0
/* Return the address of a pointer to the first FUNCTION_DECL
in the list (*LIST) whose DECL_NAME is NAME. */
list = &TREE_CHAIN (*list);
return list;
}
+#endif
tree
build_java_method_type (fntype, this_class, access_flags)
buf_ptr = &buf[strlen (buf)];
while (--name_len >= 0)
{
- char c = *name_ptr++;
+ unsigned char c = *name_ptr++;
if (c & 0x80)
continue;
- if (!isalpha(c) && !isdigit(c))
+ if (!ISALPHA(c) && !ISDIGIT(c))
c = '_';
*buf_ptr++ = c;
if (buf_ptr >= buf + 50)
{
char *name;
char buffer[25];
+ if (flag_emit_class_files)
+ {
+ const char *prim_class_name;
+ tree prim_class;
+ if (type == char_type_node)
+ prim_class_name = "java.lang.Character";
+ else if (type == boolean_type_node)
+ prim_class_name = "java.lang.Boolean";
+ else if (type == byte_type_node)
+ prim_class_name = "java.lang.Byte";
+ else if (type == short_type_node)
+ prim_class_name = "java.lang.Short";
+ else if (type == int_type_node)
+ prim_class_name = "java.lang.Integer";
+ else if (type == long_type_node)
+ prim_class_name = "java.lang.Long";
+ else if (type == float_type_node)
+ prim_class_name = "java.lang.Float";
+ else if (type == double_type_node)
+ prim_class_name = "java.lang.Double";
+ else if (type == void_type_node)
+ prim_class_name = "java.lang.Void";
+ else
+ fatal ("internal error - bad type to build_class_ref");
+ prim_class = lookup_class (get_identifier (prim_class_name));
+ return build (COMPONENT_REF, NULL_TREE,
+ prim_class, TYPE_identifier_node);
+ }
decl_name = TYPE_NAME (type);
if (TREE_CODE (decl_name) == TYPE_DECL)
decl_name = DECL_NAME (decl_name);
if (resolved)
type = build_class_ref (type);
else
- type = build_utf8_ref (build_java_signature (type));
+ {
+ tree signature = build_java_signature (type);
+ type = build_utf8_ref (unmangle_classname
+ (IDENTIFIER_POINTER(signature),
+ IDENTIFIER_LENGTH(signature)));
+ }
PUSH_FIELD_VALUE (finit, "type", type);
flags = get_access_flags_from_decl (fdecl);
if (! resolved)
build_utf8_ref (DECL_CONSTRUCTOR_P (mdecl) ?
init_identifier_node
: DECL_NAME (mdecl)));
- PUSH_FIELD_VALUE (minit, "signature",
- build_utf8_ref (build_java_signature (TREE_TYPE (mdecl))));
+ {
+ tree signature = build_java_signature (TREE_TYPE (mdecl));
+ PUSH_FIELD_VALUE (minit, "signature",
+ (build_utf8_ref
+ (unmangle_classname
+ (IDENTIFIER_POINTER(signature),
+ IDENTIFIER_LENGTH(signature)))));
+ }
PUSH_FIELD_VALUE (minit, "accflags", build_int_2 (accflags, 0));
PUSH_FIELD_VALUE (minit, "ncode", code);
FINISH_RECORD_CONSTRUCTOR (minit);
for (method = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (type));
method != NULL_TREE; method = TREE_CHAIN (method))
{
- tree init = make_method_value (method, this_class_addr);
+ tree init;
+ if (METHOD_PRIVATE (method)
+ && (flag_inline_functions || optimize))
+ continue;
+ init = make_method_value (method, this_class_addr);
method_count++;
methods = tree_cons (NULL_TREE, init, methods);
}
START_RECORD_CONSTRUCTOR (temp, object_type_node);
#if 0
- PUSH_FIELD_VALUE (temp, "dtable", NULL_TREE);
+ PUSH_FIELD_VALUE (temp, "vtable", NULL_TREE);
#else
- PUSH_FIELD_VALUE (temp, "dtable",
+ PUSH_FIELD_VALUE (temp, "vtable",
build1 (ADDR_EXPR, dtable_ptr_type, class_dtable_decl));
#endif
PUSH_FIELD_VALUE (temp, "sync_info", null_pointer_node);
START_RECORD_CONSTRUCTOR (cons, class_type_node);
PUSH_SUPER_VALUE (cons, temp);
PUSH_FIELD_VALUE (cons, "next", null_pointer_node);
- PUSH_FIELD_VALUE (cons, "name",
- build_utf8_ref (build_internal_class_name (type)));
+ PUSH_FIELD_VALUE (cons, "name", build_utf8_ref (DECL_NAME (type_decl)));
PUSH_FIELD_VALUE (cons, "accflags",
build_int_2 (get_access_flags_from_decl (type_decl), 0));
- PUSH_FIELD_VALUE (cons, "superclass", super);
+ PUSH_FIELD_VALUE (cons, "superclass",
+ CLASS_INTERFACE (type_decl) ? null_pointer_node : super);
PUSH_FIELD_VALUE (cons, "constants", constant_pool_constructor);
PUSH_FIELD_VALUE (cons, "methods",
build1 (ADDR_EXPR, method_ptr_type_node, methods_decl));
PUSH_FIELD_VALUE (cons, "method_count", build_int_2 (method_count, 0));
- PUSH_FIELD_VALUE (cons, "dtable_method_count", TYPE_NVIRTUALS (type));
+ PUSH_FIELD_VALUE (cons, "vtable_method_count", TYPE_NVIRTUALS (type));
PUSH_FIELD_VALUE (cons, "fields",
fields_decl == NULL_TREE ? null_pointer_node
: build1 (ADDR_EXPR, field_ptr_type_node, fields_decl));
PUSH_FIELD_VALUE (cons, "field_count", build_int_2 (field_count, 0));
PUSH_FIELD_VALUE (cons, "static_field_count",
build_int_2 (static_field_count, 0));
- /* For now, we let Kaffe fill in the dtable. */
- PUSH_FIELD_VALUE (cons, "dtable",
+ PUSH_FIELD_VALUE (cons, "vtable",
dtable_decl == NULL_TREE ? null_pointer_node
: build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl));
PUSH_FIELD_VALUE (cons, "interfaces", interfaces);
rest_of_decl_compilation (decl, (char*) 0, 1, 0);
}
+void
+finish_class (cl)
+ tree cl;
+{
+ tree method;
+
+ /* Emit deferred inline methods. */
+ for ( method = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (current_class));
+ method != NULL_TREE; method = TREE_CHAIN (method))
+ {
+ if (! TREE_ASM_WRITTEN (method) && DECL_SAVED_INSNS (method) != 0)
+ {
+ /* It's a deferred inline method. Decide if we need to emit it. */
+ if (flag_keep_inline_functions
+ || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (method))
+ || ! METHOD_PRIVATE (method))
+ {
+ temporary_allocation ();
+ output_inline_function (method);
+ permanent_allocation (1);
+ }
+ }
+ }
+
+ make_class_data (current_class);
+ register_class ();
+ rest_of_decl_compilation (TYPE_NAME (current_class), (char*) 0, 1, 0);
+}
+
/* Return 2 if CLASS is compiled by this compilation job;
return 1 if CLASS can otherwise be assumed to be compiled;
return 0 if we cannot assume that CLASS is compiled.
DECL_SIZE (base_decl) = TYPE_SIZE (super_class);
}
+/* Handle the different manners we may have to lay out a super class. */
+
+static tree
+maybe_layout_super_class (super_class)
+ tree super_class;
+{
+ if (TREE_CODE (super_class) == RECORD_TYPE)
+ {
+ if (!CLASS_LOADED_P (super_class)
+ && CLASS_FROM_SOURCE_P (super_class))
+ safe_layout_class (super_class);
+ if (!CLASS_LOADED_P (super_class))
+ load_class (super_class, 1);
+ }
+ /* We might have to layout the class before its dependency on
+ the super class gets resolved by java_complete_class */
+ else if (TREE_CODE (super_class) == TREE_LIST)
+ {
+ tree name = TYPE_NAME (TREE_PURPOSE (super_class));
+ load_class (name, 1);
+ super_class = IDENTIFIER_CLASS_VALUE (name);
+ if (!super_class)
+ return NULL_TREE; /* FIXME, NULL_TREE not checked by caller. */
+ super_class = TREE_TYPE (super_class);
+ }
+ if (!TYPE_SIZE (super_class))
+ safe_layout_class (super_class);
+
+ return super_class;
+}
+
void
layout_class (this_class)
tree this_class;
{
tree super_class = CLASSTYPE_SUPER (this_class);
- tree handle_type = CLASS_TO_HANDLE_TYPE (this_class);
- tree method_decl, field;
- tree dtable_count;
- int i;
+ tree field;
if (super_class)
{
- /* Class seen in source are now complete and can be layed out.
- Once layed out, a class seen in the source has its
- CLASS_LOADED_P flag set */
- if (CLASS_FROM_SOURCE_P (super_class) && !CLASS_LOADED_P (super_class))
- safe_layout_class (super_class);
- if (! CLASS_LOADED_P (super_class))
- load_class (super_class, 1);
+ super_class = maybe_layout_super_class (super_class);
if (TREE_CODE (TYPE_SIZE (super_class)) == ERROR_MARK)
{
TYPE_SIZE (this_class) = error_mark_node;
return;
}
- dtable_count = TYPE_NVIRTUALS (super_class);
-
if (TYPE_SIZE (this_class) == NULL_TREE)
push_super_field (this_class, super_class);
}
- else
- {
- dtable_count = integer_zero_node;
- }
for (field = TYPE_FIELDS (this_class);
field != NULL_TREE; field = TREE_CHAIN (field))
}
layout_type (this_class);
+}
+
+void
+layout_class_methods (this_class)
+ tree this_class;
+{
+ tree method_decl, dtable_count;
+ tree super_class, handle_type;
+ if (TYPE_NVIRTUALS (this_class))
+ return;
+
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ super_class = CLASSTYPE_SUPER (this_class);
+ handle_type = CLASS_TO_HANDLE_TYPE (this_class);
+
+ if (super_class)
+ {
+ super_class = maybe_layout_super_class (super_class);
+ if (!TYPE_NVIRTUALS (super_class))
+ layout_class_methods (super_class);
+ dtable_count = TYPE_NVIRTUALS (super_class);
+ }
+ else
+ dtable_count = integer_zero_node;
+
TYPE_METHODS (handle_type) = nreverse (TYPE_METHODS (handle_type));
- for (method_decl = TYPE_METHODS (handle_type), i = 0;
- method_decl; method_decl = TREE_CHAIN (method_decl), i++)
+ for (method_decl = TYPE_METHODS (handle_type);
+ method_decl; method_decl = TREE_CHAIN (method_decl))
+ dtable_count = layout_class_method (this_class, super_class,
+ method_decl, dtable_count);
+
+ TYPE_NVIRTUALS (this_class) = dtable_count;
+
+#ifdef JAVA_USE_HANDLES
+ layout_type (handle_type);
+#endif
+ pop_obstacks ();
+}
+
+/* Lay METHOD_DECL out, returning a possibly new value of
+ DTABLE_COUNT. */
+
+tree
+layout_class_method (this_class, super_class, method_decl, dtable_count)
+ tree this_class, super_class, method_decl, dtable_count;
+{
+ char *ptr;
+ char *asm_name;
+ tree arg, arglist, t;
+ int method_name_needs_escapes = 0;
+ tree method_name = DECL_NAME (method_decl);
+ int method_name_is_wfl =
+ (TREE_CODE (method_name) == EXPR_WITH_FILE_LOCATION);
+ if (method_name_is_wfl)
+ method_name = java_get_real_method_name (method_decl);
+
+ if (method_name != init_identifier_node
+ && method_name != finit_identifier_node)
{
- char *ptr;
- char buf[8];
- char *asm_name;
- tree method_name = DECL_NAME (method_decl);
-#if 1
- /* Remove this once we no longer need old (Kaffe / JDK 1.0) mangling. */
- if (! flag_assume_compiled && METHOD_NATIVE (method_decl))
+ int encoded_len
+ = unicode_mangling_length (IDENTIFIER_POINTER (method_name),
+ IDENTIFIER_LENGTH (method_name));
+ if (encoded_len > 0)
{
- for (ptr = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
- *ptr; )
- {
- int ch = *ptr++;
- if (ch == '.')
- ch = '_';
- obstack_1grow (&temporary_obstack, (char) ch);
- }
- obstack_1grow (&temporary_obstack, (char) '_');
- if (method_name == init_identifier_node)
- obstack_grow (&temporary_obstack, "INIT", 4);
- else
- obstack_grow (&temporary_obstack,
- IDENTIFIER_POINTER (method_name),
- IDENTIFIER_LENGTH (method_name));
+ method_name_needs_escapes = 1;
+ emit_unicode_mangled_name (&temporary_obstack,
+ IDENTIFIER_POINTER (method_name),
+ IDENTIFIER_LENGTH (method_name));
}
else
-#endif
{
- int len; tree arg, arglist, t;
- int method_name_needs_escapes = 0;
- if (method_name != init_identifier_node
- && method_name != finit_identifier_node)
+ obstack_grow (&temporary_obstack,
+ IDENTIFIER_POINTER (method_name),
+ IDENTIFIER_LENGTH (method_name));
+ }
+ }
+
+ obstack_grow (&temporary_obstack, "__", 2);
+ if (method_name == finit_identifier_node)
+ obstack_grow (&temporary_obstack, "finit", 5);
+ append_gpp_mangled_type (&temporary_obstack, this_class);
+ TREE_PUBLIC (method_decl) = 1;
+
+ t = TREE_TYPE (method_decl);
+ arglist = TYPE_ARG_TYPES (t);
+ if (TREE_CODE (t) == METHOD_TYPE)
+ arglist = TREE_CHAIN (arglist);
+ for (arg = arglist; arg != end_params_node; )
+ {
+ tree a = arglist;
+ tree argtype = TREE_VALUE (arg);
+ int tindex = 1;
+ if (TREE_CODE (argtype) == POINTER_TYPE)
+ {
+ /* This is O(N**2). Do we care? Cfr gcc/cp/method.c. */
+ while (a != arg && argtype != TREE_VALUE (a))
+ a = TREE_CHAIN (a), tindex++;
+ }
+ else
+ a = arg;
+ if (a != arg)
+ {
+ char buf[12];
+ int nrepeats = 0;
+ do
{
- int encoded_len
- = unicode_mangling_length (IDENTIFIER_POINTER (method_name),
- IDENTIFIER_LENGTH (method_name));
- if (encoded_len > 0)
- {
- method_name_needs_escapes = 1;
- emit_unicode_mangled_name (&temporary_obstack,
- IDENTIFIER_POINTER (method_name),
- IDENTIFIER_LENGTH (method_name));
- }
- else
- {
- obstack_grow (&temporary_obstack,
- IDENTIFIER_POINTER (method_name),
- IDENTIFIER_LENGTH (method_name));
- }
+ arg = TREE_CHAIN (arg); nrepeats++;
}
-
- obstack_grow (&temporary_obstack, "__", 2);
- if (method_name == finit_identifier_node)
- obstack_grow (&temporary_obstack, "finit", 5);
- append_gpp_mangled_type (&temporary_obstack, this_class);
- TREE_PUBLIC (method_decl) = 1;
-
- t = TREE_TYPE (method_decl);
- arglist = TYPE_ARG_TYPES (t);
- if (TREE_CODE (t) == METHOD_TYPE)
- arglist = TREE_CHAIN (arglist);
- for (arg = arglist; arg != NULL_TREE; )
+ while (arg != end_params_node && argtype == TREE_VALUE (arg));
+ if (nrepeats > 1)
{
- tree a = arglist;
- tree argtype = TREE_VALUE (arg);
- int tindex = 1;
- if (TREE_CODE (argtype) == POINTER_TYPE)
- {
- /* This is O(N**2). Do we care? Cfr gcc/cp/method.c. */
- while (a != arg && argtype != TREE_VALUE (a))
- a = TREE_CHAIN (a), tindex++;
- }
- else
- a = arg;
- if (a != arg)
- {
- char buf[12];
- int nrepeats = 0;
- do
- {
- arg = TREE_CHAIN (arg); nrepeats++;
- }
- while (arg != NULL_TREE && argtype == TREE_VALUE (arg));
- if (nrepeats > 1)
- {
- obstack_1grow (&temporary_obstack, 'N');
- sprintf (buf, "%d", nrepeats);
- obstack_grow (&temporary_obstack, buf, strlen (buf));
- if (nrepeats > 9)
- obstack_1grow (&temporary_obstack, '_');
- }
- else
- obstack_1grow (&temporary_obstack, 'T');
- sprintf (buf, "%d", tindex);
- obstack_grow (&temporary_obstack, buf, strlen (buf));
- if (tindex > 9)
- obstack_1grow (&temporary_obstack, '_');
- }
- else
- {
- append_gpp_mangled_type (&temporary_obstack, argtype);
- arg = TREE_CHAIN (arg);
- }
+ obstack_1grow (&temporary_obstack, 'N');
+ sprintf (buf, "%d", nrepeats);
+ obstack_grow (&temporary_obstack, buf, strlen (buf));
+ if (nrepeats > 9)
+ obstack_1grow (&temporary_obstack, '_');
}
- if (method_name_needs_escapes)
- obstack_1grow (&temporary_obstack, 'U');
+ else
+ obstack_1grow (&temporary_obstack, 'T');
+ sprintf (buf, "%d", tindex);
+ obstack_grow (&temporary_obstack, buf, strlen (buf));
+ if (tindex > 9)
+ obstack_1grow (&temporary_obstack, '_');
}
- obstack_1grow (&temporary_obstack, '\0');
- asm_name = obstack_finish (&temporary_obstack);
- DECL_ASSEMBLER_NAME (method_decl) = get_identifier (asm_name);
- if (! METHOD_ABSTRACT (method_decl))
- make_function_rtl (method_decl);
- obstack_free (&temporary_obstack, asm_name);
-
- if (method_name == init_identifier_node)
+ else
{
- char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
- for (ptr = p; *ptr; )
- {
- if (*ptr++ == '.')
- p = ptr;
- }
- DECL_NAME (method_decl) = get_identifier (p);
- DECL_CONSTRUCTOR_P (method_decl) = 1;
+ append_gpp_mangled_type (&temporary_obstack, argtype);
+ arg = TREE_CHAIN (arg);
}
- else if (! METHOD_STATIC (method_decl) && !DECL_ARTIFICIAL (method_decl))
+ }
+ if (method_name_needs_escapes)
+ obstack_1grow (&temporary_obstack, 'U');
+
+ obstack_1grow (&temporary_obstack, '\0');
+ asm_name = obstack_finish (&temporary_obstack);
+ DECL_ASSEMBLER_NAME (method_decl) = get_identifier (asm_name);
+ if (! METHOD_ABSTRACT (method_decl))
+ make_function_rtl (method_decl);
+ obstack_free (&temporary_obstack, asm_name);
+
+ if (method_name == init_identifier_node)
+ {
+ char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
+ for (ptr = p; *ptr; )
{
- tree method_sig = build_java_argument_signature (TREE_TYPE (method_decl));
- tree super_method = lookup_argument_method (super_class, method_name,
+ if (*ptr++ == '.')
+ p = ptr;
+ }
+ if (method_name_is_wfl)
+ EXPR_WFL_NODE (DECL_NAME (method_decl)) = get_identifier (p);
+ else
+ DECL_NAME (method_decl) = get_identifier (p);
+ DECL_CONSTRUCTOR_P (method_decl) = 1;
+ build_java_argument_signature (TREE_TYPE (method_decl));
+ }
+ else if (! METHOD_STATIC (method_decl) && !DECL_ARTIFICIAL (method_decl))
+ {
+ tree method_sig =
+ build_java_argument_signature (TREE_TYPE (method_decl));
+ tree super_method = lookup_argument_method (super_class, method_name,
method_sig);
- if (super_method != NULL_TREE)
- {
- DECL_VINDEX (method_decl) = DECL_VINDEX (super_method);
- if (DECL_VINDEX (method_decl) == NULL_TREE)
- error_with_decl (method_decl,
- "non-static method '%s' overrides static method");
+ if (super_method != NULL_TREE)
+ {
+ DECL_VINDEX (method_decl) = DECL_VINDEX (super_method);
+ if (DECL_VINDEX (method_decl) == NULL_TREE &&
+ ! TREE_PRIVATE (method_decl))
+ error_with_decl (method_decl,
+ "non-static method '%s' overrides static method");
#if 0
- else if (TREE_TYPE (TREE_TYPE (method_decl))
- != TREE_TYPE (TREE_TYPE (super_method)))
- {
- error_with_decl (method_decl,
- "Method `%s' redefined with different return type");
- error_with_decl (super_method,
- "Overridden decl is here");
- }
-#endif
- }
- else if (! METHOD_FINAL (method_decl)
- && ! CLASS_FINAL (TYPE_NAME (this_class)))
+ else if (TREE_TYPE (TREE_TYPE (method_decl))
+ != TREE_TYPE (TREE_TYPE (super_method)))
{
- DECL_VINDEX (method_decl) = dtable_count;
- dtable_count = build_int_2 (1+TREE_INT_CST_LOW (dtable_count), 0);
+ error_with_decl (method_decl,
+ "Method `%s' redefined with different return type");
+ error_with_decl (super_method,
+ "Overridden decl is here");
}
+#endif
+ }
+ else if (! METHOD_FINAL (method_decl)
+ && ! METHOD_PRIVATE (method_decl)
+ && ! CLASS_FINAL (TYPE_NAME (this_class))
+ && dtable_count)
+ {
+ DECL_VINDEX (method_decl) = dtable_count;
+ dtable_count = build_int_2 (1+TREE_INT_CST_LOW (dtable_count), 0);
}
}
- TYPE_NVIRTUALS (this_class) = dtable_count;
-
-#ifdef JAVA_USE_HANDLES
- layout_type (handle_type);
-#endif
+ return dtable_count;
}
static tree registered_class = NULL_TREE;
extern tree get_file_function_name PROTO((int));
tree init_name = get_file_function_name ('I');
- tree init_type = build_function_type (void_type_node, NULL_TREE);
+ tree init_type = build_function_type (void_type_node, end_params_node);
tree init_decl;
tree t;
poplevel (1, 0, 1);
{
/* Force generation, even with -O3 or deeper. Gross hack. FIXME */
- extern int flag_inline_functions;
int saved_flag = flag_inline_functions;
flag_inline_functions = 0;
rest_of_compilation (init_decl);