diff options
author | Andrew Haley <aph@redhat.com> | 2016-09-30 16:24:48 +0000 |
---|---|---|
committer | Andrew Haley <aph@gcc.gnu.org> | 2016-09-30 16:24:48 +0000 |
commit | 07b78716af6a9d7c9fd1e94d9baf94a52c873947 (patch) | |
tree | 3f22b3241c513ad168c8353805614ae1249410f4 /gcc/java/class.c | |
parent | eae993948bae8b788c53772bcb9217c063716f93 (diff) | |
download | gcc-07b78716af6a9d7c9fd1e94d9baf94a52c873947.zip gcc-07b78716af6a9d7c9fd1e94d9baf94a52c873947.tar.gz gcc-07b78716af6a9d7c9fd1e94d9baf94a52c873947.tar.bz2 |
Makefile.def: Remove libjava.
2016-09-30 Andrew Haley <aph@redhat.com>
* Makefile.def: Remove libjava.
* Makefile.tpl: Likewise.
* Makefile.in: Regenerate.
* configure.ac: Likewise.
* configure: Likewise.
* gcc/java: Remove.
* libjava: Likewise.
From-SVN: r240662
Diffstat (limited to 'gcc/java/class.c')
-rw-r--r-- | gcc/java/class.c | 3245 |
1 files changed, 0 insertions, 3245 deletions
diff --git a/gcc/java/class.c b/gcc/java/class.c deleted file mode 100644 index b4708bc..0000000 --- a/gcc/java/class.c +++ /dev/null @@ -1,3245 +0,0 @@ -/* Functions related to building classes and their related objects. - Copyright (C) 1996-2016 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. - -Java and all Java-based marks are trademarks or registered trademarks -of Sun Microsystems, Inc. in the United States and other countries. -The Free Software Foundation is independent of Sun Microsystems, Inc. */ - -/* Written by Per Bothner <bothner@cygnus.com> */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "target.h" -#include "function.h" -#include "tree.h" -#include "stringpool.h" -#include "diagnostic-core.h" -#include "fold-const.h" -#include "stor-layout.h" -#include "varasm.h" -#include "java-tree.h" -#include "jcf.h" -#include "toplev.h" -#include "output.h" /* for switch_to_section and get_section */ -#include "parse.h" -#include "tree-iterator.h" - -static tree make_method_value (tree); -static tree build_java_method_type (tree, tree, int); -static int32 hashUtf8String (const char *, int); -static tree make_field_value (tree); -static tree get_dispatch_vector (tree); -static tree get_dispatch_table (tree, tree); -static int supers_all_compiled (tree type); -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, tree); -static tree emit_assertion_table (tree); -static void register_class (void); - -struct obstack temporary_obstack; - -static const char *cyclic_inheritance_report; - -/* The compiler generates different code depending on whether or not - it can assume certain classes have been compiled down to native - code or not. The compiler options -fassume-compiled= and - -fno-assume-compiled= are used to create a tree of - class_flag_node objects. This tree is queried to determine if - a class is assume to be compiled or not. Each node in the tree - represents either a package or a specific class. */ - -typedef struct class_flag_node_struct -{ - /* The class or package name. */ - const char *ident; - - /* Nonzero if this represents an exclusion. */ - int value; - - /* Pointers to other nodes in the tree. */ - struct class_flag_node_struct *parent; - struct class_flag_node_struct *sibling; - struct class_flag_node_struct *child; -} class_flag_node; - -static class_flag_node *find_class_flag_node (class_flag_node *, const char *); -static void add_class_flag (class_flag_node **, const char *, int); - -/* This is the root of the include/exclude tree. */ - -static class_flag_node *assume_compiled_tree; - -static class_flag_node *enable_assert_tree; - -static GTY(()) tree class_roots[4]; -#define fields_ident class_roots[0] /* get_identifier ("fields") */ -#define info_ident class_roots[1] /* get_identifier ("info") */ -#define class_list class_roots[2] -#define class_dtable_decl class_roots[3] - -static GTY(()) vec<tree, va_gc> *registered_class; - -/* A tree that returns the address of the class$ of the class - currently being compiled. */ -static GTY(()) tree this_classdollar; - -/* Return the node that most closely represents the class whose name - is IDENT. Start the search from NODE (followed by its siblings). - Return NULL if an appropriate node does not exist. */ - -static class_flag_node * -find_class_flag_node (class_flag_node *node, const char *ident) -{ - while (node) - { - size_t node_ident_length = strlen (node->ident); - - /* node_ident_length is zero at the root of the tree. If the - identifiers are the same length, then we have matching - classes. Otherwise check if we've matched an enclosing - package name. */ - - if (node_ident_length == 0 - || (strncmp (ident, node->ident, node_ident_length) == 0 - && (ident[node_ident_length] == '\0' - || ident[node_ident_length] == '.'))) - { - /* We've found a match, however, there might be a more - specific match. */ - - class_flag_node *found = find_class_flag_node (node->child, ident); - if (found) - return found; - else - return node; - } - - /* No match yet. Continue through the sibling list. */ - node = node->sibling; - } - - /* No match at all in this tree. */ - return NULL; -} - -void -add_class_flag (class_flag_node **rootp, const char *ident, int value) -{ - class_flag_node *root = *rootp; - class_flag_node *parent, *node; - - /* Create the root of the tree if it doesn't exist yet. */ - - if (NULL == root) - { - root = XNEW (class_flag_node); - root->ident = ""; - root->value = 0; - root->sibling = NULL; - root->child = NULL; - root->parent = NULL; - *rootp = root; - } - - /* Calling the function with the empty string means we're setting - value for the root of the hierarchy. */ - - if (0 == ident[0]) - { - root->value = value; - return; - } - - /* Find the parent node for this new node. PARENT will either be a - class or a package name. Adjust PARENT accordingly. */ - - parent = find_class_flag_node (root, ident); - if (strcmp (ident, parent->ident) == 0) - parent->value = value; - else - { - /* Insert new node into the tree. */ - node = XNEW (class_flag_node); - - node->ident = xstrdup (ident); - node->value = value; - node->child = NULL; - - node->parent = parent; - node->sibling = parent->child; - parent->child = node; - } -} - -/* Add a new IDENT to the include/exclude tree. It's an exclusion - if EXCLUDEP is nonzero. */ - -void -add_assume_compiled (const char *ident, int excludep) -{ - add_class_flag (&assume_compiled_tree, ident, excludep); -} - -/* The default value returned by enable_assertions. */ - -#define DEFAULT_ENABLE_ASSERT (optimize == 0) - -/* Enter IDENT (a class or package name) into the enable-assertions table. - VALUE is true to enable and false to disable. */ - -void -add_enable_assert (const char *ident, int value) -{ - if (enable_assert_tree == NULL) - add_class_flag (&enable_assert_tree, "", DEFAULT_ENABLE_ASSERT); - add_class_flag (&enable_assert_tree, ident, value); -} - -/* Returns nonzero if IDENT is the name of a class that the compiler - should assume has been compiled to object code. */ - -static int -assume_compiled (const char *ident) -{ - class_flag_node *i; - int result; - - if (NULL == assume_compiled_tree) - return 1; - - i = find_class_flag_node (assume_compiled_tree, ident); - - result = ! i->value; - - return (result); -} - -/* Return true if we should generate code to check assertions within KLASS. */ - -bool -enable_assertions (tree klass) -{ - /* Check if command-line specifies whether we should check assertions. */ - - if (klass != NULL_TREE && DECL_NAME (klass) && enable_assert_tree != NULL) - { - const char *ident = IDENTIFIER_POINTER (DECL_NAME (klass)); - class_flag_node *node - = find_class_flag_node (enable_assert_tree, ident); - return node->value; - } - - /* The default is to enable assertions if generating class files, - or not optimizing. */ - return DEFAULT_ENABLE_ASSERT; -} - -/* Return an IDENTIFIER_NODE the same as (OLD_NAME, OLD_LENGTH). - except that characters matching OLD_CHAR are substituted by NEW_CHAR. - Also, PREFIX is prepended, and SUFFIX is appended. */ - -tree -ident_subst (const char* old_name, - int old_length, - const char *prefix, - int old_char, - int new_char, - const char *suffix) -{ - int prefix_len = strlen (prefix); - int suffix_len = strlen (suffix); - int i = prefix_len + old_length + suffix_len + 1; - char *buffer = (char *) alloca (i); - - strcpy (buffer, prefix); - for (i = 0; i < old_length; i++) - { - char ch = old_name[i]; - if (ch == old_char) - ch = new_char; - buffer[prefix_len + i] = ch; - } - strcpy (buffer + prefix_len + old_length, suffix); - return get_identifier (buffer); -} - -/* Return an IDENTIFIER_NODE the same as OLD_ID, - except that characters matching OLD_CHAR are substituted by NEW_CHAR. - Also, PREFIX is prepended, and SUFFIX is appended. */ - -tree -identifier_subst (const tree old_id, - const char *prefix, - int old_char, - int new_char, - const char *suffix) -{ - return ident_subst (IDENTIFIER_POINTER (old_id), IDENTIFIER_LENGTH (old_id), - prefix, old_char, new_char, suffix); -} - -/* Generate a valid C identifier from the name of the class TYPE, - prefixed by PREFIX. */ - -tree -mangled_classname (const char *prefix, tree type) -{ - tree result; - tree ident = TYPE_NAME (type); - if (TREE_CODE (ident) != IDENTIFIER_NODE) - ident = DECL_NAME (ident); - result = identifier_subst (ident, prefix, '.', '_', ""); - - /* Replace any characters that aren't in the set [0-9a-zA-Z_$] with - "_0xXX". Class names containing such chracters are uncommon, but - they do sometimes occur in class files. Without this check, - these names cause assembly errors. - - There is a possibility that a real class name could conflict with - the identifier we generate, but it is unlikely and will - immediately be detected as an assembler error. At some point we - should do something more elaborate (perhaps using the full - unicode mangling scheme) in order to prevent such a conflict. */ - { - int i; - const int len = IDENTIFIER_LENGTH (result); - const char *p = IDENTIFIER_POINTER (result); - int illegal_chars = 0; - - /* Make two passes over the identifier. The first pass is merely - to count illegal characters; we need to do this in order to - allocate a buffer. */ - for (i = 0; i < len; i++) - { - char c = p[i]; - illegal_chars += (! ISALNUM (c) && c != '_' && c != '$'); - } - - /* And the second pass, which is rarely executed, does the - rewriting. */ - if (illegal_chars != 0) - { - char *buffer = (char *) alloca (illegal_chars * 4 + len + 1); - int j; - - for (i = 0, j = 0; i < len; i++) - { - char c = p[i]; - if (! ISALNUM (c) && c != '_' && c != '$') - { - buffer[j++] = '_'; - sprintf (&buffer[j], "0x%02x", c); - j += 4; - } - else - buffer[j++] = c; - } - - buffer[j] = 0; - result = get_identifier (buffer); - } - } - - return result; -} - -tree -make_class (void) -{ - tree type; - type = make_node (RECORD_TYPE); - /* Unfortunately we must create the binfo here, so that class - loading works. */ - TYPE_BINFO (type) = make_tree_binfo (0); - MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type); - TYPE_CATCH_CLASSES (type) = NULL; - /* Push a dummy entry; we can't call make_catch_class_record here - because other infrastructure may not be set up yet. We'll come - back and fill it in later once said infrastructure is - initialized. */ - CONSTRUCTOR_APPEND_ELT (TYPE_CATCH_CLASSES (type), NULL_TREE, NULL_TREE); - - return type; -} - -/* Given a fully-qualified classname in NAME (whose length is NAME_LENGTH), - and where each of the constituents is separated by '/', - return a corresponding IDENTIFIER_NODE, except using '.' as separator. */ - -tree -unmangle_classname (const char *name, int name_length) -{ - tree to_return = ident_subst (name, name_length, "", '/', '.', ""); - /* It's not sufficient to compare to_return and get_identifier - (name) to determine whether to_return is qualified. There are - cases in signature analysis where name will be stripped of a - trailing ';'. */ - name = IDENTIFIER_POINTER (to_return); - while (*name) - if (*name++ == '.') - { - QUALIFIED_P (to_return) = 1; - break; - } - - return to_return; -} - -#define GEN_TABLE(TABLE, NAME, TABLE_TYPE, TYPE) \ -do \ -{ \ - const char *type_name = IDENTIFIER_POINTER (mangled_classname ("", TYPE)); \ - char *buf = (char *) alloca (strlen (type_name) \ - + strlen (#NAME "_syms_") + 1); \ - tree decl; \ - \ - sprintf (buf, #NAME "_%s", type_name); \ - TYPE_## TABLE ##_DECL (type) = decl = \ - build_decl (input_location, 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", type_name); \ - TYPE_## TABLE ##_SYMS_DECL (TYPE) = \ - build_decl (input_location, 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; \ -} \ -while (0) - -/* Given a class, create the DECLs for all its associated indirect - dispatch tables. */ -void -gen_indirect_dispatch_tables (tree type) -{ - const char *type_name = IDENTIFIER_POINTER (mangled_classname ("", type)); - { - tree field = NULL; - char *buf = (char *) alloca (strlen (type_name) - + strlen ("_catch_classes_") + 1); - tree catch_class_type = make_node (RECORD_TYPE); - - sprintf (buf, "_catch_classes_%s", type_name); - PUSH_FIELD (input_location, - catch_class_type, field, "address", utf8const_ptr_type); - PUSH_FIELD (input_location, - catch_class_type, field, "classname", ptr_type_node); - FINISH_RECORD (catch_class_type); - - TYPE_CTABLE_DECL (type) - = build_decl (input_location, VAR_DECL, get_identifier (buf), - build_array_type (catch_class_type, 0)); - DECL_EXTERNAL (TYPE_CTABLE_DECL (type)) = 1; - TREE_STATIC (TYPE_CTABLE_DECL (type)) = 1; - TREE_READONLY (TYPE_CTABLE_DECL (type)) = 1; - TREE_CONSTANT (TYPE_CTABLE_DECL (type)) = 1; - DECL_IGNORED_P (TYPE_CTABLE_DECL (type)) = 1; - pushdecl (TYPE_CTABLE_DECL (type)); - } - - if (flag_indirect_dispatch) - { - 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; - CLASS_P (class_type) = 1; - decl = build_decl (input_location, TYPE_DECL, class_name, class_type); - TYPE_DECL_SUPPRESS_DEBUG (decl) = 1; - - /* dbxout needs a DECL_SIZE if in gstabs mode */ - DECL_SIZE (decl) = integer_zero_node; - - input_location = saved_loc; - signature = identifier_subst (class_name, "L", '.', '/', ";"); - IDENTIFIER_SIGNATURE_TYPE (signature) = build_pointer_type (class_type); - - /* Setting DECL_ARTIFICIAL forces dbxout.c to specific the type is - both a typedef and in the struct name-space. We may want to re-visit - this later, but for now it reduces the changes needed for gdb. */ - DECL_ARTIFICIAL (decl) = 1; - - pushdecl_top_level (decl); - - return decl; -} - -/* Finds the (global) class named NAME. Creates the class if not found. - Also creates associated TYPE_DECL. - Does not check if the class actually exists, load the class, - fill in field or methods, or do layout_type. */ - -tree -lookup_class (tree name) -{ - tree decl = IDENTIFIER_CLASS_VALUE (name); - if (decl == NULL_TREE) - decl = push_class (make_class (), name); - return TREE_TYPE (decl); -} - -void -set_super_info (int access_flags, tree this_class, - tree super_class, int interfaces_count) -{ - int total_supers = interfaces_count; - tree class_decl = TYPE_NAME (this_class); - - if (super_class) - total_supers++; - - if (total_supers) - TYPE_BINFO (this_class) = make_tree_binfo (total_supers); - TYPE_VFIELD (this_class) = TYPE_VFIELD (object_type_node); - if (super_class) - { - tree super_binfo = make_tree_binfo (0); - BINFO_TYPE (super_binfo) = super_class; - BINFO_OFFSET (super_binfo) = integer_zero_node; - 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); -} - -void -set_class_decl_access_flags (int access_flags, tree class_decl) -{ - if (access_flags & ACC_PUBLIC) CLASS_PUBLIC (class_decl) = 1; - if (access_flags & ACC_FINAL) CLASS_FINAL (class_decl) = 1; - if (access_flags & ACC_SUPER) CLASS_SUPER (class_decl) = 1; - if (access_flags & ACC_INTERFACE) CLASS_INTERFACE (class_decl) = 1; - if (access_flags & ACC_ABSTRACT) CLASS_ABSTRACT (class_decl) = 1; - if (access_flags & ACC_STATIC) CLASS_STATIC (class_decl) = 1; - if (access_flags & ACC_PRIVATE) CLASS_PRIVATE (class_decl) = 1; - if (access_flags & ACC_PROTECTED) CLASS_PROTECTED (class_decl) = 1; - if (access_flags & ACC_STRICT) CLASS_STRICTFP (class_decl) = 1; - if (access_flags & ACC_ENUM) CLASS_ENUM (class_decl) = 1; - if (access_flags & ACC_SYNTHETIC) CLASS_SYNTHETIC (class_decl) = 1; - if (access_flags & ACC_ANNOTATION) CLASS_ANNOTATION (class_decl) = 1; -} - -/* Return length of inheritance chain of CLAS, where java.lang.Object is 0, - direct sub-classes of Object are 1, and so on. */ - -int -class_depth (tree clas) -{ - int depth = 0; - if (! CLASS_LOADED_P (clas)) - load_class (clas, 1); - if (TYPE_SIZE (clas) == error_mark_node) - return -1; - while (clas != object_type_node) - { - depth++; - clas = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (clas), 0)); - } - return depth; -} - -/* Return true iff TYPE2 is an interface that extends interface TYPE1 */ - -int -interface_of_p (tree type1, tree type2) -{ - int i; - tree binfo, base_binfo; - - if (! TYPE_BINFO (type2)) - return 0; - - 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 true iff TYPE1 inherits from TYPE2. */ - -int -inherits_from_p (tree type1, tree type2) -{ - while (type1 != NULL_TREE && TREE_CODE (type1) == RECORD_TYPE) - { - if (type1 == type2) - return 1; - - if (! CLASS_LOADED_P (type1)) - load_class (type1, 1); - - type1 = maybe_layout_super_class (CLASSTYPE_SUPER (type1), type1); - } - return 0; -} - -/* Return a 1 iff TYPE1 is an enclosing context for TYPE2 */ - -int -enclosing_context_p (tree type1, tree type2) -{ - if (!INNER_CLASS_TYPE_P (type2)) - return 0; - - for (type2 = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type2))); - type2; - type2 = (INNER_CLASS_TYPE_P (type2) ? - TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type2))) : NULL_TREE)) - { - if (type2 == type1) - return 1; - } - - return 0; -} - - -/* 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; - - for (type1 = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type1))); type1; - type1 = (PURE_INNER_CLASS_TYPE_P (type1) ? - TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type1))) : NULL_TREE)) - { - tree current; - for (current = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type2))); current; - current = (PURE_INNER_CLASS_TYPE_P (current) ? - TREE_TYPE (DECL_CONTEXT (TYPE_NAME (current))) : - NULL_TREE)) - if (type1 == current) - return 1; - } - return 0; -} - -/* 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 binfo, base_binfo; - int 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; -} - -/* Add the INTERFACE_CLASS as one of the interfaces of THIS_CLASS. */ - -void -add_interface (tree this_class, tree interface_class) -{ - 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); -} - -static tree -build_java_method_type (tree fntype, tree this_class, int access_flags) -{ - if (access_flags & ACC_STATIC) - return fntype; - fntype = build_method_type (this_class, fntype); - - /* We know that arg 1 of every nonstatic method is non-null; tell - the back-end so. */ - TYPE_ATTRIBUTES (fntype) = (tree_cons - (get_identifier ("nonnull"), - tree_cons (NULL_TREE, - build_int_cst (NULL_TREE, 1), - NULL_TREE), - TYPE_ATTRIBUTES (fntype))); - return fntype; -} - -void -java_hide_decl (tree decl ATTRIBUTE_UNUSED) -{ -#ifdef HAVE_GAS_HIDDEN - DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; - DECL_VISIBILITY_SPECIFIED (decl) = 1; -#endif -} - -tree -add_method_1 (tree this_class, int access_flags, tree name, tree function_type) -{ - tree method_type, fndecl; - - method_type = build_java_method_type (function_type, - this_class, access_flags); - - fndecl = build_decl (input_location, FUNCTION_DECL, name, method_type); - DECL_CONTEXT (fndecl) = this_class; - - DECL_LANG_SPECIFIC (fndecl) = ggc_cleared_alloc<struct lang_decl> (); - DECL_LANG_SPECIFIC (fndecl)->desc = LANG_DECL_FUNC; - - /* Initialize the static initializer test table. */ - - DECL_FUNCTION_INIT_TEST_TABLE (fndecl) = java_treetreehash_create (10); - - /* Initialize the initialized (static) class table. */ - if (access_flags & ACC_STATIC) - DECL_FUNCTION_INITIALIZED_CLASS_TABLE (fndecl) = - hash_table<ict_hasher>::create_ggc (50); - - DECL_CHAIN (fndecl) = TYPE_METHODS (this_class); - TYPE_METHODS (this_class) = fndecl; - - if (!(access_flags & ACC_STATIC)) - SET_DECL_ALIGN (fndecl, MINIMUM_METHOD_BOUNDARY); - - /* Notice that this is a finalizer and update the class type - accordingly. This is used to optimize instance allocation. */ - if (name == finalize_identifier_node - && TREE_TYPE (function_type) == void_type_node - && TREE_VALUE (TYPE_ARG_TYPES (function_type)) == void_type_node) - HAS_FINALIZER_P (this_class) = 1; - - if (access_flags & ACC_PUBLIC) METHOD_PUBLIC (fndecl) = 1; - if (access_flags & ACC_PROTECTED) METHOD_PROTECTED (fndecl) = 1; - if (access_flags & ACC_PRIVATE) - METHOD_PRIVATE (fndecl) = 1; - if (access_flags & ACC_NATIVE) - { - METHOD_NATIVE (fndecl) = 1; - DECL_EXTERNAL (fndecl) = 1; - } - else - /* FNDECL is external unless we are compiling it into this object - file. */ - DECL_EXTERNAL (fndecl) = CLASS_FROM_CURRENTLY_COMPILED_P (this_class) == 0; - if (access_flags & ACC_STATIC) - METHOD_STATIC (fndecl) = 1; - if (access_flags & ACC_FINAL) - METHOD_FINAL (fndecl) = 1; - if (access_flags & ACC_SYNCHRONIZED) METHOD_SYNCHRONIZED (fndecl) = 1; - if (access_flags & ACC_ABSTRACT) METHOD_ABSTRACT (fndecl) = 1; - if (access_flags & ACC_STRICT) METHOD_STRICTFP (fndecl) = 1; - if (access_flags & ACC_SYNTHETIC) DECL_ARTIFICIAL (fndecl) = 1; - if (access_flags & ACC_BRIDGE) METHOD_BRIDGE (fndecl) = 1; - if (access_flags & ACC_VARARGS) METHOD_VARARGS (fndecl) = 1; - return fndecl; -} - -/* Add a method to THIS_CLASS. - The method's name is NAME. - Its signature (mangled type) is METHOD_SIG (an IDENTIFIER_NODE). */ - -tree -add_method (tree this_class, int access_flags, tree name, tree method_sig) -{ - tree function_type, fndecl; - const unsigned char *sig - = (const unsigned char *) IDENTIFIER_POINTER (method_sig); - - if (sig[0] != '(') - fatal_error (input_location, "bad method signature"); - - function_type = get_type_from_signature (method_sig); - fndecl = add_method_1 (this_class, access_flags, name, function_type); - set_java_signature (TREE_TYPE (fndecl), method_sig); - return fndecl; -} - -tree -add_field (tree klass, tree name, tree field_type, int flags) -{ - int is_static = (flags & ACC_STATIC) != 0; - tree field; - field = build_decl (input_location, - is_static ? VAR_DECL : FIELD_DECL, name, field_type); - DECL_CHAIN (field) = TYPE_FIELDS (klass); - TYPE_FIELDS (klass) = field; - DECL_CONTEXT (field) = klass; - MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (field); - - if (flags & ACC_PUBLIC) FIELD_PUBLIC (field) = 1; - if (flags & ACC_PROTECTED) FIELD_PROTECTED (field) = 1; - if (flags & ACC_PRIVATE) FIELD_PRIVATE (field) = 1; - if (flags & ACC_FINAL) FIELD_FINAL (field) = 1; - if (flags & ACC_VOLATILE) - { - FIELD_VOLATILE (field) = 1; - TREE_THIS_VOLATILE (field) = 1; - } - if (flags & ACC_TRANSIENT) FIELD_TRANSIENT (field) = 1; - if (flags & ACC_ENUM) FIELD_ENUM (field) = 1; - if (flags & ACC_SYNTHETIC) FIELD_SYNTHETIC (field) = 1; - if (is_static) - { - FIELD_STATIC (field) = 1; - /* Always make field externally visible. This is required so - that native methods can always access the field. */ - TREE_PUBLIC (field) = 1; - /* Hide everything that shouldn't be visible outside a DSO. */ - if (flag_indirect_classes - || (FIELD_PRIVATE (field))) - java_hide_decl (field); - /* Considered external unless we are compiling it into this - object file. */ - DECL_EXTERNAL (field) = (is_compiled_class (klass) != 2); - } - - return field; -} - -/* Associate a constant value CONSTANT with VAR_DECL FIELD. */ - -void -set_constant_value (tree field, tree constant) -{ - if (field == NULL_TREE) - warning (OPT_Wattributes, - "misplaced ConstantValue attribute (not in any field)"); - else if (DECL_INITIAL (field) != NULL_TREE) - warning (OPT_Wattributes, - "duplicate ConstantValue attribute for field '%s'", - IDENTIFIER_POINTER (DECL_NAME (field))); - else - { - DECL_INITIAL (field) = constant; - if (TREE_TYPE (constant) != TREE_TYPE (field) - && ! (TREE_TYPE (constant) == int_type_node - && INTEGRAL_TYPE_P (TREE_TYPE (field)) - && TYPE_PRECISION (TREE_TYPE (field)) <= 32) - && ! (TREE_TYPE (constant) == utf8const_ptr_type - && TREE_TYPE (field) == string_ptr_type_node)) - error ("ConstantValue attribute of field '%s' has wrong type", - IDENTIFIER_POINTER (DECL_NAME (field))); - } -} - -/* Calculate a hash value for a string encoded in Utf8 format. - * This returns the same hash value as specified for java.lang.String.hashCode. - */ - -static int32 -hashUtf8String (const char *str, int len) -{ - const unsigned char* ptr = (const unsigned char*) str; - const unsigned char *limit = ptr + len; - uint32 hash = 0; - for (; ptr < limit;) - { - int ch = UTF8_GET (ptr, limit); - /* Updated specification from - http://www.javasoft.com/docs/books/jls/clarify.html. */ - hash = (31 * hash) + ch; - } - return hash; -} - -tree -build_utf8_ref (tree name) -{ - const char * name_ptr = IDENTIFIER_POINTER (name); - int name_len = IDENTIFIER_LENGTH (name), name_pad; - char buf[60]; - tree ctype, field = NULL_TREE, str_type, cinit, string; - static int utf8_count = 0; - int name_hash; - tree ref = IDENTIFIER_UTF8_REF (name); - tree decl; - vec<constructor_elt, va_gc> *v = NULL; - if (ref != NULL_TREE) - return ref; - - ctype = make_node (RECORD_TYPE); - /* '\0' byte plus padding to utf8const_type's alignment. */ - name_pad = TYPE_ALIGN_UNIT (utf8const_type) - - (name_len & (TYPE_ALIGN_UNIT (utf8const_type) - 1)); - str_type = build_prim_array_type (unsigned_byte_type_node, - name_len + name_pad); - PUSH_FIELD (input_location, ctype, field, "hash", unsigned_short_type_node); - PUSH_FIELD (input_location, - ctype, field, "length", unsigned_short_type_node); - PUSH_FIELD (input_location, ctype, field, "data", str_type); - FINISH_RECORD (ctype); - START_RECORD_CONSTRUCTOR (v, ctype); - name_hash = hashUtf8String (name_ptr, name_len) & 0xFFFF; - PUSH_FIELD_VALUE (v, "hash", build_int_cst (NULL_TREE, name_hash)); - PUSH_FIELD_VALUE (v, "length", build_int_cst (NULL_TREE, name_len)); - string = build_string (name_len, name_ptr); - TREE_TYPE (string) = str_type; - PUSH_FIELD_VALUE (v, "data", string); - FINISH_RECORD_CONSTRUCTOR (cinit, v, ctype); - TREE_CONSTANT (cinit) = 1; - - /* Generate a unique-enough identifier. */ - sprintf(buf, "_Utf%d", ++utf8_count); - - decl = build_decl (input_location, - VAR_DECL, get_identifier (buf), utf8const_type); - TREE_STATIC (decl) = 1; - DECL_ARTIFICIAL (decl) = 1; - DECL_IGNORED_P (decl) = 1; - TREE_READONLY (decl) = 1; - TREE_THIS_VOLATILE (decl) = 0; - DECL_INITIAL (decl) = cinit; - DECL_USER_ALIGN (decl) = 1; - - if (HAVE_GAS_SHF_MERGE) - { - int decl_size; - /* Ensure decl_size is a multiple of utf8const_type's alignment. */ - decl_size = name_len + 4 + name_pad; - if (flag_merge_constants && decl_size < 256) - { - char buf[32]; - int flags = (SECTION_OVERRIDE - | SECTION_MERGE | (SECTION_ENTSIZE & decl_size)); - sprintf (buf, ".rodata.jutf8.%d", decl_size); - switch_to_section (get_section (buf, flags, NULL)); - set_decl_section_name (decl, buf); - } - } - - layout_decl (decl, 0); - DECL_SIZE (decl) = TYPE_SIZE (ctype); - DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (ctype); - pushdecl (decl); - rest_of_decl_compilation (decl, global_bindings_p (), 0); - ref = build1 (ADDR_EXPR, utf8const_ptr_type, decl); - IDENTIFIER_UTF8_REF (name) = ref; - return ref; -} - -/* Like build_class_ref, but instead of a direct reference generate a - pointer into the constant pool. */ - -static tree -build_indirect_class_ref (tree type) -{ - int index; - tree cl; - index = alloc_class_constant (type); - cl = build_ref_from_constant_pool (index); - return convert (promote_type (class_ptr_type), cl); -} - -static tree -build_static_class_ref (tree type) -{ - tree decl_name, decl, ref; - - if (TYPE_SIZE (type) == error_mark_node) - return null_pointer_node; - decl_name = identifier_subst (DECL_NAME (TYPE_NAME (type)), - "", '/', '/', ".class$$"); - decl = IDENTIFIER_GLOBAL_VALUE (decl_name); - if (decl == NULL_TREE) - { - decl = build_decl (input_location, VAR_DECL, decl_name, class_type_node); - TREE_STATIC (decl) = 1; - if (! flag_indirect_classes) - { - TREE_PUBLIC (decl) = 1; - if (CLASS_PRIVATE (TYPE_NAME (type))) - java_hide_decl (decl); - } - DECL_IGNORED_P (decl) = 1; - DECL_ARTIFICIAL (decl) = 1; - if (is_compiled_class (type) == 1) - DECL_EXTERNAL (decl) = 1; - MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); - DECL_CLASS_FIELD_P (decl) = 1; - DECL_CONTEXT (decl) = type; - - /* ??? We want to preserve the DECL_CONTEXT we set just above, - that means not calling pushdecl_top_level. */ - IDENTIFIER_GLOBAL_VALUE (decl_name) = decl; - } - - ref = build1 (ADDR_EXPR, class_ptr_type, decl); - return ref; -} - -static tree -build_classdollar_field (tree type) -{ - tree decl_name = identifier_subst (DECL_NAME (TYPE_NAME (type)), - "", '/', '/', ".class$"); - tree decl = IDENTIFIER_GLOBAL_VALUE (decl_name); - - if (decl == NULL_TREE) - { - decl - = build_decl (input_location, - VAR_DECL, decl_name, - (build_qualified_type - (build_pointer_type - (build_qualified_type (class_type_node, - TYPE_QUAL_CONST)), - TYPE_QUAL_CONST))); - TREE_STATIC (decl) = 1; - TREE_CONSTANT (decl) = 1; - TREE_PUBLIC (decl) = 1; - java_hide_decl (decl); - DECL_IGNORED_P (decl) = 1; - DECL_ARTIFICIAL (decl) = 1; - MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); - IDENTIFIER_GLOBAL_VALUE (decl_name) = decl; - DECL_CLASS_FIELD_P (decl) = 1; - DECL_CONTEXT (decl) = type; - } - - return decl; -} - -/* Create a local variable that holds the current class$. */ - -void -cache_this_class_ref (tree fndecl) -{ - if (optimize) - { - tree classdollar_field; - if (flag_indirect_classes) - classdollar_field = build_classdollar_field (output_class); - else - classdollar_field = build_static_class_ref (output_class); - - this_classdollar = build_decl (input_location, - VAR_DECL, NULL_TREE, - TREE_TYPE (classdollar_field)); - - java_add_local_var (this_classdollar); - java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (this_classdollar), - this_classdollar, classdollar_field)); - } - else - this_classdollar = build_classdollar_field (output_class); - - /* Prepend class initialization for static methods reachable from - other classes. */ - if (METHOD_STATIC (fndecl) - && (! METHOD_PRIVATE (fndecl) - || INNER_CLASS_P (DECL_CONTEXT (fndecl))) - && ! DECL_CLINIT_P (fndecl) - && ! CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (fndecl)))) - { - tree init = build_call_expr (soft_initclass_node, 1, - this_classdollar); - java_add_stmt (init); - } -} - -/* Remove the reference to the local variable that holds the current - class$. */ - -void -uncache_this_class_ref (tree fndecl ATTRIBUTE_UNUSED) -{ - this_classdollar = build_classdollar_field (output_class); -} - -/* Build a reference to the class TYPE. - Also handles primitive types and array types. */ - -tree -build_class_ref (tree type) -{ - int is_compiled = is_compiled_class (type); - if (is_compiled) - { - tree ref, decl; - if (TREE_CODE (type) == POINTER_TYPE) - type = TREE_TYPE (type); - - if (flag_indirect_dispatch - && type != output_class - && TREE_CODE (type) == RECORD_TYPE) - return build_indirect_class_ref (type); - - if (type == output_class && flag_indirect_classes) - { - /* This can be NULL if we see a JNI stub before we see any - other method. */ - if (! this_classdollar) - this_classdollar = build_classdollar_field (output_class); - return this_classdollar; - } - - if (TREE_CODE (type) == RECORD_TYPE) - return build_static_class_ref (type); - else - { - const char *name; - tree decl_name; - char buffer[25]; - decl_name = TYPE_NAME (type); - if (TREE_CODE (decl_name) == TYPE_DECL) - decl_name = DECL_NAME (decl_name); - name = IDENTIFIER_POINTER (decl_name); - if (strncmp (name, "promoted_", 9) == 0) - name += 9; - sprintf (buffer, "_Jv_%sClass", name); - decl_name = get_identifier (buffer); - decl = IDENTIFIER_GLOBAL_VALUE (decl_name); - if (decl == NULL_TREE) - { - decl = build_decl (input_location, - VAR_DECL, decl_name, class_type_node); - TREE_STATIC (decl) = 1; - TREE_PUBLIC (decl) = 1; - DECL_EXTERNAL (decl) = 1; - DECL_ARTIFICIAL (decl) = 1; - pushdecl_top_level (decl); - } - } - - ref = build1 (ADDR_EXPR, class_ptr_type, decl); - return ref; - } - else - return build_indirect_class_ref (type); -} - -/* Create a local statically allocated variable that will hold a - pointer to a static field. */ - -static tree -build_fieldref_cache_entry (int index, tree fdecl ATTRIBUTE_UNUSED) -{ - tree decl, decl_name; - const char *name = IDENTIFIER_POINTER (mangled_classname ("_cpool_", output_class)); - char *buf = (char *) alloca (strlen (name) + 20); - sprintf (buf, "%s_%d_ref", name, index); - decl_name = get_identifier (buf); - decl = IDENTIFIER_GLOBAL_VALUE (decl_name); - if (decl == NULL_TREE) - { - decl = build_decl (input_location, - VAR_DECL, decl_name, ptr_type_node); - TREE_STATIC (decl) = 1; - TREE_PUBLIC (decl) = 0; - DECL_EXTERNAL (decl) = 0; - DECL_ARTIFICIAL (decl) = 1; - DECL_IGNORED_P (decl) = 1; - pushdecl_top_level (decl); - } - return decl; -} - -tree -build_static_field_ref (tree fdecl) -{ - tree fclass = DECL_CONTEXT (fdecl); - int is_compiled = is_compiled_class (fclass); - - /* Allow static final fields to fold to a constant. When using - -findirect-dispatch, we simply never do this folding if compiling - from .class; in the .class file constants will be referred to via - the constant pool. */ - if (!flag_indirect_dispatch - && (is_compiled - || (FIELD_FINAL (fdecl) && DECL_INITIAL (fdecl) != NULL_TREE - && (JSTRING_TYPE_P (TREE_TYPE (fdecl)) - || JNUMERIC_TYPE_P (TREE_TYPE (fdecl))) - && TREE_CONSTANT (DECL_INITIAL (fdecl))))) - { - if (is_compiled == 1) - DECL_EXTERNAL (fdecl) = 1; - } - else - { - /* Generate a CONSTANT_FieldRef for FDECL in the constant pool - and a class local static variable CACHE_ENTRY, then - - *(fdecl **)((__builtin_expect (cache_entry == null, false)) - ? cache_entry = _Jv_ResolvePoolEntry (output_class, cpool_index) - : cache_entry) - - This can mostly be optimized away, so that the usual path is a - load followed by a test and branch. _Jv_ResolvePoolEntry is - only called once for each constant pool entry. - - There is an optimization that we don't do: at the start of a - method, create a local copy of CACHE_ENTRY and use that instead. - - */ - - int cpool_index = alloc_constant_fieldref (output_class, fdecl); - tree cache_entry = build_fieldref_cache_entry (cpool_index, fdecl); - tree test - = build_call_expr (builtin_decl_implicit (BUILT_IN_EXPECT), 2, - build2 (EQ_EXPR, boolean_type_node, - cache_entry, null_pointer_node), - boolean_false_node); - tree cpool_index_cst = build_int_cst (NULL_TREE, cpool_index); - tree init - = build_call_expr (soft_resolvepoolentry_node, 2, - build_class_ref (output_class), - cpool_index_cst); - init = build2 (MODIFY_EXPR, ptr_type_node, cache_entry, init); - init = build3 (COND_EXPR, ptr_type_node, test, init, cache_entry); - init = fold_convert (build_pointer_type (TREE_TYPE (fdecl)), init); - fdecl = build1 (INDIRECT_REF, TREE_TYPE (fdecl), init); - } - return fdecl; -} - -int -get_access_flags_from_decl (tree decl) -{ - int access_flags = 0; - if (TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL) - { - if (FIELD_STATIC (decl)) - access_flags |= ACC_STATIC; - if (FIELD_PUBLIC (decl)) - access_flags |= ACC_PUBLIC; - if (FIELD_PROTECTED (decl)) - access_flags |= ACC_PROTECTED; - if (FIELD_PRIVATE (decl)) - access_flags |= ACC_PRIVATE; - if (FIELD_FINAL (decl)) - access_flags |= ACC_FINAL; - if (FIELD_VOLATILE (decl)) - access_flags |= ACC_VOLATILE; - if (FIELD_TRANSIENT (decl)) - access_flags |= ACC_TRANSIENT; - if (FIELD_ENUM (decl)) - access_flags |= ACC_ENUM; - if (FIELD_SYNTHETIC (decl)) - access_flags |= ACC_SYNTHETIC; - return access_flags; - } - if (TREE_CODE (decl) == TYPE_DECL) - { - if (CLASS_PUBLIC (decl)) - access_flags |= ACC_PUBLIC; - if (CLASS_FINAL (decl)) - access_flags |= ACC_FINAL; - if (CLASS_SUPER (decl)) - access_flags |= ACC_SUPER; - if (CLASS_INTERFACE (decl)) - access_flags |= ACC_INTERFACE; - if (CLASS_ABSTRACT (decl)) - access_flags |= ACC_ABSTRACT; - if (CLASS_STATIC (decl)) - access_flags |= ACC_STATIC; - if (CLASS_PRIVATE (decl)) - access_flags |= ACC_PRIVATE; - if (CLASS_PROTECTED (decl)) - access_flags |= ACC_PROTECTED; - if (CLASS_STRICTFP (decl)) - access_flags |= ACC_STRICT; - if (CLASS_ENUM (decl)) - access_flags |= ACC_ENUM; - if (CLASS_SYNTHETIC (decl)) - access_flags |= ACC_SYNTHETIC; - if (CLASS_ANNOTATION (decl)) - access_flags |= ACC_ANNOTATION; - return access_flags; - } - if (TREE_CODE (decl) == FUNCTION_DECL) - { - if (METHOD_PUBLIC (decl)) - access_flags |= ACC_PUBLIC; - if (METHOD_PRIVATE (decl)) - access_flags |= ACC_PRIVATE; - if (METHOD_PROTECTED (decl)) - access_flags |= ACC_PROTECTED; - if (METHOD_STATIC (decl)) - access_flags |= ACC_STATIC; - if (METHOD_FINAL (decl)) - access_flags |= ACC_FINAL; - if (METHOD_SYNCHRONIZED (decl)) - access_flags |= ACC_SYNCHRONIZED; - if (METHOD_NATIVE (decl)) - access_flags |= ACC_NATIVE; - if (METHOD_ABSTRACT (decl)) - access_flags |= ACC_ABSTRACT; - if (METHOD_STRICTFP (decl)) - access_flags |= ACC_STRICT; - if (METHOD_INVISIBLE (decl)) - access_flags |= ACC_INVISIBLE; - if (DECL_ARTIFICIAL (decl)) - access_flags |= ACC_SYNTHETIC; - if (METHOD_BRIDGE (decl)) - access_flags |= ACC_BRIDGE; - if (METHOD_VARARGS (decl)) - access_flags |= ACC_VARARGS; - return access_flags; - } - gcc_unreachable (); -} - -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 = (char *) alloca (strlen (method_name) + 2); - char *buf = (char *) 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); - - targetm.asm_out.generate_internal_label (buf, name, alias_labelno++); - alias = build_decl (input_location, - 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_INITIAL (alias) = error_mark_node; - TREE_ADDRESSABLE (alias) = 1; - TREE_USED (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) -{ - tree finit; - int flags; - tree type = TREE_TYPE (fdecl); - int resolved = is_compiled_class (type) && ! flag_indirect_dispatch; - vec<constructor_elt, va_gc> *v = NULL; - - START_RECORD_CONSTRUCTOR (v, field_type_node); - PUSH_FIELD_VALUE (v, "name", build_utf8_ref (DECL_NAME (fdecl))); - if (resolved) - type = build_class_ref (type); - else - { - tree signature = build_java_signature (type); - - type = build_utf8_ref (unmangle_classname - (IDENTIFIER_POINTER (signature), - IDENTIFIER_LENGTH (signature))); - } - PUSH_FIELD_VALUE (v, "type", type); - - flags = get_access_flags_from_decl (fdecl); - if (! resolved) - flags |= 0x8000 /* FIELD_UNRESOLVED_FLAG */; - - PUSH_FIELD_VALUE (v, "accflags", build_int_cst (NULL_TREE, flags)); - PUSH_FIELD_VALUE (v, "bsize", TYPE_SIZE_UNIT (TREE_TYPE (fdecl))); - - { - tree field_address = integer_zero_node; - tree index, value; - if ((DECL_INITIAL (fdecl) || ! flag_indirect_classes) - && FIELD_STATIC (fdecl)) - field_address = build_address_of (fdecl); - - index = (FIELD_STATIC (fdecl) - ? DECL_CHAIN (TYPE_FIELDS (field_info_union_node)) - : TYPE_FIELDS (field_info_union_node)); - value = (FIELD_STATIC (fdecl) - ? field_address - : byte_position (fdecl)); - - PUSH_FIELD_VALUE - (v, "info", - build_constructor_single (field_info_union_node, index, value)); - } - - FINISH_RECORD_CONSTRUCTOR (finit, v, field_type_node); - return finit; -} - -/** Make reflection data (_Jv_Method) for method MDECL. */ - -static tree -make_method_value (tree mdecl) -{ - static int method_name_count = 0; - tree minit; - tree index; - tree code; - tree class_decl; -#define ACC_TRANSLATED 0x4000 - int accflags = get_access_flags_from_decl (mdecl) | ACC_TRANSLATED; - vec<constructor_elt, va_gc> *v = NULL; - - class_decl = DECL_CONTEXT (mdecl); - /* For interfaces, the index field contains the dispatch index. */ - if (CLASS_INTERFACE (TYPE_NAME (class_decl))) - 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 - index = integer_minus_one_node; - - code = null_pointer_node; - if (METHOD_ABSTRACT (mdecl)) - code = build1 (ADDR_EXPR, nativecode_ptr_type_node, - soft_abstractmethod_node); - else - code = build1 (ADDR_EXPR, nativecode_ptr_type_node, - make_local_function_alias (mdecl)); - START_RECORD_CONSTRUCTOR (v, method_type_node); - PUSH_FIELD_VALUE (v, "name", - build_utf8_ref (DECL_CONSTRUCTOR_P (mdecl) ? - init_identifier_node - : DECL_NAME (mdecl))); - { - tree signature = build_java_signature (TREE_TYPE (mdecl)); - PUSH_FIELD_VALUE (v, "signature", - (build_utf8_ref - (unmangle_classname - (IDENTIFIER_POINTER(signature), - IDENTIFIER_LENGTH(signature))))); - } - PUSH_FIELD_VALUE (v, "accflags", build_int_cst (NULL_TREE, accflags)); - PUSH_FIELD_VALUE (v, "index", index); - PUSH_FIELD_VALUE (v, "ncode", code); - - { - /* Compute the `throws' information for the method. */ - tree table = null_pointer_node; - - if (!vec_safe_is_empty (DECL_FUNCTION_THROWS (mdecl))) - { - int length = 1 + DECL_FUNCTION_THROWS (mdecl)->length (); - tree t, type, array; - char buf[60]; - vec<constructor_elt, va_gc> *v = NULL; - int idx = length - 1; - unsigned ix; - constructor_elt *e; - - vec_alloc (v, length); - v->quick_grow_cleared (length); - - e = &(*v)[idx--]; - e->value = null_pointer_node; - - FOR_EACH_VEC_SAFE_ELT (DECL_FUNCTION_THROWS (mdecl), ix, t) - { - tree sig = DECL_NAME (TYPE_NAME (t)); - tree utf8 - = build_utf8_ref (unmangle_classname (IDENTIFIER_POINTER (sig), - IDENTIFIER_LENGTH (sig))); - e = &(*v)[idx--]; - e->value = utf8; - } - gcc_assert (idx == -1); - type = build_prim_array_type (ptr_type_node, length); - table = build_constructor (type, v); - /* Compute something unique enough. */ - sprintf (buf, "_methods%d", method_name_count++); - array = build_decl (input_location, - VAR_DECL, get_identifier (buf), type); - DECL_INITIAL (array) = table; - TREE_STATIC (array) = 1; - DECL_ARTIFICIAL (array) = 1; - DECL_IGNORED_P (array) = 1; - rest_of_decl_compilation (array, 1, 0); - - table = build1 (ADDR_EXPR, ptr_type_node, array); - } - - PUSH_FIELD_VALUE (v, "throws", table); - } - - FINISH_RECORD_CONSTRUCTOR (minit, v, method_type_node); - return minit; -} - -static tree -get_dispatch_vector (tree type) -{ - tree vtable = TYPE_VTABLE (type); - - if (vtable == NULL_TREE) - { - HOST_WIDE_INT i; - tree method; - tree super = CLASSTYPE_SUPER (type); - HOST_WIDE_INT nvirtuals = tree_to_shwi (TYPE_NVIRTUALS (type)); - vtable = make_tree_vec (nvirtuals); - TYPE_VTABLE (type) = vtable; - if (super != NULL_TREE) - { - tree super_vtable = get_dispatch_vector (super); - - for (i = tree_to_shwi (TYPE_NVIRTUALS (super)); --i >= 0; ) - TREE_VEC_ELT (vtable, i) = TREE_VEC_ELT (super_vtable, i); - } - - for (method = TYPE_METHODS (type); method != NULL_TREE; - method = DECL_CHAIN (method)) - { - tree method_index = get_method_index (method); - if (method_index != NULL_TREE - && tree_fits_shwi_p (method_index)) - TREE_VEC_ELT (vtable, tree_to_shwi (method_index)) = method; - } - } - - return vtable; -} - -static tree -get_dispatch_table (tree type, tree this_class_addr) -{ - int abstract_p = CLASS_ABSTRACT (TYPE_NAME (type)); - tree vtable = get_dispatch_vector (type); - int i, j; - int nvirtuals = TREE_VEC_LENGTH (vtable); - int arraysize; - tree gc_descr; - vec<constructor_elt, va_gc> *v = NULL; - constructor_elt *e; - tree arraytype; - - arraysize = (TARGET_VTABLE_USES_DESCRIPTORS? nvirtuals + 1 : nvirtuals + 2); - if (TARGET_VTABLE_USES_DESCRIPTORS) - arraysize *= TARGET_VTABLE_USES_DESCRIPTORS; - arraysize += 2; - - vec_safe_grow_cleared (v, arraysize); - e = &(*v)[arraysize - 1]; - -#define CONSTRUCTOR_PREPEND_VALUE(E, V) E->value = V, E-- - for (i = nvirtuals; --i >= 0; ) - { - tree method = TREE_VEC_ELT (vtable, i); - if (METHOD_ABSTRACT (method)) - { - if (! abstract_p) - warning_at (DECL_SOURCE_LOCATION (method), 0, - "abstract method in non-abstract class"); - - if (TARGET_VTABLE_USES_DESCRIPTORS) - for (j = 0; j < TARGET_VTABLE_USES_DESCRIPTORS; ++j) - CONSTRUCTOR_PREPEND_VALUE (e, null_pointer_node); - else - CONSTRUCTOR_PREPEND_VALUE (e, null_pointer_node); - } - else - { - if (TARGET_VTABLE_USES_DESCRIPTORS) - for (j = 0; j < TARGET_VTABLE_USES_DESCRIPTORS; ++j) - { - tree fdesc = build2 (FDESC_EXPR, nativecode_ptr_type_node, - method, build_int_cst (NULL_TREE, j)); - TREE_CONSTANT (fdesc) = 1; - CONSTRUCTOR_PREPEND_VALUE (e, fdesc); - } - else - CONSTRUCTOR_PREPEND_VALUE (e, - build1 (ADDR_EXPR, - nativecode_ptr_type_node, - method)); - } - } - - /* Dummy entry for compatibility with G++ -fvtable-thunks. When - using the Boehm GC we sometimes stash a GC type descriptor - there. We set the PURPOSE to NULL_TREE not to interfere (reset) - the emitted byte count during the output to the assembly file. */ - /* With TARGET_VTABLE_USES_DESCRIPTORS, we only add one extra - fake "function descriptor". It's first word is the is the class - pointer, and subsequent words (usually one) contain the GC descriptor. - In all other cases, we reserve two extra vtable slots. */ - gc_descr = get_boehm_type_descriptor (type); - CONSTRUCTOR_PREPEND_VALUE (e, gc_descr); - for (j = 1; j < TARGET_VTABLE_USES_DESCRIPTORS-1; ++j) - CONSTRUCTOR_PREPEND_VALUE (e, gc_descr); - CONSTRUCTOR_PREPEND_VALUE (e, this_class_addr); - - /** Pointer to type_info object (to be implemented), according to g++ ABI. */ - CONSTRUCTOR_PREPEND_VALUE (e, null_pointer_node); - /** Offset to start of whole object. Always (ptrdiff_t)0 for Java. */ - gcc_assert (e == v->address ()); - e->index = integer_zero_node; - e->value = null_pointer_node; -#undef CONSTRUCTOR_PREPEND_VALUE - - arraytype = build_prim_array_type (nativecode_ptr_type_node, arraysize); - return build_constructor (arraytype, v); -} - - -/* Set the method_index for a method decl. */ -void -set_method_index (tree decl, tree method_index) -{ - if (method_index != NULL_TREE) - { - /* method_index is null if we're using indirect dispatch. */ - method_index = fold (convert (sizetype, method_index)); - - if (TARGET_VTABLE_USES_DESCRIPTORS) - /* Add one to skip bogus descriptor for class and GC descriptor. */ - method_index = size_binop (PLUS_EXPR, method_index, size_int (1)); - else - /* Add 1 to skip "class" field of dtable, and 1 to skip GC - descriptor. */ - method_index = size_binop (PLUS_EXPR, method_index, size_int (2)); - } - - DECL_VINDEX (decl) = method_index; -} - -/* Get the method_index for a method decl. */ -tree -get_method_index (tree decl) -{ - tree method_index = DECL_VINDEX (decl); - - if (! method_index) - return NULL; - - if (TARGET_VTABLE_USES_DESCRIPTORS) - /* Sub one to skip bogus descriptor for class and GC descriptor. */ - method_index = size_binop (MINUS_EXPR, method_index, size_int (1)); - else - /* Sub 1 to skip "class" field of dtable, and 1 to skip GC descriptor. */ - method_index = size_binop (MINUS_EXPR, method_index, size_int (2)); - - return method_index; -} - -static int -supers_all_compiled (tree type) -{ - while (type != NULL_TREE) - { - if (!assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))))) - return 0; - type = CLASSTYPE_SUPER (type); - } - return 1; -} - -static void -add_table_and_syms (vec<constructor_elt, va_gc> **v, - vec<method_entry, va_gc> *methods, - const char *table_name, tree table_slot, tree table_type, - const char *syms_name, tree syms_slot) -{ - if (methods == NULL) - { - PUSH_FIELD_VALUE (*v, table_name, null_pointer_node); - PUSH_FIELD_VALUE (*v, syms_name, null_pointer_node); - } - else - { - pushdecl_top_level (syms_slot); - PUSH_FIELD_VALUE (*v, table_name, - build1 (ADDR_EXPR, table_type, table_slot)); - PUSH_FIELD_VALUE (*v, syms_name, - build1 (ADDR_EXPR, symbols_array_ptr_type, - syms_slot)); - TREE_CONSTANT (table_slot) = 1; - } -} - -void -make_class_data (tree type) -{ - tree decl, cons, temp; - tree field, fields_decl; - HOST_WIDE_INT static_field_count = 0; - HOST_WIDE_INT instance_field_count = 0; - HOST_WIDE_INT field_count; - tree field_array_type; - tree method; - tree dtable_decl = NULL_TREE; - HOST_WIDE_INT method_count = 0; - tree method_array_type; - tree methods_decl; - tree super; - tree this_class_addr; - tree constant_pool_constructor; - tree interfaces = null_pointer_node; - int interface_len = 0; - int uses_jv_markobj = 0; - tree type_decl = TYPE_NAME (type); - tree id_main = get_identifier("main"); - tree id_class = get_identifier("java.lang.Class"); - /** Offset from start of virtual function table declaration - to where objects actually point at, following new g++ ABI. */ - tree dtable_start_offset = size_int (2 * POINTER_SIZE / BITS_PER_UNIT); - vec<int> field_indexes; - tree first_real_field; - vec<constructor_elt, va_gc> *v1 = NULL, *v2 = NULL; - tree reflection_data; - vec<constructor_elt, va_gc> *static_fields = NULL; - vec<constructor_elt, va_gc> *instance_fields = NULL; - vec<constructor_elt, va_gc> *methods = NULL; - - this_class_addr = build_static_class_ref (type); - decl = TREE_OPERAND (this_class_addr, 0); - - if (supers_all_compiled (type) && ! CLASS_INTERFACE (type_decl) - && !flag_indirect_dispatch) - { - tree dtable = get_dispatch_table (type, this_class_addr); - uses_jv_markobj = uses_jv_markobj_p (dtable); - if (type == class_type_node && class_dtable_decl != NULL_TREE) - { - /* We've already created some other class, and consequently - we made class_dtable_decl. Now we just want to fill it - in. */ - dtable_decl = class_dtable_decl; - } - else - { - dtable_decl = build_dtable_decl (type); - TREE_STATIC (dtable_decl) = 1; - DECL_ARTIFICIAL (dtable_decl) = 1; - DECL_IGNORED_P (dtable_decl) = 1; - } - - TREE_PUBLIC (dtable_decl) = 1; - DECL_INITIAL (dtable_decl) = dtable; - /* The only dispatch table exported from a DSO is the dispatch - table for java.lang.Class. */ - if (DECL_NAME (type_decl) != id_class) - java_hide_decl (dtable_decl); - if (! flag_indirect_classes) - rest_of_decl_compilation (dtable_decl, 1, 0); - /* Maybe we're compiling Class as the first class. If so, set - class_dtable_decl to the decl we just made. */ - if (type == class_type_node && class_dtable_decl == NULL_TREE) - class_dtable_decl = dtable_decl; - } - - /* Build Field array. */ - field = TYPE_FIELDS (type); - while (field && DECL_ARTIFICIAL (field)) - field = DECL_CHAIN (field); /* Skip dummy fields. */ - if (field && DECL_NAME (field) == NULL_TREE) - field = DECL_CHAIN (field); /* Skip dummy field for inherited data. */ - first_real_field = field; - - /* First count static and instance fields. */ - for ( ; field != NULL_TREE; field = DECL_CHAIN (field)) - { - if (! DECL_ARTIFICIAL (field)) - { - if (FIELD_STATIC (field)) - static_field_count++; - else if (uses_jv_markobj || !flag_reduced_reflection) - instance_field_count++; - } - } - field_count = static_field_count + instance_field_count; - field_indexes.create (field_count); - - /* gcj sorts fields so that static fields come first, followed by - instance fields. Unfortunately, by the time this takes place we - have already generated the reflection_data for this class, and - that data contains indexes into the fields. So, we generate a - permutation that maps each original field index to its final - position. Then we pass this permutation to - rewrite_reflection_indexes(), which fixes up the reflection - data. */ - { - int i; - int static_count = 0; - int instance_count = static_field_count; - int field_index; - - for (i = 0, field = first_real_field; - field != NULL_TREE; - field = DECL_CHAIN (field), i++) - { - if (! DECL_ARTIFICIAL (field)) - { - field_index = 0; - if (FIELD_STATIC (field)) - field_index = static_count++; - else if (uses_jv_markobj || !flag_reduced_reflection) - field_index = instance_count++; - else - continue; - field_indexes.quick_push (field_index); - } - } - } - - for (field = first_real_field; field != NULL_TREE; - field = DECL_CHAIN (field)) - { - if (! DECL_ARTIFICIAL (field)) - { - if (FIELD_STATIC (field)) - { - /* We must always create reflection data for static fields - as it is used in the creation of the field itself. */ - tree init = make_field_value (field); - tree initial = DECL_INITIAL (field); - CONSTRUCTOR_APPEND_ELT (static_fields, NULL_TREE, init); - /* If the initial value is a string constant, - prevent output_constant from trying to assemble the value. */ - if (initial != NULL_TREE - && TREE_TYPE (initial) == string_ptr_type_node) - DECL_INITIAL (field) = NULL_TREE; - rest_of_decl_compilation (field, 1, 1); - DECL_INITIAL (field) = initial; - } - else if (uses_jv_markobj || !flag_reduced_reflection) - { - tree init = make_field_value (field); - CONSTRUCTOR_APPEND_ELT (instance_fields, NULL_TREE, init); - } - } - } - - gcc_assert (static_field_count == (int) vec_safe_length (static_fields)); - gcc_assert (instance_field_count == (int) vec_safe_length (instance_fields)); - - if (field_count > 0) - { - vec_safe_splice (static_fields, instance_fields); - field_array_type = build_prim_array_type (field_type_node, field_count); - fields_decl = build_decl (input_location, - VAR_DECL, mangled_classname ("_FL_", type), - field_array_type); - DECL_INITIAL (fields_decl) - = build_constructor (field_array_type, static_fields); - TREE_STATIC (fields_decl) = 1; - DECL_ARTIFICIAL (fields_decl) = 1; - DECL_IGNORED_P (fields_decl) = 1; - rest_of_decl_compilation (fields_decl, 1, 0); - } - else - fields_decl = NULL_TREE; - - /* Build Method array. */ - for (method = TYPE_METHODS (type); - method != NULL_TREE; method = DECL_CHAIN (method)) - { - tree init; - if (METHOD_PRIVATE (method) - && ! flag_keep_inline_functions - && 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; - - /* Generate method reflection data if: - - - !flag_reduced_reflection. - - - <clinit> -- The runtime uses reflection to initialize the - class. - - - Any method in class java.lang.Class -- Class.forName() and - perhaps other things require it. - - - class$ -- It does not work if reflection data missing. - - - main -- Reflection is used to find main(String[]) methods. - - - public not static -- It is potentially part of an - interface. The runtime uses reflection data to build - interface dispatch tables. */ - if (!flag_reduced_reflection - || DECL_CLINIT_P (method) - || DECL_NAME (type_decl) == id_class - || DECL_NAME (method) == id_main - || (METHOD_PUBLIC (method) && !METHOD_STATIC (method))) - { - init = make_method_value (method); - method_count++; - CONSTRUCTOR_APPEND_ELT (methods, NULL_TREE, init); - } - } - method_array_type = build_prim_array_type (method_type_node, method_count); - methods_decl = build_decl (input_location, - VAR_DECL, mangled_classname ("_MT_", type), - method_array_type); - DECL_INITIAL (methods_decl) = build_constructor (method_array_type, methods); - TREE_STATIC (methods_decl) = 1; - DECL_ARTIFICIAL (methods_decl) = 1; - DECL_IGNORED_P (methods_decl) = 1; - rest_of_decl_compilation (methods_decl, 1, 0); - - if (class_dtable_decl == NULL_TREE) - { - class_dtable_decl = build_dtable_decl (class_type_node); - TREE_STATIC (class_dtable_decl) = 1; - DECL_ARTIFICIAL (class_dtable_decl) = 1; - 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, 1, 0); - } - } - - super = CLASSTYPE_SUPER (type); - if (super == NULL_TREE) - super = null_pointer_node; - 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_cst (ptr_type_node, super_index); - } - - /* Build and emit the array of implemented interfaces. */ - if (type != object_type_node) - interface_len = BINFO_N_BASE_BINFOS (TYPE_BINFO (type)) - 1; - - if (interface_len > 0) - { - int i; - tree interface_array_type, idecl; - vec<constructor_elt, va_gc> *init; - vec_alloc (init, interface_len); - interface_array_type - = build_prim_array_type (class_ptr_type, interface_len); - idecl = build_decl (input_location, - VAR_DECL, mangled_classname ("_IF_", type), - interface_array_type); - - for (i = 1; i <= interface_len; i++) - { - tree child = BINFO_BASE_BINFO (TYPE_BINFO (type), i); - tree iclass = BINFO_TYPE (child); - tree index; - if (! flag_indirect_dispatch - && (assume_compiled - (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (iclass)))))) - index = build_class_ref (iclass); - else - { - int int_index = alloc_class_constant (iclass); - index = build_int_cst (ptr_type_node, int_index); - } - CONSTRUCTOR_APPEND_ELT (init, NULL_TREE, index); - } - DECL_INITIAL (idecl) = build_constructor (interface_array_type, init); - TREE_STATIC (idecl) = 1; - DECL_ARTIFICIAL (idecl) = 1; - DECL_IGNORED_P (idecl) = 1; - interfaces = build1 (ADDR_EXPR, ptr_type_node, idecl); - rest_of_decl_compilation (idecl, 1, 0); - } - - constant_pool_constructor = build_constants_constructor (); - - if (flag_indirect_dispatch) - { - TYPE_OTABLE_DECL (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, 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, 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 (v1, object_type_node); - PUSH_FIELD_VALUE (v1, "vtable", - (flag_indirect_classes - ? null_pointer_node - : fold_build_pointer_plus - (build1 (ADDR_EXPR, dtable_ptr_type, - class_dtable_decl), - dtable_start_offset))); - if (! flag_hash_synchronization) - PUSH_FIELD_VALUE (v1, "sync_info", null_pointer_node); - FINISH_RECORD_CONSTRUCTOR (temp, v1, object_type_node); - START_RECORD_CONSTRUCTOR (v2, class_type_node); - PUSH_SUPER_VALUE (v2, temp); - PUSH_FIELD_VALUE (v2, "next_or_version", gcj_abi_version); - PUSH_FIELD_VALUE (v2, "name", build_utf8_ref (DECL_NAME (type_decl))); - PUSH_FIELD_VALUE (v2, "accflags", - build_int_cst (NULL_TREE, - get_access_flags_from_decl (type_decl))); - - PUSH_FIELD_VALUE (v2, "superclass", - CLASS_INTERFACE (type_decl) ? null_pointer_node : super); - PUSH_FIELD_VALUE (v2, "constants", constant_pool_constructor); - PUSH_FIELD_VALUE (v2, "methods", - methods_decl == NULL_TREE ? null_pointer_node - : build1 (ADDR_EXPR, method_ptr_type_node, methods_decl)); - PUSH_FIELD_VALUE (v2, "method_count", - build_int_cst (NULL_TREE, method_count)); - - PUSH_FIELD_VALUE (v2, "vtable_method_count", - (flag_indirect_dispatch - ? integer_minus_one_node - : TYPE_NVIRTUALS (type))); - - PUSH_FIELD_VALUE (v2, "fields", - fields_decl == NULL_TREE ? null_pointer_node - : build1 (ADDR_EXPR, field_ptr_type_node, fields_decl)); - /* If we're using the binary compatibility ABI we don't know the - size until load time. */ - PUSH_FIELD_VALUE (v2, "size_in_bytes", - (flag_indirect_dispatch - ? integer_minus_one_node - : size_in_bytes (type))); - PUSH_FIELD_VALUE (v2, "field_count", - build_int_cst (NULL_TREE, field_count)); - PUSH_FIELD_VALUE (v2, "static_field_count", - build_int_cst (NULL_TREE, static_field_count)); - - PUSH_FIELD_VALUE (v2, "vtable", - (flag_indirect_dispatch || dtable_decl == NULL_TREE - ? null_pointer_node - : fold_build_pointer_plus - (build1 (ADDR_EXPR, dtable_ptr_type, - dtable_decl), - dtable_start_offset))); - add_table_and_syms (&v2, TYPE_OTABLE_METHODS (type), - "otable", TYPE_OTABLE_DECL (type), otable_ptr_type, - "otable_syms", TYPE_OTABLE_SYMS_DECL (type)); - add_table_and_syms (&v2, TYPE_ATABLE_METHODS (type), - "atable", TYPE_ATABLE_DECL (type), atable_ptr_type, - "atable_syms", TYPE_ATABLE_SYMS_DECL (type)); - add_table_and_syms (&v2, TYPE_ITABLE_METHODS (type), - "itable", TYPE_ITABLE_DECL (type), itable_ptr_type, - "itable_syms", TYPE_ITABLE_SYMS_DECL (type)); - - PUSH_FIELD_VALUE (v2, "catch_classes", - build1 (ADDR_EXPR, ptr_type_node, TYPE_CTABLE_DECL (type))); - PUSH_FIELD_VALUE (v2, "interfaces", interfaces); - PUSH_FIELD_VALUE (v2, "loader", null_pointer_node); - PUSH_FIELD_VALUE (v2, "interface_count", - build_int_cst (NULL_TREE, interface_len)); - PUSH_FIELD_VALUE (v2, "state", - convert (byte_type_node, - build_int_cst (NULL_TREE, JV_STATE_PRELOADING))); - - PUSH_FIELD_VALUE (v2, "thread", null_pointer_node); - PUSH_FIELD_VALUE (v2, "depth", integer_zero_node); - PUSH_FIELD_VALUE (v2, "ancestors", null_pointer_node); - PUSH_FIELD_VALUE (v2, "idt", null_pointer_node); - PUSH_FIELD_VALUE (v2, "arrayclass", null_pointer_node); - PUSH_FIELD_VALUE (v2, "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 (v2, "assertion_table", assertion_table_ref); - } - - PUSH_FIELD_VALUE (v2, "hack_signers", null_pointer_node); - PUSH_FIELD_VALUE (v2, "chain", null_pointer_node); - PUSH_FIELD_VALUE (v2, "aux_info", null_pointer_node); - PUSH_FIELD_VALUE (v2, "engine", null_pointer_node); - - if (TYPE_REFLECTION_DATA (current_class)) - { - int i; - int count = TYPE_REFLECTION_DATASIZE (current_class); - vec<constructor_elt, va_gc> *v; - vec_alloc (v, count); - unsigned char *data = TYPE_REFLECTION_DATA (current_class); - tree max_index = build_int_cst (sizetype, count); - tree index = build_index_type (max_index); - tree type = build_array_type (unsigned_byte_type_node, index); - char buf[64]; - tree array; - static int reflection_data_count; - - sprintf (buf, "_reflection_data_%d", reflection_data_count++); - array = build_decl (input_location, - VAR_DECL, get_identifier (buf), type); - - rewrite_reflection_indexes (&field_indexes); - - for (i = 0; i < count; i++) - { - constructor_elt elt; - elt.index = build_int_cst (sizetype, i); - elt.value = build_int_cstu (byte_type_node, data[i]); - v->quick_push (elt); - } - - DECL_INITIAL (array) = build_constructor (type, v); - TREE_STATIC (array) = 1; - DECL_ARTIFICIAL (array) = 1; - DECL_IGNORED_P (array) = 1; - TREE_READONLY (array) = 1; - TREE_CONSTANT (DECL_INITIAL (array)) = 1; - rest_of_decl_compilation (array, 1, 0); - - reflection_data = build_address_of (array); - - free (data); - TYPE_REFLECTION_DATA (current_class) = NULL; - } - else - reflection_data = null_pointer_node; - - PUSH_FIELD_VALUE (v2, "reflection_data", reflection_data); - FINISH_RECORD_CONSTRUCTOR (cons, v2, class_type_node); - - DECL_INITIAL (decl) = cons; - - /* Hash synchronization requires at least 64-bit alignment. */ - if (flag_hash_synchronization && POINTER_SIZE < 64) - SET_DECL_ALIGN (decl, 64); - - if (flag_indirect_classes) - { - TREE_READONLY (decl) = 1; - TREE_CONSTANT (DECL_INITIAL (decl)) = 1; - } - - rest_of_decl_compilation (decl, 1, 0); - - { - tree classdollar_field = build_classdollar_field (type); - if (!flag_indirect_classes) - DECL_INITIAL (classdollar_field) = build_static_class_ref (type); - rest_of_decl_compilation (classdollar_field, 1, 0); - } - - TYPE_OTABLE_DECL (type) = NULL_TREE; - TYPE_ATABLE_DECL (type) = NULL_TREE; - TYPE_CTABLE_DECL (type) = NULL_TREE; -} - -void -finish_class (void) -{ - java_expand_catch_classes (current_class); - - current_function_decl = NULL_TREE; - TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (current_class)) = 0; - make_class_data (current_class); - register_class (); - rest_of_decl_compilation (TYPE_NAME (current_class), 1, 0); -} - -/* Return 2 if KLASS is compiled by this compilation job; - return 1 if KLASS can otherwise be assumed to be compiled; - return 0 if we cannot assume that KLASS is compiled. - Returns 1 for primitive and 0 for array types. */ -int -is_compiled_class (tree klass) -{ - int seen_in_zip; - if (TREE_CODE (klass) == POINTER_TYPE) - klass = TREE_TYPE (klass); - if (TREE_CODE (klass) != RECORD_TYPE) /* Primitive types are static. */ - return 1; - if (TYPE_ARRAY_P (klass)) - return 0; - - seen_in_zip = (TYPE_JCF (klass) && JCF_SEEN_IN_ZIP (TYPE_JCF (klass))); - if (CLASS_FROM_CURRENTLY_COMPILED_P (klass)) - { - /* The class was seen in the current ZIP file and will be - available as a compiled class in the future but may not have - been loaded already. Load it if necessary. This prevent - build_class_ref () from crashing. */ - - if (seen_in_zip && !CLASS_LOADED_P (klass) && (klass != current_class)) - load_class (klass, 1); - - /* We return 2 for class seen in ZIP and class from files - belonging to the same compilation unit */ - return 2; - } - - if (assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (klass))))) - { - if (!CLASS_LOADED_P (klass)) - { - if (klass != current_class) - load_class (klass, 1); - } - return 1; - } - - return 0; -} - -/* Build a VAR_DECL for the dispatch table (vtable) for class TYPE. */ - -tree -build_dtable_decl (tree type) -{ - tree dtype, decl; - - /* We need to build a new dtable type so that its size is uniquely - computed when we're dealing with the class for real and not just - faking it (like java.lang.Class during the initialization of the - compiler.) We know we're not faking a class when CURRENT_CLASS is - TYPE. */ - if (current_class == type) - { - tree dummy = NULL_TREE; - int n; - - dtype = make_node (RECORD_TYPE); - - PUSH_FIELD (input_location, dtype, dummy, "top_offset", ptr_type_node); - PUSH_FIELD (input_location, dtype, dummy, "type_info", ptr_type_node); - - PUSH_FIELD (input_location, dtype, dummy, "class", class_ptr_type); - for (n = 1; n < TARGET_VTABLE_USES_DESCRIPTORS; ++n) - { - tree tmp_field = build_decl (input_location, - FIELD_DECL, NULL_TREE, ptr_type_node); - TREE_CHAIN (dummy) = tmp_field; - DECL_CONTEXT (tmp_field) = dtype; - DECL_ARTIFICIAL (tmp_field) = 1; - dummy = tmp_field; - } - - PUSH_FIELD (input_location, dtype, dummy, "gc_descr", ptr_type_node); - for (n = 1; n < TARGET_VTABLE_USES_DESCRIPTORS; ++n) - { - tree tmp_field = build_decl (input_location, - FIELD_DECL, NULL_TREE, ptr_type_node); - TREE_CHAIN (dummy) = tmp_field; - DECL_CONTEXT (tmp_field) = dtype; - DECL_ARTIFICIAL (tmp_field) = 1; - dummy = tmp_field; - } - - n = TREE_VEC_LENGTH (get_dispatch_vector (type)); - if (TARGET_VTABLE_USES_DESCRIPTORS) - n *= TARGET_VTABLE_USES_DESCRIPTORS; - - PUSH_FIELD (input_location, dtype, dummy, "methods", - build_prim_array_type (nativecode_ptr_type_node, n)); - layout_type (dtype); - } - else - dtype = dtable_type; - - decl = build_decl (input_location, - VAR_DECL, get_identifier ("vt$"), dtype); - DECL_CONTEXT (decl) = type; - MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); - DECL_VTABLE_P (decl) = 1; - - return decl; -} - -/* Pre-pend the TYPE_FIELDS of THIS_CLASS with a dummy FIELD_DECL for the - fields inherited from SUPER_CLASS. */ - -void -push_super_field (tree this_class, tree super_class) -{ - tree base_decl; - /* Don't insert the field if we're just re-laying the class out. */ - if (TYPE_FIELDS (this_class) && !DECL_NAME (TYPE_FIELDS (this_class))) - return; - base_decl = build_decl (input_location, - FIELD_DECL, NULL_TREE, super_class); - DECL_IGNORED_P (base_decl) = 1; - DECL_CONTEXT (base_decl) = this_class; - DECL_CHAIN (base_decl) = TYPE_FIELDS (this_class); - TYPE_FIELDS (this_class) = base_decl; - DECL_SIZE (base_decl) = TYPE_SIZE (super_class); - DECL_SIZE_UNIT (base_decl) = TYPE_SIZE_UNIT (super_class); -} - -/* Handle the different manners we may have to lay out a super class. */ - -static tree -maybe_layout_super_class (tree super_class, tree this_class ATTRIBUTE_UNUSED) -{ - if (!super_class) - return NULL_TREE; - else if (TREE_CODE (super_class) == RECORD_TYPE) - { - 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) == POINTER_TYPE) - { - if (TREE_TYPE (super_class) != NULL_TREE) - super_class = TREE_TYPE (super_class); - else - gcc_unreachable (); - } - if (!TYPE_SIZE (super_class)) - safe_layout_class (super_class); - - return super_class; -} - -/* safe_layout_class just makes sure that we can load a class without - disrupting the current_class, input_location, etc, information - about the class processed currently. */ - -void -safe_layout_class (tree klass) -{ - tree save_current_class = current_class; - location_t save_location = input_location; - - layout_class (klass); - - current_class = save_current_class; - input_location = save_location; -} - -void -layout_class (tree this_class) -{ - int i; - tree super_class = CLASSTYPE_SUPER (this_class); - - class_list = tree_cons (this_class, NULL_TREE, class_list); - if (CLASS_BEING_LAIDOUT (this_class)) - { - char buffer [1024]; - char *report; - tree current; - - sprintf (buffer, " with '%s'", - IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)))); - obstack_grow (&temporary_obstack, buffer, strlen (buffer)); - - for (current = TREE_CHAIN (class_list); current; - current = TREE_CHAIN (current)) - { - tree decl = TYPE_NAME (TREE_PURPOSE (current)); - sprintf (buffer, "\n which inherits from '%s' (%s:%d)", - IDENTIFIER_POINTER (DECL_NAME (decl)), - DECL_SOURCE_FILE (decl), - DECL_SOURCE_LINE (decl)); - obstack_grow (&temporary_obstack, buffer, strlen (buffer)); - } - obstack_1grow (&temporary_obstack, '\0'); - report = XOBFINISH (&temporary_obstack, char *); - cyclic_inheritance_report = ggc_strdup (report); - obstack_free (&temporary_obstack, report); - TYPE_SIZE (this_class) = error_mark_node; - return; - } - CLASS_BEING_LAIDOUT (this_class) = 1; - - if (super_class && !CLASS_BEING_LAIDOUT (super_class)) - { - tree maybe_super_class - = maybe_layout_super_class (super_class, this_class); - if (maybe_super_class == NULL - || TREE_CODE (TYPE_SIZE (maybe_super_class)) == ERROR_MARK) - { - TYPE_SIZE (this_class) = error_mark_node; - CLASS_BEING_LAIDOUT (this_class) = 0; - class_list = TREE_CHAIN (class_list); - return; - } - if (TYPE_SIZE (this_class) == NULL_TREE) - push_super_field (this_class, maybe_super_class); - } - - layout_type (this_class); - - /* Also recursively load/layout any superinterfaces. */ - if (TYPE_BINFO (this_class)) - { - for (i = BINFO_N_BASE_BINFOS (TYPE_BINFO (this_class)) - 1; i > 0; i--) - { - 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; - } - } - } - - /* Convert the size back to an SI integer value. */ - TYPE_SIZE_UNIT (this_class) = - fold (convert (int_type_node, TYPE_SIZE_UNIT (this_class))); - - CLASS_BEING_LAIDOUT (this_class) = 0; - class_list = TREE_CHAIN (class_list); -} - -static void -add_miranda_methods (tree base_class, tree search_class) -{ - 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 = 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 - will be correct. This code must match similar layout code in the - runtime. */ - for (method_decl = TYPE_METHODS (elt); - method_decl; method_decl = DECL_CHAIN (method_decl)) - { - tree sig, override; - - /* An interface can have <clinit>. */ - if (ID_CLINIT_P (DECL_NAME (method_decl))) - continue; - - sig = build_java_argument_signature (TREE_TYPE (method_decl)); - override = lookup_argument_method (base_class, - DECL_NAME (method_decl), sig); - if (override == NULL_TREE) - { - /* Found a Miranda method. Add it. */ - tree new_method; - sig = build_java_signature (TREE_TYPE (method_decl)); - new_method - = add_method (base_class, - get_access_flags_from_decl (method_decl), - DECL_NAME (method_decl), sig); - METHOD_INVISIBLE (new_method) = 1; - } - } - - /* Try superinterfaces. */ - add_miranda_methods (base_class, elt); - } -} - -void -layout_class_methods (tree this_class) -{ - tree method_decl, dtable_count; - tree super_class, type_name; - - if (TYPE_NVIRTUALS (this_class)) - return; - - super_class = CLASSTYPE_SUPER (this_class); - - if (super_class) - { - super_class = maybe_layout_super_class (super_class, this_class); - if (!TYPE_NVIRTUALS (super_class)) - layout_class_methods (super_class); - dtable_count = TYPE_NVIRTUALS (super_class); - } - else - dtable_count = integer_zero_node; - - type_name = TYPE_NAME (this_class); - 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 - methods". We make a dummy method entry for such methods - here. */ - add_miranda_methods (this_class, this_class); - } - - TYPE_METHODS (this_class) = nreverse (TYPE_METHODS (this_class)); - - for (method_decl = TYPE_METHODS (this_class); - method_decl; method_decl = DECL_CHAIN (method_decl)) - dtable_count = layout_class_method (this_class, super_class, - method_decl, dtable_count); - - TYPE_NVIRTUALS (this_class) = dtable_count; -} - -/* Return the index of METHOD in INTERFACE. This index begins at 1 - and is used as an argument for _Jv_LookupInterfaceMethodIdx(). */ -int -get_interface_method_index (tree method, tree interface) -{ - tree meth; - int i = 1; - - for (meth = TYPE_METHODS (interface); ; meth = DECL_CHAIN (meth)) - { - if (meth == method) - return i; - /* We don't want to put <clinit> into the interface table. */ - if (! ID_CLINIT_P (DECL_NAME (meth))) - ++i; - gcc_assert (meth != NULL_TREE); - } -} - -/* Lay METHOD_DECL out, returning a possibly new value of - DTABLE_COUNT. Also mangle the method's name. */ - -tree -layout_class_method (tree this_class, tree super_class, - tree method_decl, tree dtable_count) -{ - tree method_name = DECL_NAME (method_decl); - - TREE_PUBLIC (method_decl) = 1; - - if (flag_indirect_classes - || (METHOD_PRIVATE (method_decl) && METHOD_STATIC (method_decl) - && ! METHOD_NATIVE (method_decl) - && ! special_method_p (method_decl))) - java_hide_decl (method_decl); - - /* Considered external unless it is being compiled into this object - file, or it was already flagged as external. */ - if (!DECL_EXTERNAL (method_decl)) - DECL_EXTERNAL (method_decl) = ((is_compiled_class (this_class) != 2) - || METHOD_NATIVE (method_decl)); - - if (ID_INIT_P (method_name)) - { - const char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class))); - const char *ptr; - for (ptr = p; *ptr; ) - { - if (*ptr++ == '.') - p = ptr; - } - DECL_CONSTRUCTOR_P (method_decl) = 1; - build_java_signature (TREE_TYPE (method_decl)); - } - else if (! METHOD_STATIC (method_decl)) - { - tree method_sig = - build_java_signature (TREE_TYPE (method_decl)); - bool method_override = false; - tree super_method = lookup_java_method (super_class, method_name, - method_sig); - if (super_method != NULL_TREE - && ! METHOD_DUMMY (super_method)) - { - method_override = true; - if (! METHOD_PUBLIC (super_method) && - ! METHOD_PROTECTED (super_method)) - { - /* Don't override private method, or default-access method in - another package. */ - if (METHOD_PRIVATE (super_method) || - ! in_same_package (TYPE_NAME (this_class), - TYPE_NAME (super_class))) - method_override = false; - } - } - if (method_override) - { - tree method_index = get_method_index (super_method); - set_method_index (method_decl, method_index); - if (method_index == NULL_TREE - && ! flag_indirect_dispatch - && ! DECL_ARTIFICIAL (super_method)) - error ("non-static method %q+D overrides static method", - method_decl); - } - 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); - } - } - - return dtable_count; -} - -static void -register_class (void) -{ - tree node; - - if (!registered_class) - vec_alloc (registered_class, 8); - - if (flag_indirect_classes) - node = current_class; - else - node = TREE_OPERAND (build_class_ref (current_class), 0); - vec_safe_push (registered_class, node); -} - -/* Emit a function that calls _Jv_RegisterNewClasses with a list of - all the classes we have emitted. */ - -static void -emit_indirect_register_classes (tree *list_p) -{ - tree klass, t, register_class_fn; - int i; - - int size = vec_safe_length (registered_class) * 2 + 1; - vec<constructor_elt, va_gc> *init; - vec_alloc (init, size); - tree class_array_type - = build_prim_array_type (ptr_type_node, size); - tree cdecl = build_decl (input_location, - VAR_DECL, get_identifier ("_Jv_CLS"), - class_array_type); - tree reg_class_list; - FOR_EACH_VEC_SAFE_ELT (registered_class, i, klass) - { - t = fold_convert (ptr_type_node, build_static_class_ref (klass)); - CONSTRUCTOR_APPEND_ELT (init, NULL_TREE, t); - t = fold_convert (ptr_type_node, - build_address_of (build_classdollar_field (klass))); - CONSTRUCTOR_APPEND_ELT (init, NULL_TREE, t); - } - CONSTRUCTOR_APPEND_ELT (init, NULL_TREE, integer_zero_node); - DECL_INITIAL (cdecl) = build_constructor (class_array_type, init); - TREE_CONSTANT (DECL_INITIAL (cdecl)) = 1; - TREE_STATIC (cdecl) = 1; - DECL_ARTIFICIAL (cdecl) = 1; - DECL_IGNORED_P (cdecl) = 1; - TREE_READONLY (cdecl) = 1; - TREE_CONSTANT (cdecl) = 1; - rest_of_decl_compilation (cdecl, 1, 0); - reg_class_list = fold_convert (ptr_type_node, build_address_of (cdecl)); - - t = build_function_type_list (void_type_node, - build_pointer_type (ptr_type_node), NULL); - t = build_decl (input_location, - FUNCTION_DECL, - get_identifier ("_Jv_RegisterNewClasses"), t); - TREE_PUBLIC (t) = 1; - DECL_EXTERNAL (t) = 1; - register_class_fn = t; - t = build_call_expr (register_class_fn, 1, reg_class_list); - append_to_statement_list (t, list_p); -} - -/* Emit a list of pointers to all classes we have emitted to JCR_SECTION. */ - -static void -emit_register_classes_in_jcr_section (void) -{ -#ifdef JCR_SECTION_NAME - tree klass, cdecl, class_array_type; - int i; - int size = vec_safe_length (registered_class); - vec<constructor_elt, va_gc> *init; - vec_alloc (init, size); - - FOR_EACH_VEC_SAFE_ELT (registered_class, i, klass) - CONSTRUCTOR_APPEND_ELT (init, NULL_TREE, build_fold_addr_expr (klass)); - - /* ??? I would like to use tree_output_constant_def() but there is no way - to put the data in a named section name, or to set the alignment, - via that function. So do everything manually here. */ - class_array_type = build_prim_array_type (ptr_type_node, size); - cdecl = build_decl (UNKNOWN_LOCATION, - VAR_DECL, get_identifier ("_Jv_JCR_SECTION_data"), - class_array_type); - SET_DECL_ALIGN (cdecl, POINTER_SIZE); - DECL_USER_ALIGN (cdecl) = 1; - DECL_INITIAL (cdecl) = build_constructor (class_array_type, init); - TREE_CONSTANT (DECL_INITIAL (cdecl)) = 1; - TREE_STATIC (cdecl) = 1; - TREE_READONLY (cdecl) = 0; - TREE_CONSTANT (cdecl) = 1; - DECL_ARTIFICIAL (cdecl) = 1; - DECL_IGNORED_P (cdecl) = 1; - DECL_PRESERVE_P (cdecl) = 1; - set_decl_section_name (cdecl, JCR_SECTION_NAME); - pushdecl_top_level (cdecl); - relayout_decl (cdecl); - rest_of_decl_compilation (cdecl, 1, 0); -#else - /* A target has defined TARGET_USE_JCR_SECTION, - but doesn't have a JCR_SECTION_NAME. */ - gcc_unreachable (); -#endif -} - - -/* Emit a series of calls to _Jv_RegisterClass for every class we emitted. - A series of calls is added to LIST_P. */ - -static void -emit_Jv_RegisterClass_calls (tree *list_p) -{ - tree klass, t, register_class_fn; - int i; - - t = build_function_type_list (void_type_node, class_ptr_type, NULL); - t = build_decl (input_location, - FUNCTION_DECL, get_identifier ("_Jv_RegisterClass"), t); - TREE_PUBLIC (t) = 1; - DECL_EXTERNAL (t) = 1; - register_class_fn = t; - - FOR_EACH_VEC_SAFE_ELT (registered_class, i, klass) - { - t = build_fold_addr_expr (klass); - t = build_call_expr (register_class_fn, 1, t); - append_to_statement_list (t, list_p); - } -} - -/* Emit something to register classes at start-up time. - - The default mechanism is to generate instances at run-time. - - An alternative 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 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 (tree *list_p) -{ - if (registered_class == NULL) - return; - - /* By default, generate instances of Class at runtime. */ - if (flag_indirect_classes) - emit_indirect_register_classes (list_p); - /* TARGET_USE_JCR_SECTION defaults to 1 if SUPPORTS_WEAK and - TARGET_ASM_NAMED_SECTION, else 0. Some targets meet those conditions - but lack suitable crtbegin/end objects or linker support. These - targets can override the default in tm.h to use the fallback mechanism. */ - else if (TARGET_USE_JCR_SECTION) - emit_register_classes_in_jcr_section (); - /* Use the fallback mechanism. */ - else - emit_Jv_RegisterClass_calls (list_p); -} - -/* Build a constructor for an entry in the symbol table. */ - -static tree -build_symbol_table_entry (tree clname, tree name, tree signature) -{ - tree symbol; - vec<constructor_elt, va_gc> *v = NULL; - - START_RECORD_CONSTRUCTOR (v, symbol_type); - PUSH_FIELD_VALUE (v, "clname", clname); - PUSH_FIELD_VALUE (v, "name", name); - PUSH_FIELD_VALUE (v, "signature", signature); - FINISH_RECORD_CONSTRUCTOR (symbol, v, symbol_type); - TREE_CONSTANT (symbol) = 1; - - return symbol; -} - -/* Make a symbol_type (_Jv_MethodSymbol) node for DECL. */ - -static tree -build_symbol_entry (tree decl, tree special) -{ - tree clname, name, signature; - clname = build_utf8_ref (DECL_NAME (TYPE_NAME (DECL_CONTEXT (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))); - /* SPECIAL is either NULL_TREE or integer_one_node. We emit - signature addr+1 if SPECIAL, and this indicates to the runtime - system that this is a "special" symbol, i.e. one that should - bypass access controls. */ - if (special != NULL_TREE) - signature = fold_build_pointer_plus (signature, special); - - return build_symbol_table_entry (clname, name, signature); -} - -/* Emit a symbol table: used by -findirect-dispatch. */ - -tree -emit_symbol_table (tree name, tree the_table, - vec<method_entry, va_gc> *decl_table, - tree the_syms_decl, tree the_array_element_type, - int element_size) -{ - tree table, null_symbol, table_size, the_array_type; - unsigned index; - method_entry *e; - vec<constructor_elt, va_gc> *v = NULL; - - /* Only emit a table if this translation unit actually made any - references via it. */ - if (!decl_table) - return the_table; - - /* Build a list of _Jv_MethodSymbols for each entry in otable_methods. */ - FOR_EACH_VEC_ELT (*decl_table, index, e) - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, - build_symbol_entry (e->method, e->special)); - - /* Terminate the list with a "null" entry. */ - null_symbol = build_symbol_table_entry (null_pointer_node, - null_pointer_node, - null_pointer_node); - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, null_symbol); - - tree symbols_arr_type - = build_prim_array_type (symbol_type, vec_safe_length (v)); - - table = build_constructor (symbols_arr_type, v); - - /* Make it the initial value for otable_syms and emit the decl. */ - TREE_TYPE (the_syms_decl) = symbols_arr_type; - relayout_decl (the_syms_decl); - 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, 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_cst (NULL_TREE, index * element_size + 1)); - the_array_type = build_array_type (the_array_element_type, table_size); - the_table = build_decl (input_location, - VAR_DECL, name, the_array_type); - TREE_STATIC (the_table) = 1; - TREE_READONLY (the_table) = 1; - rest_of_decl_compilation (the_table, 1, 0); - - return the_table; -} - -/* Make an entry for the catch_classes list. */ -tree -make_catch_class_record (tree catch_class, tree classname) -{ - tree entry; - tree type = TREE_TYPE (TREE_TYPE (TYPE_CTABLE_DECL (output_class))); - vec<constructor_elt, va_gc> *v = NULL; - START_RECORD_CONSTRUCTOR (v, type); - PUSH_FIELD_VALUE (v, "address", catch_class); - PUSH_FIELD_VALUE (v, "classname", classname); - FINISH_RECORD_CONSTRUCTOR (entry, v, type); - return entry; -} - - -/* Generate the list of Throwable classes that are caught by exception - handlers in this class. */ -tree -emit_catch_table (tree this_class) -{ - tree table, table_size, array_type; - int n_catch_classes; - constructor_elt *e; - /* Fill in the dummy entry that make_class created. */ - e = &(*TYPE_CATCH_CLASSES (this_class))[0]; - e->value = make_catch_class_record (null_pointer_node, null_pointer_node); - CONSTRUCTOR_APPEND_ELT (TYPE_CATCH_CLASSES (this_class), NULL_TREE, - make_catch_class_record (null_pointer_node, - null_pointer_node)); - n_catch_classes = TYPE_CATCH_CLASSES (this_class)->length (); - table_size = build_index_type (build_int_cst (NULL_TREE, n_catch_classes)); - array_type - = build_array_type (TREE_TYPE (TREE_TYPE (TYPE_CTABLE_DECL (this_class))), - table_size); - table = - build_decl (input_location, - VAR_DECL, DECL_NAME (TYPE_CTABLE_DECL (this_class)), array_type); - DECL_INITIAL (table) = - build_constructor (array_type, TYPE_CATCH_CLASSES (this_class)); - TREE_STATIC (table) = 1; - TREE_READONLY (table) = 1; - DECL_IGNORED_P (table) = 1; - 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; -} - -/* Build an entry in the type assertion table. */ - -static tree -build_assertion_table_entry (tree code, tree op1, tree op2) -{ - vec<constructor_elt, va_gc> *v = NULL; - tree entry; - - START_RECORD_CONSTRUCTOR (v, assertion_entry_type); - PUSH_FIELD_VALUE (v, "assertion_code", code); - PUSH_FIELD_VALUE (v, "op1", op1); - PUSH_FIELD_VALUE (v, "op2", op2); - FINISH_RECORD_CONSTRUCTOR (entry, v, assertion_entry_type); - - return entry; -} - -/* Add an entry to the type assertion table. Callback used during hashtable - traversal. */ - -int -add_assertion_table_entry (type_assertion **slot, vec<constructor_elt, va_gc> **v) -{ - tree entry; - tree code_val, op1_utf8, op2_utf8; - type_assertion *as = *slot; - - 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); - - entry = build_assertion_table_entry (code_val, op1_utf8, op2_utf8); - - CONSTRUCTOR_APPEND_ELT (*v, NULL_TREE, entry); - return true; -} - -/* Generate the type assertion table for KLASS, and return its DECL. */ - -static tree -emit_assertion_table (tree klass) -{ - tree null_entry, ctor, table_decl; - hash_table<type_assertion_hasher> *assertions_htab = TYPE_ASSERTIONS (klass); - vec<constructor_elt, va_gc> *v = NULL; - - /* Iterate through the hash table. */ - assertions_htab - ->traverse<vec<constructor_elt, va_gc> **, add_assertion_table_entry> (&v); - - /* Finish with a null entry. */ - null_entry = build_assertion_table_entry (integer_zero_node, - null_pointer_node, - null_pointer_node); - - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, null_entry); - - tree type - = build_prim_array_type (assertion_entry_type, vec_safe_length (v)); - - ctor = build_constructor (type, v); - - table_decl = build_decl (input_location, - VAR_DECL, mangled_classname ("_type_assert_", klass), - 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) -{ - fields_ident = get_identifier ("fields"); - info_ident = get_identifier ("info"); - - gcc_obstack_init (&temporary_obstack); -} - -/* A hash table mapping trees to trees. Used generally. */ - -#define JAVA_TREEHASHHASH_H(t) ((hashval_t)TYPE_UID (t)) - -hashval_t -treetreehasher::hash (treetreehash_entry *k) -{ - return JAVA_TREEHASHHASH_H (k->key); -} - -bool -treetreehasher::equal (treetreehash_entry *k1, tree k2) -{ - return (k1->key == k2); -} - -tree -java_treetreehash_find (hash_table<treetreehasher> *ht, tree t) -{ - struct treetreehash_entry *e; - hashval_t hv = JAVA_TREEHASHHASH_H (t); - e = ht->find_with_hash (t, hv); - if (e == NULL) - return NULL; - else - return e->value; -} - -tree * -java_treetreehash_new (hash_table<treetreehasher> *ht, tree t) -{ - struct treetreehash_entry *tthe; - hashval_t hv = JAVA_TREEHASHHASH_H (t); - - treetreehash_entry **e = ht->find_slot_with_hash (t, hv, INSERT); - if (*e == NULL) - { - tthe = ggc_cleared_alloc<treetreehash_entry> (); - tthe->key = t; - *e = tthe; - } - else - tthe = *e; - return &tthe->value; -} - -hash_table<treetreehasher> * -java_treetreehash_create (size_t size) -{ - return hash_table<treetreehasher>::create_ggc (size); -} - -/* Break down qualified IDENTIFIER into package and class-name components. - For example, given SOURCE "pkg.foo.Bar", LEFT will be set to - "pkg.foo", and RIGHT to "Bar". */ - -int -split_qualified_name (tree *left, tree *right, tree source) -{ - char *p, *base; - int l = IDENTIFIER_LENGTH (source); - - base = (char *) alloca (l + 1); - memcpy (base, IDENTIFIER_POINTER (source), l + 1); - - /* Breakdown NAME into REMAINDER . IDENTIFIER. */ - p = base + l - 1; - while (*p != '.' && p != base) - p--; - - /* We didn't find a '.'. Return an error. */ - if (p == base) - return 1; - - *p = '\0'; - if (right) - *right = get_identifier (p+1); - *left = get_identifier (base); - - return 0; -} - -/* Given two classes (TYPE_DECL) or class names (IDENTIFIER), return TRUE - if the classes are from the same package. */ - -int -in_same_package (tree name1, tree name2) -{ - tree tmp; - tree pkg1; - tree pkg2; - - if (TREE_CODE (name1) == TYPE_DECL) - name1 = DECL_NAME (name1); - if (TREE_CODE (name2) == TYPE_DECL) - name2 = DECL_NAME (name2); - - if (QUALIFIED_P (name1) != QUALIFIED_P (name2)) - /* One in empty package. */ - return 0; - - if (QUALIFIED_P (name1) == 0 && QUALIFIED_P (name2) == 0) - /* Both in empty package. */ - return 1; - - split_qualified_name (&pkg1, &tmp, name1); - split_qualified_name (&pkg2, &tmp, name2); - - return (pkg1 == pkg2); -} - -#include "gt-java-class.h" |