/* Process declarations and variables for the GNU compiler for the
Java(TM) language.
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
- Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007,
+ 2005, 2006, 2007 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 2, or (at your option)
+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,
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 COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
+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.
#include "cgraph.h"
#include "tree-inline.h"
#include "target.h"
+#include "version.h"
+#include "tree-iterator.h"
+#include "langhooks.h"
#if defined (DEBUG_JAVA_BINDING_LEVELS)
extern void indent (void);
static tree push_promoted_type (const char *, tree);
static struct binding_level *make_binding_level (void);
static tree create_primitive_vtable (const char *);
-static tree check_local_named_variable (tree, tree, int, int *);
static tree check_local_unnamed_variable (tree, tree, tree);
+static void parse_version (void);
+
+
+/* The following ABI flags are used in the high-order bits of the version
+ ID field. The version ID number itself should never be larger than
+ 0xfffff, so it should be safe to use top 12 bits for these flags. */
+
+#define FLAG_BINARYCOMPAT_ABI (1<<31) /* Class is built with the BC-ABI. */
+
+#define FLAG_BOOTSTRAP_LOADER (1<<30) /* Used when defining a class that
+ should be loaded by the bootstrap
+ loader. */
+
+/* If an ABI change is made within a GCC release series, rendering current
+ binaries incompatible with the old runtimes, this number must be set to
+ enforce the compatibility rules. */
+#define MINOR_BINARYCOMPAT_ABI_VERSION 1
+
+/* The runtime may recognize a variety of BC ABIs (objects generated by
+ different version of gcj), but will probably always require strict
+ matching for the ordinary (C++) ABI. */
+
+/* The version ID of the BC ABI that we generate. This must be kept in
+ sync with parse_version(), libgcj, and reality (if the BC format changes,
+ this must change). */
+#define GCJ_CURRENT_BC_ABI_VERSION \
+ (4 * 100000 + 0 * 1000 + MINOR_BINARYCOMPAT_ABI_VERSION)
+
+/* The ABI version number. */
+tree gcj_abi_version;
/* Name of the Cloneable class. */
tree java_lang_cloneable_identifier_node;
static GTY(()) tree decl_map;
+/* The base_decl_map is contains one variable of ptr_type: this is
+ used to contain every variable of reference type that is ever
+ stored in a local variable slot. */
+
+static GTY(()) tree base_decl_map;
+
+/* An index used to make temporary identifiers unique. */
+static int uniq;
+
/* A list of local variables VAR_DECLs for this method that we have seen
debug information, but we have not reached their starting (byte) PC yet. */
static GTY(()) tree pending_local_decls;
-/* Push a local variable or stack slot into the decl_map,
- and assign it an rtl. */
+/* The decl for "_Jv_ResolvePoolEntry". */
+tree soft_resolvepoolentry_node;
+
+/* The decl for the .constants field of an instance of Class. */
+tree constants_field_decl_node;
+
+/* The decl for the .data field of an instance of Class. */
+tree constants_data_field_decl_node;
#if defined(DEBUG_JAVA_BINDING_LEVELS)
int binding_depth = 0;
}
#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
-/* Copy the value in decl into every alias in the same local variable
- slot. */
-void
-update_aliases (tree decl, int index)
+/* True if decl is a named local variable, i.e. if it is an alias
+ that's used only for debugging purposes. */
+
+static bool
+debug_variable_p (tree decl)
{
- tree tmp = TREE_VEC_ELT (decl_map, index);
- tree type = TREE_TYPE (decl);
- while (tmp != NULL_TREE)
- {
- if (tmp != decl
- && ! LOCAL_VAR_OUT_OF_SCOPE_P (tmp)
- && TYPE_MODE (type) == TYPE_MODE (TREE_TYPE (tmp)))
- {
- tree src = build1 (NOP_EXPR, TREE_TYPE (tmp), decl);
- java_add_stmt
- (build (MODIFY_EXPR, TREE_TYPE (tmp), tmp, src));
- }
- tmp = DECL_LOCAL_SLOT_CHAIN (tmp);
- }
-}
+ if (TREE_CODE (decl) == PARM_DECL)
+ return false;
+
+ if (LOCAL_SLOT_P (decl))
+ return false;
+ return true;
+}
+
static tree
push_jvm_slot (int index, tree decl)
{
- tree type = TREE_TYPE (decl);
- tree tmp;
-
DECL_CONTEXT (decl) = current_function_decl;
layout_decl (decl, 0);
- /* Look for another variable of the same mode in this slot. */
- tmp = TREE_VEC_ELT (decl_map, index);
- while (tmp != NULL_TREE)
- {
- if (! LOCAL_VAR_OUT_OF_SCOPE_P (tmp)
- && TYPE_MODE (type) == TYPE_MODE (TREE_TYPE (tmp)))
- {
- /* At the point of its creation this decl inherits whatever
- is in the slot. */
- tree src = build1 (NOP_EXPR, TREE_TYPE (decl), tmp);
- java_add_stmt
- (build (MODIFY_EXPR, TREE_TYPE (decl), decl, src));
- break;
- }
- tmp = DECL_LOCAL_SLOT_CHAIN (tmp);
- }
-
/* Now link the decl into the decl_map. */
if (DECL_LANG_SPECIFIC (decl) == NULL)
{
DECL_LOCAL_SLOT_CHAIN (decl) = TREE_VEC_ELT (decl_map, index);
TREE_VEC_ELT (decl_map, index) = decl;
- if (TREE_CODE (decl) != PARM_DECL)
- pushdecl (decl);
return decl;
}
-/* Find out if 'decl' passed in fits the defined PC location better than
- 'best'. Return decl if it does, return best if it doesn't. If decl
- is returned, then updated is set to true. */
-
-static tree
-check_local_named_variable (tree best, tree decl, int pc, int *updated)
-{
- if (pc >= DECL_LOCAL_START_PC (decl)
- && pc < DECL_LOCAL_END_PC (decl))
- {
- if (best == NULL_TREE
- || (DECL_LOCAL_START_PC (decl) > DECL_LOCAL_START_PC (best)
- && DECL_LOCAL_END_PC (decl) < DECL_LOCAL_END_PC (best)))
- {
- *updated = 1;
- return decl;
- }
- }
-
- return best;
-}
-
/* Find the best declaration based upon type. If 'decl' fits 'type' better
than 'best', return 'decl'. Otherwise return 'best'. */
static tree
check_local_unnamed_variable (tree best, tree decl, tree type)
{
- if (TREE_TYPE (decl) == type
- || (TREE_CODE (TREE_TYPE (decl)) == TREE_CODE (type)
- && TYPE_PRECISION (TREE_TYPE (decl)) <= 32
- && TYPE_PRECISION (type) <= 32
- && TREE_CODE (type) != POINTER_TYPE)
- || (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
- && type == ptr_type_node))
- {
- if (best == NULL_TREE
- || (TREE_TYPE (decl) == type && TREE_TYPE (best) != type))
- return decl;
- }
+ tree decl_type = TREE_TYPE (decl);
+
+ gcc_assert (! LOCAL_VAR_OUT_OF_SCOPE_P (decl));
+
+ /* Use the same decl for all integer types <= 32 bits. This is
+ necessary because sometimes a value is stored as (for example)
+ boolean but loaded as int. */
+ if (decl_type == type
+ || (INTEGRAL_TYPE_P (decl_type)
+ && INTEGRAL_TYPE_P (type)
+ && TYPE_PRECISION (decl_type) <= 32
+ && TYPE_PRECISION (type) <= 32
+ && TYPE_PRECISION (decl_type) >= TYPE_PRECISION (type))
+ /* ptr_type_node is used for null pointers, which are
+ assignment compatible with everything. */
+ || (TREE_CODE (decl_type) == POINTER_TYPE
+ && type == ptr_type_node)
+ /* Whenever anyone wants to use a slot that is initially
+ occupied by a PARM_DECL of pointer type they must get that
+ decl, even if they asked for a pointer to a different type.
+ However, if someone wants a scalar variable in a slot that
+ initially held a pointer arg -- or vice versa -- we create a
+ new VAR_DECL.
+
+ ???: As long as verification is correct, this will be a
+ compatible type. But maybe we should create a dummy variable
+ and replace all references to it with the DECL and a
+ NOP_EXPR.
+ */
+ || (TREE_CODE (decl_type) == POINTER_TYPE
+ && TREE_CODE (decl) == PARM_DECL
+ && TREE_CODE (type) == POINTER_TYPE))
+ {
+ if (best == NULL_TREE
+ || (decl_type == type && TREE_TYPE (best) != type))
+ return decl;
+ }
- return best;
+ return best;
}
If there is no existing matching decl, allocate one. */
tree
-find_local_variable (int index, tree type, int pc)
+find_local_variable (int index, tree type, int pc ATTRIBUTE_UNUSED)
{
- tree decl = TREE_VEC_ELT (decl_map, index);
- tree best = NULL_TREE;
- int found_scoped_var = 0;
+ tree tmp = TREE_VEC_ELT (decl_map, index);
+ tree decl = NULL_TREE;
- /* Scan through every declaration that has been created in this slot. */
- while (decl != NULL_TREE)
+ /* Scan through every declaration that has been created in this
+ slot. We're only looking for variables that correspond to local
+ index declarations and PARM_DECLs, not named variables: such
+ local variables are used only for debugging information. */
+ while (tmp != NULL_TREE)
{
- bool has_name = false;
- tree name = DECL_NAME (decl);
- if (name && IDENTIFIER_POINTER (name))
- has_name = IDENTIFIER_POINTER (name)[0] != '#';
-
- /* Variables created in give_name_to_locals() have a name and have
- a specified scope, so we can handle them specifically. We want
- to use the specific decls created for those so they are assigned
- the right variables in the debugging information. */
- if (has_name)
- {
- /* This is a variable we have a name for, so it has a scope
- supplied in the class file. But it only matters when we
- actually have a PC to use. If pc<0, then we are asking
- for a stack slot and this decl won't be one of those. */
- if (pc >= 0)
- best = check_local_named_variable (best, decl, pc,
- &found_scoped_var);
- }
- /* We scan for type information unless we found a variable in the
- proper scope already. */
- else if (!found_scoped_var)
- {
- /* If we don't have scoping information for a variable, we use
- a different method to look it up. */
- best = check_local_unnamed_variable (best, decl, type);
- }
-
- decl = DECL_LOCAL_SLOT_CHAIN (decl);
+ if (! debug_variable_p (tmp))
+ decl = check_local_unnamed_variable (decl, tmp, type);
+ tmp = DECL_LOCAL_SLOT_CHAIN (tmp);
}
- if (best != NULL_TREE)
- return best;
+ /* gcj has a function called promote_type(), which is used by both
+ the bytecode compiler and the source compiler. Unfortunately,
+ the type systems for the Java VM and the Java language are not
+ the same: a boolean in the VM promotes to an int, not to a wide
+ boolean. If our caller wants something to hold a boolean, that
+ had better be an int, because that slot might be re-used
+ later in integer context. */
+ if (TREE_CODE (type) == BOOLEAN_TYPE)
+ type = integer_type_node;
/* If we don't find a match, create one with the type passed in.
- Ths name of the variable is #n#m, which n is the variable index
+ The name of the variable is #n#m, which n is the variable index
in the local variable area and m is a dummy identifier for
uniqueness -- multiple variables may share the same local
- variable index. */
- {
- char buf[64];
- tree name;
- static int uniq;
- sprintf (buf, "#%d#%d", index, uniq++);
- name = get_identifier (buf);
+ variable index. We don't call pushdecl() to push pointer types
+ into a binding expr because they'll all be replaced by a single
+ variable that is used for every reference in that local variable
+ slot. */
+ if (! decl)
+ {
+ char buf[64];
+ tree name;
+ sprintf (buf, "#slot#%d#%d", index, uniq++);
+ name = get_identifier (buf);
+ decl = build_decl (VAR_DECL, name, type);
+ DECL_IGNORED_P (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
+ decl = push_jvm_slot (index, decl);
+ LOCAL_SLOT_P (decl) = 1;
+
+ if (TREE_CODE (type) != POINTER_TYPE)
+ pushdecl_function_level (decl);
+ }
- return push_jvm_slot (index, build_decl (VAR_DECL, name, type));
- }
+ /* As well as creating a local variable that matches the type, we
+ also create a base variable (of ptr_type) that will hold all its
+ aliases. */
+ if (TREE_CODE (type) == POINTER_TYPE
+ && ! TREE_VEC_ELT (base_decl_map, index))
+ {
+ char buf[64];
+ tree name;
+ tree base_decl;
+ sprintf (buf, "#ref#%d#%d", index, uniq++);
+ name = get_identifier (buf);
+ base_decl
+ = TREE_VEC_ELT (base_decl_map, index)
+ = build_decl (VAR_DECL, name, ptr_type_node);
+ pushdecl_function_level (base_decl);
+ DECL_IGNORED_P (base_decl) = 1;
+ DECL_ARTIFICIAL (base_decl) = 1;
+ }
+
+ return decl;
+}
+
+/* Called during gimplification for every variable. If the variable
+ is a temporary of pointer type, replace it with a common variable
+ thath is used to hold all pointer types that are ever stored in
+ that slot. Set WANT_LVALUE if you want a variable that is to be
+ written to. */
+
+tree
+java_replace_reference (tree var_decl, bool want_lvalue)
+{
+ tree decl_type;
+
+ if (! base_decl_map)
+ return var_decl;
+
+ decl_type = TREE_TYPE (var_decl);
+
+ if (TREE_CODE (decl_type) == POINTER_TYPE)
+ {
+ if (DECL_LANG_SPECIFIC (var_decl)
+ && LOCAL_SLOT_P (var_decl))
+ {
+ int index = DECL_LOCAL_SLOT_NUMBER (var_decl);
+ tree base_decl = TREE_VEC_ELT (base_decl_map, index);
+
+ gcc_assert (base_decl);
+ if (! want_lvalue)
+ base_decl = build1 (NOP_EXPR, decl_type, base_decl);
+
+ return base_decl;
+ }
+ }
+
+ return var_decl;
}
that were entered and exited one level down. */
tree blocks;
- /* The BLOCK node for this level, if one has been preallocated.
- If 0, the BLOCK is allocated (if needed) when the level is popped. */
- tree this_block;
-
/* The binding level which this one is contained in (inherits from). */
struct binding_level *level_chain;
static GTY(()) struct binding_level *global_binding_level;
+/* The binding level that holds variables declared at the outermost
+ level within a function body. */
+
+static struct binding_level *function_binding_level;
+
/* A PC value bigger than any PC value we may ever may encounter. */
#define LARGEST_PC (( (unsigned int)1 << (HOST_BITS_PER_INT - 1)) - 1)
NULL_TREE, /* names */
NULL_TREE, /* shadowed */
NULL_TREE, /* blocks */
- NULL_TREE, /* this_lock */
NULL_BINDING_LEVEL, /* level_chain */
LARGEST_PC, /* end_pc */
0, /* start_pc */
0, /* binding_depth */
};
-#if 0
-/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
- that have names. Here so we can clear out their names' definitions
- at the end of the function. */
-
-static tree named_labels;
-
-/* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
-
-static tree shadowed_labels;
-#endif
-
tree java_global_trees[JTI_MAX];
/* Build (and pushdecl) a "promoted type" for all standard
TYPE_MAX_VALUE (type) = copy_node (in_max);
TREE_TYPE (TYPE_MAX_VALUE (type)) = type;
TYPE_PRECISION (type) = TYPE_PRECISION (int_type_node);
+ TYPE_STRING_FLAG (type) = TYPE_STRING_FLAG (actual_type);
layout_type (type);
pushdecl (build_decl (TYPE_DECL, get_identifier (name), type));
return type;
}
-/* Return a definition for a builtin function named NAME and whose data type
- is TYPE. TYPE should be a function type with argument types.
- FUNCTION_CODE tells later passes how to compile calls to this function.
- See tree.h for its possible values.
-
- If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
- the name to be called if we can't opencode the function. If
- ATTRS is nonzero, use that for the function's attribute list. */
-
-tree
-builtin_function (const char *name,
- tree type,
- int function_code,
- enum built_in_class class,
- const char *library_name,
- tree attrs ATTRIBUTE_UNUSED)
-{
- tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
- DECL_EXTERNAL (decl) = 1;
- TREE_PUBLIC (decl) = 1;
- if (library_name)
- SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
- make_decl_rtl (decl, NULL);
- pushdecl (decl);
- DECL_BUILT_IN_CLASS (decl) = class;
- DECL_FUNCTION_CODE (decl) = function_code;
- return decl;
-}
-
/* Return tree that represents a vtable for a primitive array. */
static tree
create_primitive_vtable (const char *name)
return t;
}
+/* Parse the version string and compute the ABI version number. */
+static void
+parse_version (void)
+{
+ const char *p = version_string;
+ unsigned int major = 0, minor = 0;
+ unsigned int abi_version;
+
+ /* Skip leading junk. */
+ while (*p && !ISDIGIT (*p))
+ ++p;
+ gcc_assert (*p);
+
+ /* Extract major version. */
+ while (ISDIGIT (*p))
+ {
+ major = major * 10 + *p - '0';
+ ++p;
+ }
+
+ gcc_assert (*p == '.' && ISDIGIT (p[1]));
+ ++p;
+
+ /* Extract minor version. */
+ while (ISDIGIT (*p))
+ {
+ minor = minor * 10 + *p - '0';
+ ++p;
+ }
+
+ if (flag_indirect_dispatch)
+ {
+ abi_version = GCJ_CURRENT_BC_ABI_VERSION;
+ abi_version |= FLAG_BINARYCOMPAT_ABI;
+ }
+ else /* C++ ABI */
+ {
+ /* Implicit in this computation is the idea that we won't break the
+ old-style binary ABI in a sub-minor release (e.g., from 4.0.0 to
+ 4.0.1). */
+ abi_version = 100000 * major + 1000 * minor;
+ }
+ if (flag_bootstrap_classes)
+ abi_version |= FLAG_BOOTSTRAP_LOADER;
+
+ gcj_abi_version = build_int_cstu (ptr_type_node, abi_version);
+}
void
java_init_decl_processing (void)
tree t;
init_class_processing ();
- init_resource_processing ();
current_function_decl = NULL;
current_binding_level = NULL_BINDING_LEVEL;
TREE_TYPE (error_mark_node) = error_mark_node;
/* Create sizetype first - needed for other types. */
- initialize_sizetypes ();
+ initialize_sizetypes (false);
byte_type_node = make_signed_type (8);
pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"), byte_type_node));
/* Define these next since types below may used them. */
integer_type_node = java_type_for_size (INT_TYPE_SIZE, 0);
- integer_zero_node = build_int_2 (0, 0);
- integer_one_node = build_int_2 (1, 0);
- integer_two_node = build_int_2 (2, 0);
- integer_four_node = build_int_2 (4, 0);
- integer_minus_one_node = build_int_2 (-1, -1);
+ integer_zero_node = build_int_cst (NULL_TREE, 0);
+ integer_one_node = build_int_cst (NULL_TREE, 1);
+ integer_two_node = build_int_cst (NULL_TREE, 2);
+ integer_four_node = build_int_cst (NULL_TREE, 4);
+ integer_minus_one_node = build_int_cst (NULL_TREE, -1);
/* A few values used for range checking in the lexer. */
- decimal_int_max = build_int_2 (0x80000000, 0);
- TREE_TYPE (decimal_int_max) = unsigned_int_type_node;
+ decimal_int_max = build_int_cstu (unsigned_int_type_node, 0x80000000);
#if HOST_BITS_PER_WIDE_INT == 64
- decimal_long_max = build_int_2 (0x8000000000000000LL, 0);
-#else
-#if HOST_BITS_PER_WIDE_INT == 32
- decimal_long_max = build_int_2 (0, 0x80000000);
+ decimal_long_max = build_int_cstu (unsigned_long_type_node,
+ 0x8000000000000000LL);
+#elif HOST_BITS_PER_WIDE_INT == 32
+ decimal_long_max = build_int_cst_wide (unsigned_long_type_node,
+ 0, 0x80000000);
#else
#error "unsupported size"
#endif
-#endif
- TREE_TYPE (decimal_long_max) = unsigned_long_type_node;
size_zero_node = size_int (0);
size_one_node = size_int (1);
bitsize_one_node = bitsize_int (1);
bitsize_unit_node = bitsize_int (BITS_PER_UNIT);
- long_zero_node = build_int_2 (0, 0);
- TREE_TYPE (long_zero_node) = long_type_node;
+ long_zero_node = build_int_cst (long_type_node, 0);
void_type_node = make_node (VOID_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("void"), void_type_node));
layout_type (void_type_node); /* Uses size_zero_node */
+
ptr_type_node = build_pointer_type (void_type_node);
+ const_ptr_type_node
+ = build_pointer_type (build_type_variant (void_type_node, 1, 0));
+
t = make_node (VOID_TYPE);
layout_type (t); /* Uses size_zero_node */
return_address_type_node = build_pointer_type (t);
- null_pointer_node = build_int_2 (0, 0);
- TREE_TYPE (null_pointer_node) = ptr_type_node;
+ null_pointer_node = build_int_cst (ptr_type_node, 0);
-#if 0
- /* Make a type to be the domain of a few array types
- whose domains don't really matter.
- 200 is small enough that it always fits in size_t
- and large enough that it can hold most function names for the
- initializations of __FUNCTION__ and __PRETTY_FUNCTION__. */
- short_array_type_node = build_prim_array_type (short_type_node, 200);
-#endif
- char_type_node = make_node (CHAR_TYPE);
+ char_type_node = make_node (INTEGER_TYPE);
+ TYPE_STRING_FLAG (char_type_node) = 1;
TYPE_PRECISION (char_type_node) = 16;
fixup_unsigned_type (char_type_node);
pushdecl (build_decl (TYPE_DECL, get_identifier ("char"), char_type_node));
TYPE_NONALIASED_COMPONENT (atable_type) = 1;
atable_ptr_type = build_pointer_type (atable_type);
+ itable_type = build_array_type (ptr_type_node,
+ one_elt_array_domain_type);
+ TYPE_NONALIASED_COMPONENT (itable_type) = 1;
+ itable_ptr_type = build_pointer_type (itable_type);
+
symbol_type = make_node (RECORD_TYPE);
PUSH_FIELD (symbol_type, field, "clname", utf8const_ptr_type);
PUSH_FIELD (symbol_type, field, "name", utf8const_ptr_type);
one_elt_array_domain_type);
symbols_array_ptr_type = build_pointer_type (symbols_array_type);
+ assertion_entry_type = make_node (RECORD_TYPE);
+ PUSH_FIELD (assertion_entry_type, field, "assertion_code", integer_type_node);
+ PUSH_FIELD (assertion_entry_type, field, "op1", utf8const_ptr_type);
+ PUSH_FIELD (assertion_entry_type, field, "op2", utf8const_ptr_type);
+ FINISH_RECORD (assertion_entry_type);
+
+ assertion_table_type = build_array_type (assertion_entry_type,
+ one_elt_array_domain_type);
+
/* As you're adding items here, please update the code right after
this section, so that the filename containing the source code of
the pre-defined class gets registered correctly. */
TYPE_identifier_node = get_identifier ("TYPE");
init_identifier_node = get_identifier ("<init>");
clinit_identifier_node = get_identifier ("<clinit>");
- finit_identifier_node = get_identifier ("finit$");
- instinit_identifier_node = get_identifier ("instinit$");
void_signature_node = get_identifier ("()V");
- length_identifier_node = get_identifier ("length");
finalize_identifier_node = get_identifier ("finalize");
this_identifier_node = get_identifier ("this");
- super_identifier_node = get_identifier ("super");
- continue_identifier_node = get_identifier ("continue");
- access0_identifier_node = get_identifier ("access$0");
- classdollar_identifier_node = get_identifier ("class$");
java_lang_cloneable_identifier_node = get_identifier ("java.lang.Cloneable");
java_io_serializable_identifier_node =
PUSH_FIELD (constants_type_node, field, "size", unsigned_int_type_node);
PUSH_FIELD (constants_type_node, field, "tags", ptr_type_node);
PUSH_FIELD (constants_type_node, field, "data", ptr_type_node);
+ constants_data_field_decl_node = field;
FINISH_RECORD (constants_type_node);
build_decl (TYPE_DECL, get_identifier ("constants"), constants_type_node);
set_super_info (0, string_type_node, object_type_node, 0);
class_ptr_type = build_pointer_type (class_type_node);
- PUSH_FIELD (class_type_node, field, "next", class_ptr_type);
+ PUSH_FIELD (class_type_node, field, "next_or_version", class_ptr_type);
PUSH_FIELD (class_type_node, field, "name", utf8const_ptr_type);
PUSH_FIELD (class_type_node, field, "accflags", access_flags_type_node);
PUSH_FIELD (class_type_node, field, "superclass", class_ptr_type);
PUSH_FIELD (class_type_node, field, "constants", constants_type_node);
+ constants_field_decl_node = field;
PUSH_FIELD (class_type_node, field, "methods", method_ptr_type_node);
PUSH_FIELD (class_type_node, field, "method_count", short_type_node);
PUSH_FIELD (class_type_node, field, "vtable_method_count", short_type_node);
PUSH_FIELD (class_type_node, field, "atable", atable_ptr_type);
PUSH_FIELD (class_type_node, field, "atable_syms",
symbols_array_ptr_type);
+ PUSH_FIELD (class_type_node, field, "itable", itable_ptr_type);
+ PUSH_FIELD (class_type_node, field, "itable_syms",
+ symbols_array_ptr_type);
PUSH_FIELD (class_type_node, field, "catch_classes", ptr_type_node);
PUSH_FIELD (class_type_node, field, "interfaces",
build_pointer_type (class_ptr_type));
PUSH_FIELD (class_type_node, field, "idt", ptr_type_node);
PUSH_FIELD (class_type_node, field, "arrayclass", ptr_type_node);
PUSH_FIELD (class_type_node, field, "protectionDomain", ptr_type_node);
+ PUSH_FIELD (class_type_node, field, "assertion_table", ptr_type_node);
PUSH_FIELD (class_type_node, field, "hack_signers", ptr_type_node);
PUSH_FIELD (class_type_node, field, "chain", ptr_type_node);
PUSH_FIELD (class_type_node, field, "aux_info", ptr_type_node);
+ PUSH_FIELD (class_type_node, field, "engine", ptr_type_node);
+ PUSH_FIELD (class_type_node, field, "reflection_data", ptr_type_node);
for (t = TYPE_FIELDS (class_type_node); t != NULL_TREE; t = TREE_CHAIN (t))
FIELD_PRIVATE (t) = 1;
push_super_field (class_type_node, object_type_node);
field_info_union_node = make_node (UNION_TYPE);
PUSH_FIELD (field_info_union_node, field, "boffset", int_type_node);
PUSH_FIELD (field_info_union_node, field, "addr", ptr_type_node);
-#if 0
- PUSH_FIELD (field_info_union_node, field, "idx", unsigned_short_type_node);
-#endif
layout_type (field_info_union_node);
PUSH_FIELD (field_type_node, field, "name", utf8const_ptr_type);
FINISH_RECORD (dtable_type);
build_decl (TYPE_DECL, get_identifier ("dispatchTable"), dtable_type);
-#define jint_type int_type_node
-#define jint_ptr_type ptr_type_node
-
jexception_type = make_node (RECORD_TYPE);
PUSH_FIELD (jexception_type, field, "start_pc", ptr_type_node);
PUSH_FIELD (jexception_type, field, "end_pc", ptr_type_node);
PUSH_FIELD (lineNumbers_type, field, "length", unsigned_int_type_node);
FINISH_RECORD (lineNumbers_type);
-#define instn_ptr_type_node ptr_type_node /* XXX JH */
-
-#define lineNumbers_ptr_type_node build_pointer_type(lineNumbers_type)
-
PUSH_FIELD (method_type_node, field, "name", utf8const_ptr_type);
PUSH_FIELD (method_type_node, field, "signature", utf8const_ptr_type);
PUSH_FIELD (method_type_node, field, "accflags", access_flags_type_node);
endlink = end_params_node = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
- t = tree_cons (NULL_TREE, class_ptr_type,
- tree_cons (NULL_TREE, int_type_node, endlink));
- alloc_object_node = builtin_function ("_Jv_AllocObject",
- build_function_type (ptr_type_node, t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ t = tree_cons (NULL_TREE, class_ptr_type, endlink);
+ alloc_object_node = add_builtin_function ("_Jv_AllocObject",
+ build_function_type (ptr_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
DECL_IS_MALLOC (alloc_object_node) = 1;
- alloc_no_finalizer_node =
- builtin_function ("_Jv_AllocObjectNoFinalizer",
- build_function_type (ptr_type_node, t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ alloc_no_finalizer_node =
+ add_builtin_function ("_Jv_AllocObjectNoFinalizer",
+ build_function_type (ptr_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
DECL_IS_MALLOC (alloc_no_finalizer_node) = 1;
t = tree_cons (NULL_TREE, ptr_type_node, endlink);
- soft_initclass_node = builtin_function ("_Jv_InitClass",
- build_function_type (void_type_node,
- t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
-
- throw_node = builtin_function ("_Jv_Throw",
- build_function_type (ptr_type_node, t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ soft_initclass_node = add_builtin_function ("_Jv_InitClass",
+ build_function_type (void_type_node,
+ t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ t = tree_cons (NULL_TREE, class_ptr_type,
+ tree_cons (NULL_TREE, int_type_node, endlink));
+ soft_resolvepoolentry_node
+ = add_builtin_function ("_Jv_ResolvePoolEntry",
+ build_function_type (ptr_type_node, t),
+ 0,NOT_BUILT_IN, NULL, NULL_TREE);
+ DECL_IS_PURE (soft_resolvepoolentry_node) = 1;
+ throw_node = add_builtin_function ("_Jv_Throw",
+ build_function_type (void_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
/* Mark throw_nodes as `noreturn' functions with side effects. */
TREE_THIS_VOLATILE (throw_node) = 1;
TREE_SIDE_EFFECTS (throw_node) = 1;
- t = build_function_type (int_type_node, endlink);
- soft_monitorenter_node
- = builtin_function ("_Jv_MonitorEnter", t, 0, NOT_BUILT_IN,
- NULL, NULL_TREE);
- soft_monitorexit_node
- = builtin_function ("_Jv_MonitorExit", t, 0, NOT_BUILT_IN,
- NULL, NULL_TREE);
-
- t = tree_cons (NULL_TREE, int_type_node,
+ t = build_function_type (void_type_node, tree_cons (NULL_TREE, ptr_type_node,
+ endlink));
+ soft_monitorenter_node
+ = add_builtin_function ("_Jv_MonitorEnter", t, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+ soft_monitorexit_node
+ = add_builtin_function ("_Jv_MonitorExit", t, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+
+ t = tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, int_type_node, endlink));
soft_newarray_node
- = builtin_function ("_Jv_NewPrimArray",
- build_function_type(ptr_type_node, t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ = add_builtin_function ("_Jv_NewPrimArray",
+ build_function_type (ptr_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
DECL_IS_MALLOC (soft_newarray_node) = 1;
t = tree_cons (NULL_TREE, int_type_node,
tree_cons (NULL_TREE, class_ptr_type,
- tree_cons (NULL_TREE, object_ptr_type_node, endlink)));
+ tree_cons (NULL_TREE, object_ptr_type_node,
+ endlink)));
soft_anewarray_node
- = builtin_function ("_Jv_NewObjectArray",
- build_function_type (ptr_type_node, t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ = add_builtin_function ("_Jv_NewObjectArray",
+ build_function_type (ptr_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
DECL_IS_MALLOC (soft_anewarray_node) = 1;
/* There is no endlink here because _Jv_NewMultiArray is a varargs
t = tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, int_type_node, NULL_TREE));
soft_multianewarray_node
- = builtin_function ("_Jv_NewMultiArray",
- build_function_type (ptr_type_node, t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ = add_builtin_function ("_Jv_NewMultiArray",
+ build_function_type (ptr_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
DECL_IS_MALLOC (soft_multianewarray_node) = 1;
t = build_function_type (void_type_node,
tree_cons (NULL_TREE, int_type_node, endlink));
soft_badarrayindex_node
- = builtin_function ("_Jv_ThrowBadArrayIndex", t,
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ = add_builtin_function ("_Jv_ThrowBadArrayIndex", t,
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
/* Mark soft_badarrayindex_node as a `noreturn' function with side
effects. */
TREE_THIS_VOLATILE (soft_badarrayindex_node) = 1;
TREE_SIDE_EFFECTS (soft_badarrayindex_node) = 1;
soft_nullpointer_node
- = builtin_function ("_Jv_ThrowNullPointerException",
- build_function_type (void_type_node, endlink),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ = add_builtin_function ("_Jv_ThrowNullPointerException",
+ build_function_type (void_type_node, endlink),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
/* Mark soft_nullpointer_node as a `noreturn' function with side
effects. */
TREE_THIS_VOLATILE (soft_nullpointer_node) = 1;
TREE_SIDE_EFFECTS (soft_nullpointer_node) = 1;
+ soft_abstractmethod_node
+ = add_builtin_function ("_Jv_ThrowAbstractMethodError",
+ build_function_type (void_type_node, endlink),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ /* Mark soft_abstractmethod_node as a `noreturn' function with side
+ effects. */
+ TREE_THIS_VOLATILE (soft_abstractmethod_node) = 1;
+ TREE_SIDE_EFFECTS (soft_abstractmethod_node) = 1;
+
+ soft_nosuchfield_node
+ = add_builtin_function ("_Jv_ThrowNoSuchFieldError",
+ build_function_type (void_type_node, endlink),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ /* Mark soft_nosuchfield_node as a `noreturn' function with side
+ effects. */
+ TREE_THIS_VOLATILE (soft_nosuchfield_node) = 1;
+ TREE_SIDE_EFFECTS (soft_nosuchfield_node) = 1;
+
t = tree_cons (NULL_TREE, class_ptr_type,
tree_cons (NULL_TREE, object_ptr_type_node, endlink));
soft_checkcast_node
- = builtin_function ("_Jv_CheckCast",
- build_function_type (ptr_type_node, t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ = add_builtin_function ("_Jv_CheckCast",
+ build_function_type (ptr_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
t = tree_cons (NULL_TREE, object_ptr_type_node,
tree_cons (NULL_TREE, class_ptr_type, endlink));
soft_instanceof_node
- = builtin_function ("_Jv_IsInstanceOf",
- build_function_type (boolean_type_node, t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ = add_builtin_function ("_Jv_IsInstanceOf",
+ build_function_type (boolean_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ DECL_IS_PURE (soft_instanceof_node) = 1;
t = tree_cons (NULL_TREE, object_ptr_type_node,
tree_cons (NULL_TREE, object_ptr_type_node, endlink));
soft_checkarraystore_node
- = builtin_function ("_Jv_CheckArrayStore",
- build_function_type (void_type_node, t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ = add_builtin_function ("_Jv_CheckArrayStore",
+ build_function_type (void_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
t = tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, int_type_node, endlink)));
- soft_lookupinterfacemethod_node
- = builtin_function ("_Jv_LookupInterfaceMethodIdx",
- build_function_type (ptr_type_node, t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
-
+ soft_lookupinterfacemethod_node
+ = add_builtin_function ("_Jv_LookupInterfaceMethodIdx",
+ build_function_type (ptr_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ DECL_IS_PURE (soft_lookupinterfacemethod_node) = 1;
+ t = tree_cons (NULL_TREE, ptr_type_node,
+ tree_cons (NULL_TREE, ptr_type_node,
+ tree_cons (NULL_TREE, ptr_type_node, endlink)));
+ soft_lookupinterfacemethodbyname_node
+ = add_builtin_function ("_Jv_LookupInterfaceMethod",
+ build_function_type (ptr_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
t = tree_cons (NULL_TREE, object_ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, int_type_node,
endlink))));
soft_lookupjnimethod_node
- = builtin_function ("_Jv_LookupJNIMethod",
- build_function_type (ptr_type_node, t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ = add_builtin_function ("_Jv_LookupJNIMethod",
+ build_function_type (ptr_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
t = tree_cons (NULL_TREE, ptr_type_node, endlink);
soft_getjnienvnewframe_node
- = builtin_function ("_Jv_GetJNIEnvNewFrame",
- build_function_type (ptr_type_node, t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ = add_builtin_function ("_Jv_GetJNIEnvNewFrame",
+ build_function_type (ptr_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
soft_jnipopsystemframe_node
- = builtin_function ("_Jv_JNI_PopSystemFrame",
- build_function_type (ptr_type_node, t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ = add_builtin_function ("_Jv_JNI_PopSystemFrame",
+ build_function_type (void_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
+
+ t = tree_cons (NULL_TREE, object_ptr_type_node, endlink);
+ soft_unwrapjni_node
+ = add_builtin_function ("_Jv_UnwrapJNIweakReference",
+ build_function_type (object_ptr_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ t = tree_cons (NULL_TREE, int_type_node,
+ tree_cons (NULL_TREE, int_type_node, endlink));
soft_idiv_node
- = builtin_function ("_Jv_divI",
- build_function_type (int_type_node, t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ = add_builtin_function ("_Jv_divI",
+ build_function_type (int_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
soft_irem_node
- = builtin_function ("_Jv_remI",
- build_function_type (int_type_node, t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ = add_builtin_function ("_Jv_remI",
+ build_function_type (int_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ t = tree_cons (NULL_TREE, long_type_node,
+ tree_cons (NULL_TREE, long_type_node, endlink));
soft_ldiv_node
- = builtin_function ("_Jv_divJ",
- build_function_type (long_type_node, t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ = add_builtin_function ("_Jv_divJ",
+ build_function_type (long_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
soft_lrem_node
- = builtin_function ("_Jv_remJ",
- build_function_type (long_type_node, t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ = add_builtin_function ("_Jv_remJ",
+ build_function_type (long_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
/* Initialize variables for except.c. */
eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
? "__gcj_personality_sj0"
: "__gcj_personality_v0");
+ default_init_unwind_resume_libfunc ();
lang_eh_runtime_type = do_nothing;
- init_jcf_parse ();
-
initialize_builtins ();
soft_fmod_node = built_in_decls[BUILT_IN_FMOD];
-#if 0
- soft_fmodf_node = built_in_decls[BUILT_IN_FMODF];
-#endif
+
+ parse_version ();
}
}
/* Similar to `lookup_name' but look only at current binding level and
- the previous one if its the parameter level. */
+ the previous one if it's the parameter level. */
static tree
lookup_name_current_level (tree name)
return t;
}
-/* Use a binding level to record a labeled block declaration */
-
-void
-push_labeled_block (tree lb)
-{
- tree name = DECL_NAME (LABELED_BLOCK_LABEL (lb));
- struct binding_level *b = current_binding_level;
- tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
- if (oldlocal != 0)
- b->shadowed = tree_cons (name, oldlocal, b->shadowed);
- TREE_CHAIN (lb) = b->names;
- b->names = lb;
- IDENTIFIER_LOCAL_VALUE (name) = lb;
-}
-
-/* Pop the current binding level, reinstalling values for the previous
- labeled block */
-
-void
-pop_labeled_block (void)
-{
- struct binding_level *b = current_binding_level;
- tree label = b->names;
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (LABELED_BLOCK_LABEL (label))) =
- NULL_TREE;
- if (b->shadowed)
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (b->shadowed)) =
- TREE_VALUE (b->shadowed);
-
- /* Pop the current level, and free the structure for reuse. */
- current_binding_level = current_binding_level->level_chain;
- b->level_chain = free_binding_level;
- free_binding_level = b;
-}
-
/* Record a decl-node X as belonging to the current lexical scope.
Check for errors (such as an incompatible declaration for the same
name already seen in the same scope).
/* error_mark_node is 0 for a while during initialization! */
{
t = 0;
- error ("%J'%D' used prior to declaration", x, x);
+ error ("%q+D used prior to declaration", x);
}
/* If we're naming a hitherto-unnamed type, set its TYPE_NAME
tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
IDENTIFIER_LOCAL_VALUE (name) = x;
-#if 0
- /* Warn if shadowing an argument at the top level of the body. */
- if (oldlocal != 0 && !DECL_EXTERNAL (x)
- /* This warning doesn't apply to the parms of a nested fcn. */
- && ! current_binding_level->parm_flag
- /* Check that this is one level down from the parms. */
- && current_binding_level->level_chain->parm_flag
- /* Check that the decl being shadowed
- comes from the parm level, one level up. */
- && chain_member (oldlocal, current_binding_level->level_chain->names))
- {
- if (TREE_CODE (oldlocal) == PARM_DECL)
- pedwarn ("declaration of `%s' shadows a parameter",
- IDENTIFIER_POINTER (name));
- else
- pedwarn ("declaration of `%s' shadows a symbol from the parameter list",
- IDENTIFIER_POINTER (name));
- }
-
- /* Maybe warn if shadowing something else. */
- else if (warn_shadow && !DECL_EXTERNAL (x)
- /* No shadow warnings for internally generated vars. */
- && DECL_SOURCE_LINE (x) != 0
- /* No shadow warnings for vars made for inlining. */
- && ! DECL_FROM_INLINE (x))
- {
- const char *warnstring = 0;
-
- if (TREE_CODE (x) == PARM_DECL
- && current_binding_level->level_chain->parm_flag)
- /* Don't warn about the parm names in function declarator
- within a function declarator.
- It would be nice to avoid warning in any function
- declarator in a declaration, as opposed to a definition,
- but there is no way to tell it's not a definition. */
- ;
- else if (oldlocal != 0 && TREE_CODE (oldlocal) == PARM_DECL)
- warnstring = "declaration of `%s' shadows a parameter";
- else if (oldlocal != 0)
- warnstring = "declaration of `%s' shadows previous local";
- else if (IDENTIFIER_GLOBAL_VALUE (name) != 0
- && IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node)
- warnstring = "declaration of `%s' shadows global declaration";
-
- if (warnstring)
- warning (warnstring, IDENTIFIER_POINTER (name));
- }
-#endif
-
/* If storing a local value, there may already be one (inherited).
If so, record it for restoration when this binding level ends. */
if (oldlocal != 0)
return t;
}
+/* Like pushdecl, only it places X in FUNCTION_BINDING_LEVEL, if appropriate. */
+
+tree
+pushdecl_function_level (tree x)
+{
+ tree t;
+ struct binding_level *b = current_binding_level;
+
+ current_binding_level = function_binding_level;
+ t = pushdecl (x);
+ current_binding_level = b;
+ return t;
+}
+
/* Nonzero if we are currently in the global binding level. */
int
{
struct binding_level *newlevel = NULL_BINDING_LEVEL;
-#if 0
- /* If this is the top level of a function,
- just make sure that NAMED_LABELS is 0. */
-
- if (current_binding_level == global_binding_level)
- named_labels = 0;
-#endif
-
/* Reuse or create a struct for this binding level. */
if (free_binding_level)
tree block = 0;
tree decl;
tree bind = 0;
- int block_previously_created;
#if defined(DEBUG_JAVA_BINDING_LEVELS)
binding_depth--;
else
fprintf (stderr, "pop %s level %p pc %d\n",
(is_class_level) ? "class" : "block", current_binding_level, current_pc);
-#if 0
- if (is_class_level != (current_binding_level == class_binding_level))
- {
- indent ();
- fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n");
- }
- is_class_level = 0;
-#endif
#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
/* Get the decls in the order they were written.
create a BLOCK to record them for the life of this function. */
block = 0;
- block_previously_created = (current_binding_level->this_block != 0);
- if (block_previously_created)
- block = current_binding_level->this_block;
- else if (keep || functionbody)
+ if (keep || functionbody)
{
block = make_node (BLOCK);
TREE_TYPE (block) = void_type_node;
}
*var = NULL;
- bind = build (BIND_EXPR, TREE_TYPE (block), BLOCK_VARS (block),
+ bind = build3 (BIND_EXPR, TREE_TYPE (block), BLOCK_VARS (block),
BLOCK_EXPR_BODY (block), block);
BIND_EXPR_BODY (bind) = current_binding_level->stmts;
found in the FUNCTION_DECL instead. */
BLOCK_VARS (block) = 0;
-
- /* Clear out the definitions of all label names,
- since their scopes end here,
- and add them to BLOCK_VARS. */
-
-#if 0
- for (link = named_labels; link; link = TREE_CHAIN (link))
- {
- tree label = TREE_VALUE (link);
-
- if (DECL_INITIAL (label) == 0)
- {
- error ("%Jlabel '%D' used but not defined", label, label);
- /* Avoid crashing later. */
- define_label (input_location, DECL_NAME (label));
- }
- else if (warn_unused[UNUSED_LABEL] && !TREE_USED (label))
- warning ("%Jlabel '%D' defined but not used", label, label);
- IDENTIFIER_LABEL_VALUE (DECL_NAME (label)) = 0;
-
- /* Put the labels into the "variables" of the
- top-level block, so debugger can see them. */
- TREE_CHAIN (label) = BLOCK_VARS (block);
- BLOCK_VARS (block) = label;
- }
-#endif
}
/* Pop the current level, and free the structure for reuse. */
{
if (block)
{
- if (!block_previously_created)
- current_binding_level->blocks
- = chainon (current_binding_level->blocks, block);
+ current_binding_level->blocks
+ = chainon (current_binding_level->blocks, block);
}
/* If we did not make a block for the level just exited,
any blocks made for inner levels
pending_local_decls = *ptr;
*ptr = NULL_TREE;
- /* Force non-nested range to be nested in current range. */
+ /* Force non-nested range to be nested in current range by
+ truncating variable lifetimes. */
if (end_pc > current_binding_level->end_pc)
- end_pc = current_binding_level->end_pc;
+ {
+ tree t;
+ end_pc = current_binding_level->end_pc;
+ for (t = decl; t != NULL_TREE; t = TREE_CHAIN (t))
+ DECL_LOCAL_END_PC (t) = end_pc;
+ }
maybe_start_try (pc, end_pc);
current_binding_level->names = NULL;
for ( ; decl != NULL_TREE; decl = next)
{
+ int index = DECL_LOCAL_SLOT_NUMBER (decl);
+ tree base_decl;
next = TREE_CHAIN (decl);
- push_jvm_slot (DECL_LOCAL_SLOT_NUMBER (decl), decl);
+ push_jvm_slot (index, decl);
+ pushdecl (decl);
+ base_decl
+ = find_local_variable (index, TREE_TYPE (decl), pc);
+ if (TREE_CODE (TREE_TYPE (base_decl)) == POINTER_TYPE)
+ base_decl = TREE_VEC_ELT (base_decl_map, index);
+ SET_DECL_VALUE_EXPR (decl, base_decl);
+ DECL_HAS_VALUE_EXPR_P (decl) = 1;
}
}
current_pc = pc;
#endif
+ /* FIXME: I'm pretty sure that this is wrong. Variable scopes are
+ inclusive, so a variable is live if pc == end_pc. Here, we
+ terminate a range if the current pc is equal to the end of the
+ range, and this is *before* we have generated code for the
+ instruction at end_pc. We're closing a binding level one
+ instruction too early.*/
while (current_binding_level->end_pc <= pc)
poplevel (1, 0, 0);
}
while (current_binding_level->start_pc > start_pc)
{
if (pedantic && current_binding_level->start_pc > start_pc)
- warning ("%JIn %D: overlapped variable and exception ranges at %d",
- current_function_decl, current_function_decl,
+ warning (0, "In %+D: overlapped variable and exception ranges at %d",
+ current_function_decl,
current_binding_level->start_pc);
poplevel (1, 0, 0);
}
= chainon (current_binding_level->blocks, block);
}
-/* Set the BLOCK node for the innermost scope
- (the one we are currently in). */
-
-void
-set_block (tree block)
-{
- current_binding_level->this_block = block;
- current_binding_level->names = chainon (current_binding_level->names,
- BLOCK_VARS (block));
- current_binding_level->blocks = chainon (current_binding_level->blocks,
- BLOCK_SUBBLOCKS (block));
-}
-
/* integrate_decl_tree calls this function. */
void
{
tree decl = TREE_VEC_ELT (decl_map, slot);
DECL_NAME (decl) = name;
- SET_DECL_ASSEMBLER_NAME (decl, name);
if (TREE_CODE (decl) != PARM_DECL || TREE_TYPE (decl) != type)
- warning ("bad type in parameter debug info");
+ warning (0, "bad type in parameter debug info");
}
else
{
tree decl = build_decl (VAR_DECL, name, type);
if (end_pc > DECL_CODE_LENGTH (current_function_decl))
{
- warning ("%Jbad PC range for debug info for local '%D'",
- decl, decl);
+ warning (0, "bad PC range for debug info for local %q+D",
+ decl);
end_pc = DECL_CODE_LENGTH (current_function_decl);
}
MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
DECL_LOCAL_SLOT_NUMBER (decl) = slot;
DECL_LOCAL_START_PC (decl) = start_pc;
-#if 0
- /* FIXME: The range used internally for exceptions and local
- variable ranges, is a half-open interval:
- start_pc <= pc < end_pc. However, the range used in the
- Java VM spec is inclusive at both ends:
- start_pc <= pc <= end_pc. */
- end_pc++;
-#endif
DECL_LOCAL_END_PC (decl) = end_pc;
/* Now insert the new decl in the proper place in
sprintf (buffer, "ARG_%d", arg_i);
DECL_NAME (parm) = get_identifier (buffer);
}
- SET_DECL_ASSEMBLER_NAME (parm, DECL_NAME (parm));
}
}
}
&& TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node))
restype = integer_type_node;
result = build_decl (RESULT_DECL, NULL_TREE, restype);
+ DECL_ARTIFICIAL (result) = 1;
+ DECL_IGNORED_P (result) = 1;
DECL_CONTEXT (result) = fndecl;
DECL_RESULT (fndecl) = result;
}
tree tem, *ptr;
int i;
+ uniq = 0;
+
current_function_decl = fndecl;
announce_function (fndecl);
i = DECL_MAX_LOCALS(fndecl) + DECL_MAX_STACK(fndecl);
decl_map = make_tree_vec (i);
+ base_decl_map = make_tree_vec (i);
type_map = xrealloc (type_map, i * sizeof (tree));
#if defined(DEBUG_JAVA_BINDING_LEVELS)
{
tree parm_name = NULL_TREE, parm_decl;
tree parm_type = TREE_VALUE (tem);
- if (i >= DECL_MAX_LOCALS (fndecl))
- abort ();
+ gcc_assert (i < DECL_MAX_LOCALS (fndecl));
parm_decl = build_decl (PARM_DECL, parm_name, parm_type);
DECL_CONTEXT (parm_decl) = fndecl;
/* Push local variables. */
pushlevel (2);
+
+ function_binding_level = current_binding_level;
}
void
poplevel (1, 0, 1);
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
+
+ if (DECL_SAVED_TREE (fndecl))
+ {
+ tree fbody, block_body;
+ /* Before we check initialization, attached all class initialization
+ variable to the block_body */
+ fbody = DECL_SAVED_TREE (fndecl);
+ block_body = BIND_EXPR_BODY (fbody);
+ htab_traverse (DECL_FUNCTION_INIT_TEST_TABLE (fndecl),
+ attach_init_test_initialization_flags, block_body);
+ }
- flag_unit_at_a_time = 0;
finish_method (fndecl);
if (! flag_unit_at_a_time)
lock = DECL_ARGUMENTS (fndecl);
BUILD_MONITOR_ENTER (enter, lock);
BUILD_MONITOR_EXIT (exit, lock);
- *tp = build (COMPOUND_EXPR, void_type_node,
- enter,
- build (TRY_FINALLY_EXPR, void_type_node, *tp, exit));
- }
-
- /* Prepend class initialization for static methods reachable from
- other classes. */
- if (METHOD_STATIC (fndecl) && ! METHOD_PRIVATE (fndecl)
- && ! DECL_CLINIT_P (fndecl)
- && ! CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (fndecl))))
- {
- tree clas = DECL_CONTEXT (fndecl);
- tree init = build (CALL_EXPR, void_type_node,
- build_address_of (soft_initclass_node),
- build_tree_list (NULL_TREE, build_class_ref (clas)),
- NULL_TREE);
- *tp = build (COMPOUND_EXPR, TREE_TYPE (*tp), init, *tp);
+ *tp = build2 (COMPOUND_EXPR, void_type_node, enter,
+ build2 (TRY_FINALLY_EXPR, void_type_node, *tp, exit));
}
/* Convert function tree to GENERIC prior to inlining. */
cfun = DECL_STRUCT_FUNCTION (fndecl);
else
allocate_struct_function (fndecl);
+#ifdef USE_MAPPED_LOCATION
+ cfun->function_end_locus = DECL_FUNCTION_LAST_LINE (fndecl);
+#else
cfun->function_end_locus.file = DECL_SOURCE_FILE (fndecl);
cfun->function_end_locus.line = DECL_FUNCTION_LAST_LINE (fndecl);
+#endif
/* Defer inlining and expansion to the cgraph optimizers. */
cgraph_finalize_function (fndecl, false);
void
java_expand_body (tree fndecl)
{
- tree_rest_of_compilation (fndecl, 0);
+ tree_rest_of_compilation (fndecl);
}
/* We pessimistically marked all methods and fields external until we
/* If we've already constructed DECL_RTL, give encode_section_info
a second chance, now that we've changed the flags. */
+ /* ??? Ideally, we'd have flag_unit_at_a_time set, and not have done
+ anything that would have referenced DECL_RTL so far. But at the
+ moment we force flag_unit_at_a_time off due to excessive memory
+ consumption when compiling large jar files. Which probably means
+ that we need to re-order how we process jar files... */
if (DECL_RTL_SET_P (decl))
- make_decl_rtl (decl, NULL);
+ make_decl_rtl (decl);
}
+/* Given appropriate target support, G++ will emit hidden aliases for native
+ methods. Using this hidden name is required for proper operation of
+ _Jv_Method::ncode, but it doesn't hurt to use it everywhere. Look for
+ proper target support, then mark the method for aliasing. */
+
+static void
+java_mark_cni_decl_local (tree decl)
+{
+ /* Setting DECL_LOCAL_CNI_METHOD_P changes the behavior of the mangler.
+ We expect that we should not yet have referenced this decl in a
+ context that requires it. Check this invariant even if we don't have
+ support for hidden aliases. */
+ gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl));
+
+#if !defined(HAVE_GAS_HIDDEN) || !defined(ASM_OUTPUT_DEF)
+ return;
+#endif
+
+ DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ DECL_LOCAL_CNI_METHOD_P (decl) = 1;
+}
+
+/* Use the preceding two functions and mark all members of the class. */
+
void
java_mark_class_local (tree class)
{
java_mark_decl_local (t);
for (t = TYPE_METHODS (class); t ; t = TREE_CHAIN (t))
- if (!METHOD_ABSTRACT (t) && (!METHOD_NATIVE (t) || flag_jni))
- java_mark_decl_local (t);
+ if (!METHOD_ABSTRACT (t))
+ {
+ if (METHOD_NATIVE (t) && !flag_jni)
+ java_mark_cni_decl_local (t);
+ else
+ java_mark_decl_local (t);
+ }
}
/* Add a statement to a compound_expr. */
return existing;
else if (existing)
{
- tree expr = build (COMPOUND_EXPR, type, existing, stmt);
- TREE_SIDE_EFFECTS (expr)
- = TREE_SIDE_EFFECTS (existing) | TREE_SIDE_EFFECTS (stmt);
+ tree expr = build2 (COMPOUND_EXPR, type, existing, stmt);
+ TREE_SIDE_EFFECTS (expr) = TREE_SIDE_EFFECTS (existing)
+ | TREE_SIDE_EFFECTS (stmt);
return expr;
}
else
return stmt;
}
-/* Add a statement to the compound_expr currently being
- constructed. */
+/* Add a statement to the statement_list currently being constructed.
+ If the statement_list is null, we don't create a singleton list.
+ This is necessary because poplevel() assumes that adding a
+ statement to a null statement_list returns the statement. */
tree
-java_add_stmt (tree stmt)
+java_add_stmt (tree new_stmt)
{
+ tree stmts = current_binding_level->stmts;
+ tree_stmt_iterator i;
+
if (input_filename)
- annotate_with_locus (stmt, input_location);
+ SET_EXPR_LOCATION (new_stmt, input_location);
- return current_binding_level->stmts
- = add_stmt_to_compound (current_binding_level->stmts,
- TREE_TYPE (stmt), stmt);
+ if (stmts == NULL)
+ return current_binding_level->stmts = new_stmt;
+
+ /* Force STMTS to be a statement_list. */
+ if (TREE_CODE (stmts) != STATEMENT_LIST)
+ {
+ tree t = make_node (STATEMENT_LIST);
+ i = tsi_last (t);
+ tsi_link_after (&i, stmts, TSI_CONTINUE_LINKING);
+ stmts = t;
+ }
+
+ i = tsi_last (stmts);
+ tsi_link_after (&i, new_stmt, TSI_CONTINUE_LINKING);
+ TREE_TYPE (stmts) = void_type_node;
+
+ return current_binding_level->stmts = stmts;
}
/* Add a variable to the current scope. */
void
register_exception_range (struct eh_range *range, int pc, int end_pc)
{
- if (current_binding_level->exception_range)
- abort ();
+ gcc_assert (! current_binding_level->exception_range);
current_binding_level->exception_range = range;
current_binding_level->end_pc = end_pc;
current_binding_level->start_pc = pc;