aboutsummaryrefslogtreecommitdiff
path: root/gcc/java/class.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/java/class.c')
-rw-r--r--gcc/java/class.c349
1 files changed, 262 insertions, 87 deletions
diff --git a/gcc/java/class.c b/gcc/java/class.c
index 543bdf2..391752a 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -43,6 +43,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "stdio.h"
#include "target.h"
#include "except.h"
+#include "cgraph.h"
#include "tree-iterator.h"
/* DOS brain-damage */
@@ -61,6 +62,7 @@ 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 tree emit_assertion_table (tree);
struct obstack temporary_obstack;
@@ -342,6 +344,34 @@ unmangle_classname (const char *name, int name_length)
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. */
@@ -372,54 +402,14 @@ gen_indirect_dispatch_tables (tree type)
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)
{
@@ -959,7 +949,7 @@ build_class_ref (tree type)
we always emit this hard superclass reference. */
if (flag_indirect_dispatch
&& type != output_class
- && type != CLASSTYPE_SUPER (output_class)
+// && type != CLASSTYPE_SUPER (output_class)
&& TREE_CODE (type) == RECORD_TYPE)
return build_indirect_class_ref (type);
@@ -1062,8 +1052,7 @@ build_static_field_ref (tree fdecl)
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)))
@@ -1084,16 +1073,19 @@ build_static_field_ref (tree fdecl)
= build_int_cst (NULL_TREE, get_symbol_table_index
(fdecl, &TYPE_ATABLE_METHODS (output_class)));
tree field_address
- = build4 (ARRAY_REF, build_pointer_type (TREE_TYPE (fdecl)),
+ = 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;
@@ -1117,7 +1109,7 @@ build_static_field_ref (tree fdecl)
ref, build_int_cst (NULL_TREE, field_index)));
ref = build1 (INDIRECT_REF, field_type_node, ref);
ref = build3 (COMPONENT_REF, field_info_union_node,
- ref, lookup_field (&field_type_node, info_ident),
+ 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)),
@@ -1284,7 +1276,7 @@ make_field_value (tree fdecl)
? 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);
@@ -1565,7 +1557,9 @@ make_class_data (tree type)
/* 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))
{
@@ -1620,6 +1614,11 @@ make_class_data (tree type)
&& ! flag_keep_inline_functions
&& optimize)
continue;
+ /* Even if we have a decl, we don't necessaily 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++;
methods = tree_cons (NULL_TREE, init, methods);
@@ -1663,10 +1662,8 @@ make_class_data (tree type)
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
@@ -1721,13 +1718,19 @@ make_class_data (tree type)
= 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);
@@ -1765,8 +1768,13 @@ make_class_data (tree 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, "size_in_bytes", size_in_bytes (type));
- PUSH_FIELD_VALUE (cons, "field_count",
+ /* 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_cst (NULL_TREE, static_field_count));
@@ -1810,6 +1818,21 @@ make_class_data (tree type)
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)));
@@ -1817,7 +1840,13 @@ make_class_data (tree type)
PUSH_FIELD_VALUE (cons, "loader", null_pointer_node);
PUSH_FIELD_VALUE (cons, "interface_count",
build_int_cst (NULL_TREE, interface_len));
- PUSH_FIELD_VALUE (cons, "state", integer_zero_node);
+ 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);
@@ -1825,9 +1854,23 @@ make_class_data (tree type)
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);
@@ -1838,11 +1881,26 @@ make_class_data (tree type)
DECL_ALIGN (decl) = 64;
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;
@@ -2095,20 +2153,22 @@ layout_class (tree this_class)
if (!CLASS_FROM_SOURCE_P (this_class))
{
int i;
-
- for (i = BINFO_N_BASE_BINFOS (TYPE_BINFO (this_class)) - 1; i > 0; i--)
+ if (TYPE_BINFO (this_class))
{
- 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
- || TREE_CODE (TYPE_SIZE (maybe_super_interface)) == ERROR_MARK)
+ for (i = BINFO_N_BASE_BINFOS (TYPE_BINFO (this_class)) - 1; i > 0; i--)
{
- TYPE_SIZE (this_class) = error_mark_node;
- CLASS_BEING_LAIDOUT (this_class) = 0;
- class_list = TREE_CHAIN (class_list);
- return;
+ 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
+ || TREE_CODE (TYPE_SIZE (maybe_super_interface)) == ERROR_MARK)
+ {
+ TYPE_SIZE (this_class) = error_mark_node;
+ CLASS_BEING_LAIDOUT (this_class) = 0;
+ class_list = TREE_CHAIN (class_list);
+ return;
+ }
}
}
}
@@ -2124,8 +2184,11 @@ layout_class (tree this_class)
static void
add_miranda_methods (tree base_class, tree search_class)
{
- tree binfo, base_binfo;
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++)
@@ -2133,6 +2196,11 @@ add_miranda_methods (tree base_class, tree search_class)
tree method_decl;
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);
@@ -2193,7 +2261,8 @@ layout_class_methods (tree this_class)
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
@@ -2273,7 +2342,9 @@ layout_class_method (tree this_class, tree super_class,
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)
+ && ! DECL_ARTIFICIAL (super_method))
{
method_override = true;
if (! METHOD_PUBLIC (super_method) &&
@@ -2296,11 +2367,19 @@ layout_class_method (tree this_class, tree super_class,
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 (build2 (PLUS_EXPR, integer_type_node,
dtable_count, integer_one_node));
@@ -2387,14 +2466,20 @@ static tree
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);
@@ -2410,7 +2495,8 @@ build_symbol_entry (tree decl)
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;
@@ -2457,7 +2543,8 @@ emit_symbol_table (tree name, tree the_table, tree decl_list,
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_cst (NULL_TREE, index));
+ 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;
@@ -2467,7 +2554,7 @@ emit_symbol_table (tree name, tree the_table, tree decl_list,
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)
{
@@ -2512,7 +2599,95 @@ emit_catch_table (tree this_class)
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)