#include "stdio.h"
#include "target.h"
#include "except.h"
+#include "cgraph.h"
+#include "tree-iterator.h"
/* DOS brain-damage */
#ifndef O_BINARY
static tree get_dispatch_vector (tree);
static tree get_dispatch_table (tree, tree);
static int supers_all_compiled (tree type);
-static void add_interface_do (tree, tree, int);
static tree maybe_layout_super_class (tree, tree);
static void add_miranda_methods (tree, tree);
static int assume_compiled (const char *);
static tree build_symbol_entry (tree);
-
-static GTY(()) rtx registerClass_libfunc;
+static tree emit_assertion_table (tree);
struct obstack temporary_obstack;
int prefix_len = strlen (prefix);
int suffix_len = strlen (suffix);
int i = prefix_len + old_length + suffix_len + 1;
-#ifdef __GNUC__
- char buffer[i];
-#else
char *buffer = alloca (i);
-#endif
+
strcpy (buffer, prefix);
for (i = 0; i < old_length; i++)
{
{
tree type;
type = make_node (RECORD_TYPE);
- TYPE_BINFO (type) = make_tree_vec (BINFO_ELTS);
MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type);
return type;
return to_return;
}
+#define GEN_TABLE(TABLE, NAME, TABLE_TYPE, TYPE) \
+do \
+{ \
+ const char *typename = IDENTIFIER_POINTER (mangled_classname ("", TYPE)); \
+ char *buf = alloca (strlen (typename) + strlen (#NAME "_syms_") + 1); \
+ tree decl; \
+ \
+ sprintf (buf, #NAME "_%s", typename); \
+ TYPE_## TABLE ##_DECL (type) = decl = \
+ build_decl (VAR_DECL, get_identifier (buf), TABLE_TYPE); \
+ DECL_EXTERNAL (decl) = 1; \
+ TREE_STATIC (decl) = 1; \
+ TREE_READONLY (decl) = 1; \
+ TREE_CONSTANT (decl) = 1; \
+ DECL_IGNORED_P (decl) = 1; \
+ /* Mark the table as belonging to this class. */ \
+ pushdecl (decl); \
+ MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); \
+ DECL_OWNER (decl) = TYPE; \
+ sprintf (buf, #NAME "_syms_%s", typename); \
+ TYPE_## TABLE ##_SYMS_DECL (TYPE) = \
+ build_decl (VAR_DECL, get_identifier (buf), symbols_array_type); \
+ TREE_STATIC (TYPE_## TABLE ##_SYMS_DECL (TYPE)) = 1; \
+ TREE_CONSTANT (TYPE_## TABLE ##_SYMS_DECL (TYPE)) = 1; \
+ DECL_IGNORED_P (TYPE_## TABLE ##_SYMS_DECL (TYPE)) = 1; \
+ pushdecl (TYPE_## TABLE ##_SYMS_DECL (TYPE)); \
+} \
+while (0)
/* Given a class, create the DECLs for all its associated indirect
dispatch tables. */
if (flag_indirect_dispatch)
{
- {
- char *buf = alloca (strlen (typename) + strlen ("_otable_syms_") + 1);
-
- sprintf (buf, "_otable_%s", typename);
- TYPE_OTABLE_DECL (type) =
- build_decl (VAR_DECL, get_identifier (buf), otable_type);
- DECL_EXTERNAL (TYPE_OTABLE_DECL (type)) = 1;
- TREE_STATIC (TYPE_OTABLE_DECL (type)) = 1;
- TREE_READONLY (TYPE_OTABLE_DECL (type)) = 1;
- TREE_CONSTANT (TYPE_OTABLE_DECL (type)) = 1;
- DECL_IGNORED_P (TYPE_OTABLE_DECL (type)) = 1;
- pushdecl (TYPE_OTABLE_DECL (type));
- sprintf (buf, "_otable_syms_%s", typename);
- TYPE_OTABLE_SYMS_DECL (type) =
- build_decl (VAR_DECL, get_identifier (buf), symbols_array_type);
- TREE_STATIC (TYPE_OTABLE_SYMS_DECL (type)) = 1;
- TREE_CONSTANT (TYPE_OTABLE_SYMS_DECL (type)) = 1;
- DECL_IGNORED_P(TYPE_OTABLE_SYMS_DECL (type)) = 1;
- pushdecl (TYPE_OTABLE_SYMS_DECL (type));
- }
-
- {
- char *buf = alloca (strlen (typename) + strlen ("_atable_syms_") + 1);
- tree decl;
-
- sprintf (buf, "_atable_%s", typename);
- TYPE_ATABLE_DECL (type) = decl =
- build_decl (VAR_DECL, get_identifier (buf), atable_type);
- DECL_EXTERNAL (decl) = 1;
- TREE_STATIC (decl) = 1;
- TREE_READONLY (decl) = 1;
- TREE_CONSTANT (decl) = 1;
- DECL_IGNORED_P (decl) = 1;
- /* Mark the atable as belonging to this class. */
- pushdecl (decl);
- MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
- DECL_OWNER (decl) = type;
- sprintf (buf, "_atable_syms_%s", typename);
- TYPE_ATABLE_SYMS_DECL (type) =
- build_decl (VAR_DECL, get_identifier (buf), symbols_array_type);
- TREE_STATIC (TYPE_ATABLE_SYMS_DECL (type)) = 1;
- TREE_CONSTANT (TYPE_ATABLE_SYMS_DECL (type)) = 1;
- DECL_IGNORED_P (TYPE_ATABLE_SYMS_DECL (type)) = 1;
- pushdecl (TYPE_ATABLE_SYMS_DECL (type));
- }
+ GEN_TABLE (ATABLE, _atable, atable_type, type);
+ GEN_TABLE (OTABLE, _otable, otable_type, type);
+ GEN_TABLE (ITABLE, _itable, itable_type, type);
}
}
+#undef GEN_TABLE
+
tree
push_class (tree class_type, tree class_name)
{
tree decl, signature;
location_t saved_loc = input_location;
+#ifndef USE_MAPPED_LOCATION
tree source_name = identifier_subst (class_name, "", '.', '/', ".java");
- CLASS_P (class_type) = 1;
input_filename = IDENTIFIER_POINTER (source_name);
input_line = 0;
+#endif
+ CLASS_P (class_type) = 1;
decl = build_decl (TYPE_DECL, class_name, class_type);
/* dbxout needs a DECL_SIZE if in gstabs mode */
{
int total_supers = interfaces_count;
tree class_decl = TYPE_NAME (this_class);
+
if (super_class)
total_supers++;
+ TYPE_BINFO (this_class) = make_tree_binfo (total_supers);
TYPE_VFIELD (this_class) = TYPE_VFIELD (object_type_node);
- TYPE_BINFO_BASETYPES (this_class) = make_tree_vec (total_supers);
if (super_class)
{
- tree super_binfo = make_tree_vec (BINFO_ELTS);
+ tree super_binfo = make_tree_binfo (0);
BINFO_TYPE (super_binfo) = super_class;
BINFO_OFFSET (super_binfo) = integer_zero_node;
- TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (this_class)), 0)
- = super_binfo;
- CLASS_HAS_SUPER (this_class) = 1;
+ BINFO_BASE_APPEND (TYPE_BINFO (this_class), super_binfo);
+ CLASS_HAS_SUPER_FLAG (TYPE_BINFO (this_class)) = 1;
}
set_class_decl_access_flags (access_flags, class_decl);
while (clas != object_type_node)
{
depth++;
- clas = TYPE_BINFO_BASETYPE (clas, 0);
+ clas = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (clas), 0));
}
return depth;
}
int
interface_of_p (tree type1, tree type2)
{
- int n, i;
- tree basetype_vec;
+ int i;
+ tree binfo, base_binfo;
- if (!(basetype_vec = TYPE_BINFO_BASETYPES (type2)))
+ if (! TYPE_BINFO (type2))
return 0;
- n = TREE_VEC_LENGTH (basetype_vec);
- for (i = 0; i < n; i++)
- {
- tree vec_elt = TREE_VEC_ELT (basetype_vec, i);
- if (vec_elt && BINFO_TYPE (vec_elt) == type1)
- return 1;
- }
- for (i = 0; i < n; i++)
- {
- tree vec_elt = TREE_VEC_ELT (basetype_vec, i);
- if (vec_elt && BINFO_TYPE (vec_elt)
- && interface_of_p (type1, BINFO_TYPE (vec_elt)))
- return 1;
- }
+
+ for (binfo = TYPE_BINFO (type2), i = 0;
+ BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ if (BINFO_TYPE (base_binfo) == type1)
+ return 1;
+
+ for (binfo = TYPE_BINFO (type2), i = 0;
+ BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) /* */
+ if (BINFO_TYPE (base_binfo)
+ && interface_of_p (type1, BINFO_TYPE (base_binfo)))
+ return 1;
+
return 0;
}
return 0;
}
-/* Return 1 iff there exists a common enclosing context between TYPE1
- and TYPE2. */
+
+/* Return 1 iff TYPE1 and TYPE2 share a common enclosing class, regardless of
+ nesting level. */
int
common_enclosing_context_p (tree type1, tree type2)
{
+ while (type1)
+ {
+ tree current;
+ for (current = type2; current;
+ current = (INNER_CLASS_TYPE_P (current) ?
+ TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current))) :
+ NULL_TREE))
+ if (type1 == current)
+ return 1;
+
+ if (INNER_CLASS_TYPE_P (type1))
+ type1 = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type1)));
+ else
+ break;
+ }
+ return 0;
+}
+
+/* Return 1 iff there exists a common enclosing "this" between TYPE1
+ and TYPE2, without crossing any static context. */
+
+int
+common_enclosing_instance_p (tree type1, tree type2)
+{
if (!PURE_INNER_CLASS_TYPE_P (type1) || !PURE_INNER_CLASS_TYPE_P (type2))
return 0;
return 0;
}
-static void
-add_interface_do (tree basetype_vec, tree interface_class, int i)
-{
- tree interface_binfo = make_tree_vec (BINFO_ELTS);
- BINFO_TYPE (interface_binfo) = interface_class;
- BINFO_OFFSET (interface_binfo) = integer_zero_node;
- BINFO_VPTR_FIELD (interface_binfo) = integer_zero_node;
- TREE_VIA_VIRTUAL (interface_binfo) = 1;
- TREE_VEC_ELT (basetype_vec, i) = interface_binfo;
-}
-
/* Add INTERFACE_CLASS to THIS_CLASS iff INTERFACE_CLASS can't be
found in THIS_CLASS. Returns NULL_TREE upon success, INTERFACE_CLASS
if attempt is made to add it twice. */
tree
maybe_add_interface (tree this_class, tree interface_class)
{
- tree basetype_vec = TYPE_BINFO_BASETYPES (this_class);
+ tree binfo, base_binfo;
int i;
- int n = TREE_VEC_LENGTH (basetype_vec);
- for (i = 0; ; i++)
- {
- if (i >= n)
- {
- error ("internal error - too many interface type");
- return NULL_TREE;
- }
- else if (TREE_VEC_ELT (basetype_vec, i) == NULL_TREE)
- break;
- else if (BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i)) == interface_class)
- return interface_class;
- }
- add_interface_do (basetype_vec, interface_class, i);
+
+ for (binfo = TYPE_BINFO (this_class), i = 0;
+ BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ if (BINFO_TYPE (base_binfo) == interface_class)
+ return interface_class;
+ add_interface (this_class, interface_class);
return NULL_TREE;
}
void
add_interface (tree this_class, tree interface_class)
{
- tree basetype_vec = TYPE_BINFO_BASETYPES (this_class);
- int i;
- int n = TREE_VEC_LENGTH (basetype_vec);
- for (i = 0; ; i++)
- {
- if (i >= n)
- {
- error ("internal error - too many interface type");
- return;
- }
- else if (TREE_VEC_ELT (basetype_vec, i) == NULL_TREE)
- break;
- }
- add_interface_do (basetype_vec, interface_class, i);
+ tree interface_binfo = make_tree_binfo (0);
+
+ BINFO_TYPE (interface_binfo) = interface_class;
+ BINFO_OFFSET (interface_binfo) = integer_zero_node;
+ BINFO_VPTR_FIELD (interface_binfo) = integer_zero_node;
+ BINFO_VIRTUAL_P (interface_binfo) = 1;
+
+ BINFO_BASE_APPEND (TYPE_BINFO (this_class), interface_binfo);
}
#if 0
FINISH_RECORD (ctype);
START_RECORD_CONSTRUCTOR (cinit, ctype);
name_hash = hashUtf8String (name_ptr, name_len) & 0xFFFF;
- PUSH_FIELD_VALUE (cinit, "hash", build_int_2 (name_hash, 0));
- PUSH_FIELD_VALUE (cinit, "length", build_int_2 (name_len, 0));
+ PUSH_FIELD_VALUE (cinit, "hash", build_int_cst (NULL_TREE, name_hash));
+ PUSH_FIELD_VALUE (cinit, "length", build_int_cst (NULL_TREE, name_len));
string = build_string (name_len, name_ptr);
TREE_TYPE (string) = str_type;
PUSH_FIELD_VALUE (cinit, "data", string);
TREE_CHAIN (decl) = utf8_decl_list;
layout_decl (decl, 0);
pushdecl (decl);
- rest_of_decl_compilation (decl, (char*) 0, global_bindings_p (), 0);
+ rest_of_decl_compilation (decl, global_bindings_p (), 0);
utf8_decl_list = decl;
- make_decl_rtl (decl, (char*) 0);
+ make_decl_rtl (decl);
ref = build1 (ADDR_EXPR, utf8const_ptr_type, decl);
IDENTIFIER_UTF8_REF (name) = ref;
return ref;
if (TREE_CODE (type) == POINTER_TYPE)
type = TREE_TYPE (type);
- /* FIXME: we really want an indirect reference to our
- superclass. However, libgcj assumes that a superclass
- pointer always points directly to a class. As a workaround
- we always emit this hard superclass reference. */
if (flag_indirect_dispatch
&& type != output_class
- && type != CLASSTYPE_SUPER (output_class)
&& TREE_CODE (type) == RECORD_TYPE)
return build_indirect_class_ref (type);
SET_DECL_ASSEMBLER_NAME (decl,
java_mangle_class_field
(&temporary_obstack, type));
- make_decl_rtl (decl, NULL);
+ make_decl_rtl (decl);
pushdecl_top_level (decl);
}
}
abort ();
prim_class = lookup_class (get_identifier (prim_class_name));
- return build (COMPONENT_REF, NULL_TREE,
- prim_class, TYPE_identifier_node, NULL_TREE);
+ return build3 (COMPONENT_REF, NULL_TREE,
+ prim_class, TYPE_identifier_node, NULL_TREE);
}
decl_name = TYPE_NAME (type);
if (TREE_CODE (decl_name) == TYPE_DECL)
TREE_STATIC (decl) = 1;
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = 1;
- make_decl_rtl (decl, NULL);
+ DECL_ARTIFICIAL (decl) = 1;
+ make_decl_rtl (decl);
pushdecl_top_level (decl);
}
}
However, currently sometimes gcj is too eager and will end up
returning the field itself, leading to an incorrect external
reference being generated. */
- if ((is_compiled
- && (! flag_indirect_dispatch || current_class == fclass))
+ if ((is_compiled && !flag_indirect_dispatch)
|| (FIELD_FINAL (fdecl) && DECL_INITIAL (fdecl) != NULL_TREE
&& (JSTRING_TYPE_P (TREE_TYPE (fdecl))
|| JNUMERIC_TYPE_P (TREE_TYPE (fdecl)))
{
if (is_compiled == 1)
DECL_EXTERNAL (fdecl) = 1;
- make_decl_rtl (fdecl, NULL);
+ make_decl_rtl (fdecl);
}
return fdecl;
}
if (flag_indirect_dispatch)
{
tree table_index
- = build_int_2 (get_symbol_table_index
- (fdecl, &TYPE_ATABLE_METHODS (output_class)), 0);
+ = build_int_cst (NULL_TREE, get_symbol_table_index
+ (fdecl, &TYPE_ATABLE_METHODS (output_class)));
tree field_address
- = build (ARRAY_REF, build_pointer_type (TREE_TYPE (fdecl)),
- TYPE_ATABLE_DECL (output_class), table_index,
- NULL_TREE, NULL_TREE);
+ = build4 (ARRAY_REF,
+ TREE_TYPE (TREE_TYPE (TYPE_ATABLE_DECL (output_class))),
+ TYPE_ATABLE_DECL (output_class), table_index,
+ NULL_TREE, NULL_TREE);
+ field_address = convert (build_pointer_type (TREE_TYPE (fdecl)),
+ field_address);
return fold (build1 (INDIRECT_REF, TREE_TYPE (fdecl),
field_address));
}
else
{
/* Compile as:
- * *(FTYPE*)build_class_ref(FCLASS)->fields[INDEX].info.addr */
+ *(FTYPE*)build_class_ref(FCLASS)->fields[INDEX].info.addr */
tree ref = build_class_ref (fclass);
tree fld;
int field_index = 0;
ref = build1 (INDIRECT_REF, class_type_node, ref);
- ref = build (COMPONENT_REF, field_ptr_type_node, ref,
- lookup_field (&class_type_node, fields_ident),
- NULL_TREE);
+ ref = build3 (COMPONENT_REF, field_ptr_type_node, ref,
+ lookup_field (&class_type_node, fields_ident),
+ NULL_TREE);
for (fld = TYPE_FIELDS (fclass); ; fld = TREE_CHAIN (fld))
{
field_index++;
}
field_index *= int_size_in_bytes (field_type_node);
- ref = fold (build (PLUS_EXPR, field_ptr_type_node,
- ref, build_int_2 (field_index, 0)));
+ ref = fold (build2 (PLUS_EXPR, field_ptr_type_node,
+ ref, build_int_cst (NULL_TREE, field_index)));
ref = build1 (INDIRECT_REF, field_type_node, ref);
- ref = build (COMPONENT_REF, field_info_union_node,
- ref, lookup_field (&field_type_node, info_ident),
- NULL_TREE);
- ref = build (COMPONENT_REF, ptr_type_node,
- ref, TREE_CHAIN (TYPE_FIELDS (field_info_union_node)),
- NULL_TREE);
+ ref = build3 (COMPONENT_REF, field_info_union_node,
+ ref, lookup_field (&field_type_node, info_ident),
+ NULL_TREE);
+ ref = build3 (COMPONENT_REF, ptr_type_node,
+ ref, TREE_CHAIN (TYPE_FIELDS (field_info_union_node)),
+ NULL_TREE);
+ ref = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (fdecl)), ref);
return fold (build1 (INDIRECT_REF, TREE_TYPE(fdecl), ref));
}
}
abort ();
}
+static GTY (()) int alias_labelno = 0;
+
+/* Create a private alias for METHOD. Using this alias instead of the method
+ decl ensures that ncode entries in the method table point to the real function
+ at runtime, not a PLT entry. */
+
+static tree
+make_local_function_alias (tree method)
+{
+#ifdef ASM_OUTPUT_DEF
+ tree alias;
+
+ const char *method_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (method));
+ char *name = alloca (strlen (method_name) + 2);
+ char *buf = alloca (strlen (method_name) + 128);
+
+ /* Only create aliases for local functions. */
+ if (DECL_EXTERNAL (method))
+ return method;
+
+ /* Prefix method_name with 'L' for the alias label. */
+ *name = 'L';
+ strcpy (name + 1, method_name);
+
+ ASM_GENERATE_INTERNAL_LABEL (buf, name, alias_labelno++);
+ alias = build_decl (FUNCTION_DECL, get_identifier (buf),
+ TREE_TYPE (method));
+ DECL_CONTEXT (alias) = NULL;
+ TREE_READONLY (alias) = TREE_READONLY (method);
+ TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (method);
+ TREE_PUBLIC (alias) = 0;
+ DECL_EXTERNAL (alias) = 0;
+ DECL_ARTIFICIAL (alias) = 1;
+ DECL_INLINE (alias) = 0;
+ DECL_INITIAL (alias) = error_mark_node;
+ TREE_ADDRESSABLE (alias) = 1;
+ TREE_USED (alias) = 1;
+ SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias));
+ TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1;
+ if (!flag_syntax_only)
+ assemble_alias (alias, DECL_ASSEMBLER_NAME (method));
+ return alias;
+#else
+ return method;
+#endif
+}
+
+/** Make reflection data (_Jv_Field) for field FDECL. */
+
static tree
make_field_value (tree fdecl)
{
if (! resolved)
flags |= 0x8000 /* FIELD_UNRESOLVED_FLAG */;
- PUSH_FIELD_VALUE (finit, "accflags", build_int_2 (flags, 0));
+ PUSH_FIELD_VALUE (finit, "accflags", build_int_cst (NULL_TREE, flags));
PUSH_FIELD_VALUE (finit, "bsize", TYPE_SIZE_UNIT (TREE_TYPE (fdecl)));
PUSH_FIELD_VALUE
? TREE_CHAIN (TYPE_FIELDS (field_info_union_node))
: TYPE_FIELDS (field_info_union_node)),
(FIELD_STATIC (fdecl)
- ? build_address_of (build_static_field_ref (fdecl))
+ ? build_address_of (fdecl)
: byte_position (fdecl)))));
FINISH_RECORD_CONSTRUCTOR (finit);
return finit;
}
+/** Make reflection data (_Jv_Method) for method MDECL. */
+
static tree
make_method_value (tree mdecl)
{
class_decl = DECL_CONTEXT (mdecl);
/* For interfaces, the index field contains the dispatch index. */
if (CLASS_INTERFACE (TYPE_NAME (class_decl)))
- index = build_int_2 (get_interface_method_index (mdecl, class_decl), 0);
+ index = build_int_cst (NULL_TREE,
+ get_interface_method_index (mdecl, class_decl));
else if (!flag_indirect_dispatch && get_method_index (mdecl) != NULL_TREE)
index = get_method_index (mdecl);
else
code = null_pointer_node;
if (DECL_RTL_SET_P (mdecl))
- code = build1 (ADDR_EXPR, nativecode_ptr_type_node, mdecl);
+ code = build1 (ADDR_EXPR, nativecode_ptr_type_node,
+ make_local_function_alias (mdecl));
START_RECORD_CONSTRUCTOR (minit, method_type_node);
PUSH_FIELD_VALUE (minit, "name",
build_utf8_ref (DECL_CONSTRUCTOR_P (mdecl) ?
(IDENTIFIER_POINTER(signature),
IDENTIFIER_LENGTH(signature)))));
}
- PUSH_FIELD_VALUE (minit, "accflags", build_int_2 (accflags, 0));
+ PUSH_FIELD_VALUE (minit, "accflags", build_int_cst (NULL_TREE, accflags));
PUSH_FIELD_VALUE (minit, "index", index);
PUSH_FIELD_VALUE (minit, "ncode", code);
TREE_STATIC (array) = 1;
DECL_ARTIFICIAL (array) = 1;
DECL_IGNORED_P (array) = 1;
- rest_of_decl_compilation (array, (char*) 0, 1, 0);
+ rest_of_decl_compilation (array, 1, 0);
table = build1 (ADDR_EXPR, ptr_type_node, array);
}
else
{
if (!DECL_RTL_SET_P (method))
- make_decl_rtl (method, NULL);
+ make_decl_rtl (method);
if (TARGET_VTABLE_USES_DESCRIPTORS)
for (j = 0; j < TARGET_VTABLE_USES_DESCRIPTORS; ++j)
{
- tree fdesc = build (FDESC_EXPR, nativecode_ptr_type_node,
- method, build_int_2 (j, 0));
+ tree fdesc = build2 (FDESC_EXPR, nativecode_ptr_type_node,
+ method, build_int_cst (NULL_TREE, j));
TREE_CONSTANT (fdesc) = 1;
TREE_INVARIANT (fdesc) = 1;
list = tree_cons (NULL_TREE, fdesc, list);
tree type_decl = TYPE_NAME (type);
/** Offset from start of virtual function table declaration
to where objects actually point at, following new g++ ABI. */
- tree dtable_start_offset = build_int_2 (2 * POINTER_SIZE / BITS_PER_UNIT, 0);
+ tree dtable_start_offset = build_int_cst (NULL_TREE,
+ 2 * POINTER_SIZE / BITS_PER_UNIT);
this_class_addr = build_class_ref (type);
decl = TREE_OPERAND (this_class_addr, 0);
/* Build Field array. */
field = TYPE_FIELDS (type);
- if (DECL_NAME (field) == NULL_TREE)
+ while (field && DECL_ARTIFICIAL (field))
+ field = TREE_CHAIN (field); /* Skip dummy fields. */
+ if (field && DECL_NAME (field) == NULL_TREE)
field = TREE_CHAIN (field); /* Skip dummy field for inherited data. */
for ( ; field != NULL_TREE; field = TREE_CHAIN (field))
{
if (initial != NULL_TREE
&& TREE_TYPE (initial) == string_ptr_type_node)
DECL_INITIAL (field) = NULL_TREE;
- rest_of_decl_compilation (field, (char*) 0, 1, 1);
+ rest_of_decl_compilation (field, 1, 1);
DECL_INITIAL (field) = initial;
}
else
TREE_STATIC (fields_decl) = 1;
DECL_ARTIFICIAL (fields_decl) = 1;
DECL_IGNORED_P (fields_decl) = 1;
- rest_of_decl_compilation (fields_decl, (char*) 0, 1, 0);
+ rest_of_decl_compilation (fields_decl, 1, 0);
}
else
fields_decl = NULL_TREE;
tree init;
if (METHOD_PRIVATE (method)
&& ! flag_keep_inline_functions
- && (flag_inline_functions || optimize))
+ && optimize)
+ continue;
+ /* Even if we have a decl, we don't necessarily have the code.
+ This can happen if we inherit a method from a superclass for
+ which we don't have a .class file. */
+ if (METHOD_DUMMY (method))
continue;
init = make_method_value (method);
method_count++;
TREE_STATIC (methods_decl) = 1;
DECL_ARTIFICIAL (methods_decl) = 1;
DECL_IGNORED_P (methods_decl) = 1;
- rest_of_decl_compilation (methods_decl, (char*) 0, 1, 0);
+ rest_of_decl_compilation (methods_decl, 1, 0);
if (supers_all_compiled (type) && ! CLASS_INTERFACE (type_decl)
&& !flag_indirect_dispatch)
DECL_ARTIFICIAL (dtable_decl) = 1;
DECL_IGNORED_P (dtable_decl) = 1;
TREE_PUBLIC (dtable_decl) = 1;
- rest_of_decl_compilation (dtable_decl, (char*) 0, 1, 0);
+ rest_of_decl_compilation (dtable_decl, 1, 0);
if (type == class_type_node)
class_dtable_decl = dtable_decl;
}
DECL_IGNORED_P (class_dtable_decl) = 1;
if (is_compiled_class (class_type_node) != 2)
DECL_EXTERNAL (class_dtable_decl) = 1;
- rest_of_decl_compilation (class_dtable_decl, (char*) 0, 1, 0);
+ rest_of_decl_compilation (class_dtable_decl, 1, 0);
}
super = CLASSTYPE_SUPER (type);
if (super == NULL_TREE)
super = null_pointer_node;
- else if (/* FIXME: we should also test for (!
- flag_indirect_dispatch) here, but libgcj can't cope with
- a symbolic reference a superclass in the class data. */
- assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl)))
+ else if (! flag_indirect_dispatch
+ && assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl)))
&& assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (super)))))
super = build_class_ref (super);
else
{
int super_index = alloc_class_constant (super);
- super = build_int_2 (super_index, 0);
- TREE_TYPE (super) = ptr_type_node;
+ super = build_int_cst (ptr_type_node, super_index);
}
/* Build and emit the array of implemented interfaces. */
if (type != object_type_node)
- interface_len = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type)) - 1;
+ interface_len = BINFO_N_BASE_BINFOS (TYPE_BINFO (type)) - 1;
+
if (interface_len > 0)
{
tree init = NULL_TREE;
= build_prim_array_type (class_ptr_type, interface_len);
idecl = build_decl (VAR_DECL, mangled_classname ("_IF_", type),
interface_array_type);
+
for (i = interface_len; i > 0; i--)
{
- tree child = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), i);
+ tree child = BINFO_BASE_BINFO (TYPE_BINFO (type), i);
tree iclass = BINFO_TYPE (child);
tree index;
if (! flag_indirect_dispatch
else
{
int int_index = alloc_class_constant (iclass);
- index = build_int_2 (int_index, 0);
- TREE_TYPE (index) = ptr_type_node;
+ index = build_int_cst (ptr_type_node, int_index);
}
init = tree_cons (NULL_TREE, index, init);
}
DECL_ARTIFICIAL (idecl) = 1;
DECL_IGNORED_P (idecl) = 1;
interfaces = build1 (ADDR_EXPR, ptr_type_node, idecl);
- rest_of_decl_compilation (idecl, (char*) 0, 1, 0);
+ rest_of_decl_compilation (idecl, 1, 0);
}
constant_pool_constructor = build_constants_constructor ();
= emit_symbol_table
(DECL_NAME (TYPE_OTABLE_DECL (type)),
TYPE_OTABLE_DECL (type), TYPE_OTABLE_METHODS (type),
- TYPE_OTABLE_SYMS_DECL (type), integer_type_node);
+ TYPE_OTABLE_SYMS_DECL (type), integer_type_node, 1);
TYPE_ATABLE_DECL (type)
= emit_symbol_table
(DECL_NAME (TYPE_ATABLE_DECL (type)),
TYPE_ATABLE_DECL (type), TYPE_ATABLE_METHODS (type),
- TYPE_ATABLE_SYMS_DECL (type), ptr_type_node);
+ TYPE_ATABLE_SYMS_DECL (type), ptr_type_node, 1);
+
+ TYPE_ITABLE_DECL (type)
+ = emit_symbol_table
+ (DECL_NAME (TYPE_ITABLE_DECL (type)),
+ TYPE_ITABLE_DECL (type), TYPE_ITABLE_METHODS (type),
+ TYPE_ITABLE_SYMS_DECL (type), ptr_type_node, 2);
}
TYPE_CTABLE_DECL (type) = emit_catch_table (type);
START_RECORD_CONSTRUCTOR (temp, object_type_node);
PUSH_FIELD_VALUE (temp, "vtable",
- build (PLUS_EXPR, dtable_ptr_type,
- build1 (ADDR_EXPR, dtable_ptr_type, class_dtable_decl),
- dtable_start_offset));
+ build2 (PLUS_EXPR, dtable_ptr_type,
+ build1 (ADDR_EXPR, dtable_ptr_type,
+ class_dtable_decl),
+ dtable_start_offset));
if (! flag_hash_synchronization)
PUSH_FIELD_VALUE (temp, "sync_info", null_pointer_node);
FINISH_RECORD_CONSTRUCTOR (temp);
PUSH_FIELD_VALUE (cons, "next", null_pointer_node);
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));
+ build_int_cst (NULL_TREE,
+ get_access_flags_from_decl (type_decl)));
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, "method_count",
+ build_int_cst (NULL_TREE, method_count));
if (flag_indirect_dispatch)
PUSH_FIELD_VALUE (cons, "vtable_method_count", integer_minus_one_node);
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, "size_in_bytes", size_in_bytes (type));
- PUSH_FIELD_VALUE (cons, "field_count", build_int_2 (field_count, 0));
+ /* If we're using the binary compatibility ABI we don't know the
+ size until load time. */
+ PUSH_FIELD_VALUE (cons, "size_in_bytes",
+ (flag_indirect_dispatch
+ ? integer_minus_one_node
+ : size_in_bytes (type)));
+ PUSH_FIELD_VALUE (cons, "field_count",
+ build_int_cst (NULL_TREE, field_count));
PUSH_FIELD_VALUE (cons, "static_field_count",
- build_int_2 (static_field_count, 0));
+ build_int_cst (NULL_TREE, static_field_count));
if (flag_indirect_dispatch)
PUSH_FIELD_VALUE (cons, "vtable", null_pointer_node);
else
PUSH_FIELD_VALUE (cons, "vtable",
dtable_decl == NULL_TREE ? null_pointer_node
- : build (PLUS_EXPR, dtable_ptr_type,
- build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl),
- dtable_start_offset));
+ : build2 (PLUS_EXPR, dtable_ptr_type,
+ build1 (ADDR_EXPR, dtable_ptr_type,
+ dtable_decl),
+ dtable_start_offset));
if (TYPE_OTABLE_METHODS (type) == NULL_TREE)
{
PUSH_FIELD_VALUE (cons, "otable", null_pointer_node);
TREE_CONSTANT (TYPE_ATABLE_DECL (type)) = 1;
TREE_INVARIANT (TYPE_ATABLE_DECL (type)) = 1;
}
+ if (TYPE_ITABLE_METHODS(type) == NULL_TREE)
+ {
+ PUSH_FIELD_VALUE (cons, "itable", null_pointer_node);
+ PUSH_FIELD_VALUE (cons, "itable_syms", null_pointer_node);
+ }
+ else
+ {
+ PUSH_FIELD_VALUE (cons, "itable",
+ build1 (ADDR_EXPR, itable_ptr_type, TYPE_ITABLE_DECL (type)));
+ PUSH_FIELD_VALUE (cons, "itable_syms",
+ build1 (ADDR_EXPR, symbols_array_ptr_type,
+ TYPE_ITABLE_SYMS_DECL (type)));
+ TREE_CONSTANT (TYPE_ITABLE_DECL (type)) = 1;
+ TREE_INVARIANT (TYPE_ITABLE_DECL (type)) = 1;
+ }
PUSH_FIELD_VALUE (cons, "catch_classes",
build1 (ADDR_EXPR, ptr_type_node, TYPE_CTABLE_DECL (type)));
PUSH_FIELD_VALUE (cons, "interfaces", interfaces);
PUSH_FIELD_VALUE (cons, "loader", null_pointer_node);
- PUSH_FIELD_VALUE (cons, "interface_count", build_int_2 (interface_len, 0));
- PUSH_FIELD_VALUE (cons, "state", integer_zero_node);
+ PUSH_FIELD_VALUE (cons, "interface_count",
+ build_int_cst (NULL_TREE, interface_len));
+ PUSH_FIELD_VALUE
+ (cons, "state",
+ convert (byte_type_node,
+ build_int_cst (NULL_TREE,
+ flag_indirect_dispatch
+ ? JV_STATE_PRELOADING
+ : JV_STATE_COMPILED)));
PUSH_FIELD_VALUE (cons, "thread", null_pointer_node);
PUSH_FIELD_VALUE (cons, "depth", integer_zero_node);
PUSH_FIELD_VALUE (cons, "idt", null_pointer_node);
PUSH_FIELD_VALUE (cons, "arrayclass", null_pointer_node);
PUSH_FIELD_VALUE (cons, "protectionDomain", null_pointer_node);
+
+ {
+ tree assertion_table_ref;
+ if (TYPE_ASSERTIONS (type) == NULL)
+ assertion_table_ref = null_pointer_node;
+ else
+ assertion_table_ref = build1 (ADDR_EXPR,
+ build_pointer_type (assertion_table_type),
+ emit_assertion_table (type));
+
+ PUSH_FIELD_VALUE (cons, "assertion_table", assertion_table_ref);
+ }
+
PUSH_FIELD_VALUE (cons, "hack_signers", null_pointer_node);
PUSH_FIELD_VALUE (cons, "chain", null_pointer_node);
PUSH_FIELD_VALUE (cons, "aux_info", null_pointer_node);
+ PUSH_FIELD_VALUE (cons, "engine", null_pointer_node);
FINISH_RECORD_CONSTRUCTOR (cons);
if (flag_hash_synchronization && POINTER_SIZE < 64)
DECL_ALIGN (decl) = 64;
- rest_of_decl_compilation (decl, (char*) 0, 1, 0);
+ rest_of_decl_compilation (decl, 1, 0);
+
+ TYPE_OTABLE_DECL (type) = NULL_TREE;
+ TYPE_ATABLE_DECL (type) = NULL_TREE;
+ TYPE_CTABLE_DECL (type) = NULL_TREE;
}
void
finish_class (void)
{
+ if (TYPE_VERIFY_METHOD (output_class))
+ {
+ tree verify_method = TYPE_VERIFY_METHOD (output_class);
+ DECL_SAVED_TREE (verify_method)
+ = add_stmt_to_compound (DECL_SAVED_TREE (verify_method), void_type_node,
+ build (RETURN_EXPR, void_type_node, NULL));
+ java_genericize (verify_method);
+ cgraph_finalize_function (verify_method, false);
+ TYPE_ASSERTIONS (current_class) = NULL;
+ }
+
java_expand_catch_classes (current_class);
current_function_decl = NULL_TREE;
make_class_data (current_class);
register_class ();
- rest_of_decl_compilation (TYPE_NAME (current_class), (char*) 0, 1, 0);
+ rest_of_decl_compilation (TYPE_NAME (current_class), 1, 0);
}
/* Return 2 if CLASS is compiled by this compilation job;
if (this_class)
{
tree this_decl = TYPE_NAME (this_class);
+#ifdef USE_MAPPED_LOCATION
+ this_wrap = build_expr_wfl (this_class,
+ DECL_SOURCE_LOCATION (this_decl));
+#else
this_wrap = build_expr_wfl (this_class,
DECL_SOURCE_FILE (this_decl),
DECL_SOURCE_LINE (this_decl), 0);
+#endif
}
super_class = do_resolve_class (NULL_TREE, /* FIXME? */
super_class, NULL_TREE, this_wrap);
char *report;
tree current;
- sprintf (buffer, " with `%s'",
+ sprintf (buffer, " with '%s'",
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class))));
obstack_grow (&temporary_obstack, buffer, strlen (buffer));
current = TREE_CHAIN (current))
{
tree decl = TYPE_NAME (TREE_PURPOSE (current));
- sprintf (buffer, "\n which inherits from `%s' (%s:%d)",
+ sprintf (buffer, "\n which inherits from '%s' (%s:%d)",
IDENTIFIER_POINTER (DECL_NAME (decl)),
DECL_SOURCE_FILE (decl),
DECL_SOURCE_LINE (decl));
of this itself. */
if (!CLASS_FROM_SOURCE_P (this_class))
{
- tree basetype_vec = TYPE_BINFO_BASETYPES (this_class);
-
- if (basetype_vec)
+ int i;
+ if (TYPE_BINFO (this_class))
{
- int n = TREE_VEC_LENGTH (basetype_vec) - 1;
- int i;
- for (i = n; i > 0; i--)
+ for (i = BINFO_N_BASE_BINFOS (TYPE_BINFO (this_class)) - 1; i > 0; i--)
{
- tree vec_elt = TREE_VEC_ELT (basetype_vec, i);
- tree super_interface = BINFO_TYPE (vec_elt);
-
+ tree binfo = BINFO_BASE_BINFO (TYPE_BINFO (this_class), i);
+ tree super_interface = BINFO_TYPE (binfo);
tree maybe_super_interface
= maybe_layout_super_class (super_interface, NULL_TREE);
if (maybe_super_interface == NULL
static void
add_miranda_methods (tree base_class, tree search_class)
{
- tree basetype_vec = TYPE_BINFO_BASETYPES (search_class);
- int i, n = TREE_VEC_LENGTH (basetype_vec);
- for (i = 1; i < n; ++i)
+ int i;
+ tree binfo, base_binfo;
+
+ if (!CLASS_PARSED_P (search_class))
+ load_class (search_class, 1);
+
+ for (binfo = TYPE_BINFO (search_class), i = 1;
+ BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
{
tree method_decl;
- tree elt = TREE_VEC_ELT (basetype_vec, i);
- if (elt == NULL_TREE)
- break;
- elt = BINFO_TYPE (elt);
+ tree elt = BINFO_TYPE (base_binfo);
+
+ /* FIXME: This is totally bogus. We should not be handling
+ Miranda methods at all if we're using the BC ABI. */
+ if (TYPE_DUMMY (elt))
+ continue;
/* Ensure that interface methods are seen in declared order. */
+ if (!CLASS_LOADED_P (elt))
+ load_class (elt, 1);
layout_class_methods (elt);
/* All base classes will have been laid out at this point, so the order
dtable_count = integer_zero_node;
type_name = TYPE_NAME (this_class);
- if (CLASS_ABSTRACT (type_name) || CLASS_INTERFACE (type_name))
+ if (!flag_indirect_dispatch
+ && (CLASS_ABSTRACT (type_name) || CLASS_INTERFACE (type_name)))
{
/* An abstract class can have methods which are declared only in
an implemented interface. These are called "Miranda
if (! METHOD_ABSTRACT (method_decl)
|| (CLASS_INTERFACE (TYPE_NAME (this_class))
&& (DECL_CLINIT_P (method_decl))))
- make_decl_rtl (method_decl, NULL);
+ make_decl_rtl (method_decl);
if (ID_INIT_P (method_name))
{
DECL_CONSTRUCTOR_P (method_decl) = 1;
build_java_argument_signature (TREE_TYPE (method_decl));
}
- else if (! METHOD_STATIC (method_decl) && !DECL_ARTIFICIAL (method_decl))
+ else if (! METHOD_STATIC (method_decl))
{
tree method_sig =
build_java_argument_signature (TREE_TYPE (method_decl));
bool method_override = false;
tree super_method = lookup_argument_method (super_class, method_name,
method_sig);
- if (super_method != NULL_TREE)
+ if (super_method != NULL_TREE
+ && ! METHOD_DUMMY (super_method))
{
method_override = true;
if (! METHOD_PUBLIC (super_method) &&
tree method_index = get_method_index (super_method);
set_method_index (method_decl, method_index);
if (method_index == NULL_TREE
- && !CLASS_FROM_SOURCE_P (this_class))
+ && !CLASS_FROM_SOURCE_P (this_class)
+ && ! DECL_ARTIFICIAL (super_method))
error ("%Jnon-static method '%D' overrides static method",
method_decl, method_decl);
}
- else if (! METHOD_FINAL (method_decl)
- && ! METHOD_PRIVATE (method_decl)
- && ! CLASS_FINAL (TYPE_NAME (this_class))
+ else if (this_class == object_type_node
+ && (METHOD_FINAL (method_decl)
+ || METHOD_PRIVATE (method_decl)))
+ {
+ /* We don't generate vtable entries for final Object
+ methods. This is simply to save space, since every
+ object would otherwise have to define them. */
+ }
+ else if (! METHOD_PRIVATE (method_decl)
&& dtable_count)
{
+ /* We generate vtable entries for final methods because they
+ may one day be changed to non-final. */
set_method_index (method_decl, dtable_count);
- dtable_count = fold (build (PLUS_EXPR, integer_type_node,
- dtable_count, integer_one_node));
+ dtable_count = fold (build2 (PLUS_EXPR, integer_type_node,
+ dtable_count, integer_one_node));
}
}
/* Emit something to register classes at start-up time.
The preferred mechanism is through the .jcr section, which contain
- a list of pointers to classes which get registered during
- constructor invocation time. The fallback mechanism is to generate
- a `constructor' function which calls _Jv_RegisterClass for each
- class in this file. */
+ a list of pointers to classes which get registered during constructor
+ invocation time.
+
+ The fallback mechanism is to add statements to *LIST_P to call
+ _Jv_RegisterClass for each class in this file. These statements will
+ be added to a static constructor function for this translation unit. */
void
-emit_register_classes (void)
+emit_register_classes (tree *list_p)
{
+ if (registered_class == NULL)
+ return;
+
/* ??? This isn't quite the correct test. We also have to know
that the target is using gcc's crtbegin/crtend objects rather
than the ones that come with the operating system. */
}
else
{
- extern tree get_file_function_name (int);
- tree init_name = get_file_function_name ('I');
- tree init_type = build_function_type (void_type_node, end_params_node);
- tree init_decl;
- tree t;
- location_t saved_loc = input_location;
-
- init_decl = build_decl (FUNCTION_DECL, init_name, init_type);
- SET_DECL_ASSEMBLER_NAME (init_decl, init_name);
- DECL_SOURCE_LINE (init_decl) = 0;
- TREE_STATIC (init_decl) = 1;
- current_function_decl = init_decl;
- DECL_INLINE (init_decl) = 0;
- DECL_UNINLINABLE (init_decl) = 1;
- DECL_RESULT (init_decl) = build_decl (RESULT_DECL, NULL_TREE,
- void_type_node);
-
- /* It can be a static function as long as collect2 does not have
- to scan the object file to find its ctor/dtor routine. */
- TREE_PUBLIC (init_decl) = ! targetm.have_ctors_dtors;
-
- /* Suppress spurious warnings. */
- TREE_USED (init_decl) = 1;
-
- pushlevel (0);
- make_decl_rtl (init_decl, NULL);
- init_function_start (init_decl);
- expand_function_start (init_decl, 0);
-
- for ( t = registered_class; t; t = TREE_CHAIN (t))
- emit_library_call (registerClass_libfunc, 0, VOIDmode, 1,
- XEXP (DECL_RTL (t), 0), Pmode);
- input_location = DECL_SOURCE_LOCATION (init_decl);
- expand_function_end ();
- poplevel (1, 0, 1);
- rest_of_compilation ();
- current_function_decl = NULL_TREE;
-
- if (targetm.have_ctors_dtors)
- (* targetm.asm_out.constructor) (XEXP (DECL_RTL (init_decl), 0),
- DEFAULT_INIT_PRIORITY);
- input_location = saved_loc;
+ tree klass, t, register_class_fn;
+
+ t = build_function_type_list (void_type_node, class_ptr_type, NULL);
+ t = build_decl (FUNCTION_DECL, get_identifier ("_Jv_RegisterClass"), t);
+ TREE_PUBLIC (t) = 1;
+ DECL_EXTERNAL (t) = 1;
+ register_class_fn = t;
+
+ for (klass = registered_class; klass; klass = TREE_CHAIN (klass))
+ {
+ t = build_fold_addr_expr (klass);
+ t = tree_cons (NULL, t, NULL);
+ t = build_function_call_expr (register_class_fn, t);
+ append_to_statement_list (t, list_p);
+ }
}
}
build_symbol_entry (tree decl)
{
tree clname, name, signature, sym;
-
clname = build_utf8_ref (DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))));
- name = build_utf8_ref (DECL_NAME (decl));
+ /* ??? Constructors are given the name foo.foo all the way through
+ the compiler, but in the method table they're all renamed
+ foo.<init>. So, we have to do the same here unless we want an
+ unresolved reference at runtime. */
+ name = build_utf8_ref ((TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_CONSTRUCTOR_P (decl))
+ ? init_identifier_node
+ : DECL_NAME (decl));
signature = build_java_signature (TREE_TYPE (decl));
signature = build_utf8_ref (unmangle_classname
(IDENTIFIER_POINTER (signature),
IDENTIFIER_LENGTH (signature)));
-
+
START_RECORD_CONSTRUCTOR (sym, symbol_type);
PUSH_FIELD_VALUE (sym, "clname", clname);
PUSH_FIELD_VALUE (sym, "name", name);
tree
emit_symbol_table (tree name, tree the_table, tree decl_list,
- tree the_syms_decl, tree the_array_element_type)
+ tree the_syms_decl, tree the_array_element_type,
+ int element_size)
{
tree method_list, method, table, list, null_symbol;
tree table_size, the_array_type;
DECL_INITIAL (the_syms_decl) = table;
DECL_ARTIFICIAL (the_syms_decl) = 1;
DECL_IGNORED_P (the_syms_decl) = 1;
- rest_of_decl_compilation (the_syms_decl, NULL, 1, 0);
+ rest_of_decl_compilation (the_syms_decl, 1, 0);
/* Now that its size is known, redefine the table as an
uninitialized static array of INDEX + 1 elements. The extra entry
is used by the runtime to track whether the table has been
initialized. */
- table_size = build_index_type (build_int_2 (index, 0));
+ table_size
+ = build_index_type (build_int_cst (NULL_TREE, index * element_size + 1));
the_array_type = build_array_type (the_array_element_type, table_size);
the_table = build_decl (VAR_DECL, name, the_array_type);
TREE_STATIC (the_table) = 1;
TREE_READONLY (the_table) = 1;
- rest_of_decl_compilation (the_table, NULL, 1, 0);
+ rest_of_decl_compilation (the_table, 1, 0);
return the_table;
}
-/* make an entry for the catch_classes list. */
+/* Make an entry for the catch_classes list. */
tree
make_catch_class_record (tree catch_class, tree classname)
{
tree_cons (NULL,
make_catch_class_record (null_pointer_node, null_pointer_node),
TYPE_CATCH_CLASSES (this_class));
- table_size =
- build_index_type (build_int_2
- (list_length (TYPE_CATCH_CLASSES (this_class)), 0));
+ table_size = build_index_type
+ (build_int_cst (NULL_TREE,
+ list_length (TYPE_CATCH_CLASSES (this_class))));
array_type
= build_array_type (TREE_TYPE (TREE_TYPE (TYPE_CTABLE_DECL (this_class))),
table_size);
TREE_STATIC (table) = 1;
TREE_READONLY (table) = 1;
DECL_IGNORED_P (table) = 1;
- rest_of_decl_compilation (table, NULL, 1, 0);
+ rest_of_decl_compilation (table, 1, 0);
return table;
}
-
+
+/* Given a type, return the signature used by
+ _Jv_FindClassFromSignature() in libgcj. This isn't exactly the
+ same as build_java_signature() because we want the canonical array
+ type. */
+
+static tree
+build_signature_for_libgcj (tree type)
+{
+ tree sig, ref;
+
+ sig = build_java_signature (type);
+ ref = build_utf8_ref (unmangle_classname (IDENTIFIER_POINTER (sig),
+ IDENTIFIER_LENGTH (sig)));
+ return ref;
+}
+
+/* Add an entry to the type assertion table. Callback used during hashtable
+ traversal. */
+
+static int
+add_assertion_table_entry (void **htab_entry, void *ptr)
+{
+ tree entry;
+ tree code_val, op1_utf8, op2_utf8;
+ tree *list = (tree *) ptr;
+ type_assertion *as = (type_assertion *) *htab_entry;
+
+ code_val = build_int_cst (NULL_TREE, as->assertion_code);
+
+ if (as->op1 == NULL_TREE)
+ op1_utf8 = null_pointer_node;
+ else
+ op1_utf8 = build_signature_for_libgcj (as->op1);
+
+ if (as->op2 == NULL_TREE)
+ op2_utf8 = null_pointer_node;
+ else
+ op2_utf8 = build_signature_for_libgcj (as->op2);
+
+ START_RECORD_CONSTRUCTOR (entry, assertion_entry_type);
+ PUSH_FIELD_VALUE (entry, "assertion_code", code_val);
+ PUSH_FIELD_VALUE (entry, "op1", op1_utf8);
+ PUSH_FIELD_VALUE (entry, "op2", op2_utf8);
+ FINISH_RECORD_CONSTRUCTOR (entry);
+
+ *list = tree_cons (NULL_TREE, entry, *list);
+ return true;
+}
+
+/* Generate the type assertion table for CLASS, and return its DECL. */
+
+static tree
+emit_assertion_table (tree class)
+{
+ tree null_entry, ctor, table_decl;
+ tree list = NULL_TREE;
+ htab_t assertions_htab = TYPE_ASSERTIONS (class);
+
+ /* Iterate through the hash table. */
+ htab_traverse (assertions_htab, add_assertion_table_entry, &list);
+
+ /* Finish with a null entry. */
+ START_RECORD_CONSTRUCTOR (null_entry, assertion_entry_type);
+ PUSH_FIELD_VALUE (null_entry, "assertion_code", integer_zero_node);
+ PUSH_FIELD_VALUE (null_entry, "op1", null_pointer_node);
+ PUSH_FIELD_VALUE (null_entry, "op2", null_pointer_node);
+ FINISH_RECORD_CONSTRUCTOR (null_entry);
+
+ list = tree_cons (NULL_TREE, null_entry, list);
+
+ /* Put the list in the right order and make it a constructor. */
+ list = nreverse (list);
+ ctor = build_constructor (assertion_table_type, list);
+
+ table_decl = build_decl (VAR_DECL, mangled_classname ("_type_assert_", class),
+ assertion_table_type);
+
+ TREE_STATIC (table_decl) = 1;
+ TREE_READONLY (table_decl) = 1;
+ TREE_CONSTANT (table_decl) = 1;
+ DECL_IGNORED_P (table_decl) = 1;
+
+ DECL_INITIAL (table_decl) = ctor;
+ DECL_ARTIFICIAL (table_decl) = 1;
+ rest_of_decl_compilation (table_decl, 1, 0);
+
+ return table_decl;
+}
void
init_class_processing (void)
{
- registerClass_libfunc = gen_rtx_SYMBOL_REF (Pmode, "_Jv_RegisterClass");
fields_ident = get_identifier ("fields");
info_ident = get_identifier ("info");
+
gcc_obstack_init (&temporary_obstack);
}
\f