diff options
author | Tom Tromey <tromey@gcc.gnu.org> | 2004-11-25 03:47:08 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2004-11-25 03:47:08 +0000 |
commit | 367390404d26b7bfc400d77893579e83e2a19fb9 (patch) | |
tree | 477abdf83653e20b0e74447d6ca47eb67b0511b8 /gcc/java/class.c | |
parent | ec0641f612862498e829fdaf040a201c0ba68762 (diff) | |
download | gcc-367390404d26b7bfc400d77893579e83e2a19fb9.zip gcc-367390404d26b7bfc400d77893579e83e2a19fb9.tar.gz gcc-367390404d26b7bfc400d77893579e83e2a19fb9.tar.bz2 |
* Merged gcj-abi-2-dev-branch to trunk.
(Actual changes too large to list in the commit message;
see ChangeLog.)
From-SVN: r91270
Diffstat (limited to 'gcc/java/class.c')
-rw-r--r-- | gcc/java/class.c | 349 |
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) |