/* Process declarations and variables for the GNU compiler for the
Java(TM) language.
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GCC.
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.
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
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"
#if defined (DEBUG_JAVA_BINDING_LEVELS)
extern void indent (void);
static struct binding_level *make_binding_level (void);
static tree create_primitive_vtable (const char *);
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 can be set to
+ enforce the compatibility rules. */
+#define MINOR_BINARYCOMPAT_ABI_VERSION 0
+
+/* 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 pending_local_decls;
+/* The decl for "_Jv_ResolvePoolEntry". */
+tree soft_resolvepoolentry_node;
+
#if defined(DEBUG_JAVA_BINDING_LEVELS)
int binding_depth = 0;
int is_class_level = 0;
tree decl_type = TREE_TYPE (decl);
tree tmp;
- if (debug_variable_p (decl))
- abort ();
+ gcc_assert (! debug_variable_p (decl));
for (tmp = TREE_VEC_ELT (decl_map, index);
tmp != NULL_TREE;
&& LOCAL_SLOT_P (tmp) == 0
&& (pc == -1
|| (pc >= DECL_LOCAL_START_PC (tmp)
- && pc <= DECL_LOCAL_END_PC (tmp)))
+ && pc < DECL_LOCAL_END_PC (tmp)))
+ /* This test is < (rather than <=) because there's no point
+ updating an alias that's about to die at the end of this
+ instruction. */
&& (tmp_type == decl_type
|| (INTEGRAL_TYPE_P (tmp_type)
&& INTEGRAL_TYPE_P (decl_type)
&& TREE_CODE (decl_type) == POINTER_TYPE)))
{
tree src = build1 (NOP_EXPR, tmp_type, decl);
- if (LOCAL_VAR_OUT_OF_SCOPE_P (tmp))
- abort ();
+ gcc_assert (! LOCAL_VAR_OUT_OF_SCOPE_P (tmp));
java_add_stmt (build2 (MODIFY_EXPR, tmp_type, tmp, src));
}
}
{
tree decl_type = TREE_TYPE (decl);
- if (LOCAL_VAR_OUT_OF_SCOPE_P (decl))
- abort ();
+ 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)
|| (INTEGRAL_TYPE_P (decl_type)
&& INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (decl_type) <= 32
- && TYPE_PRECISION (type) <= 32
+ && TYPE_PRECISION (type) <= 32
&& TYPE_PRECISION (decl_type) >= TYPE_PRECISION (type))
- || (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
- && type == ptr_type_node))
- {
- if (best == NULL_TREE
+ /* 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 decl;
+ }
- return best;
+ return best;
}
tmp = DECL_LOCAL_SLOT_CHAIN (tmp);
}
+ /* 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.
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
variable that is used for every reference in that local variable
slot. */
if (! decl)
- {
- char buf[64];
- tree name;
+ {
+ char buf[64];
+ tree name;
sprintf (buf, "#slot#%d#%d", index, uniq++);
name = get_identifier (buf);
decl = build_decl (VAR_DECL, name, type);
int index = DECL_LOCAL_SLOT_NUMBER (var_decl);
tree base_decl = TREE_VEC_ELT (base_decl_map, index);
- if (! base_decl)
- abort ();
-
+ gcc_assert (base_decl);
if (! want_lvalue)
base_decl = build1 (NOP_EXPR, decl_type, base_decl);
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;
TREE_PUBLIC (decl) = 1;
if (library_name)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
- make_decl_rtl (decl);
pushdecl (decl);
DECL_BUILT_IN_CLASS (decl) = cl;
DECL_FUNCTION_CODE (decl) = function_code;
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)
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);
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. */
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, "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);
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);
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));
+ t = tree_cons (NULL_TREE, class_ptr_type, endlink);
alloc_object_node = builtin_function ("_Jv_AllocObject",
build_function_type (ptr_type_node, t),
0, NOT_BUILT_IN, NULL, NULL_TREE);
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
+ = 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 = builtin_function ("_Jv_Throw",
- build_function_type (ptr_type_node, t),
+ 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);
+ t = build_function_type (void_type_node, tree_cons (NULL_TREE, ptr_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 = 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),
+ 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),
TREE_THIS_VOLATILE (soft_nullpointer_node) = 1;
TREE_SIDE_EFFECTS (soft_nullpointer_node) = 1;
+ soft_abstractmethod_node
+ = 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
+ = 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_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
+ = 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,
0, NOT_BUILT_IN, NULL, NULL_TREE);
soft_jnipopsystemframe_node
= builtin_function ("_Jv_JNI_PopSystemFrame",
- build_function_type (ptr_type_node, t),
+ 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
+ = 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),
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),
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;
#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)
/* 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
&& chain_member (oldlocal, current_binding_level->level_chain->names))
{
if (TREE_CODE (oldlocal) == PARM_DECL)
- pedwarn ("declaration of `%s' shadows a parameter",
+ pedwarn ("declaration of %qs shadows a parameter",
IDENTIFIER_POINTER (name));
else
- pedwarn ("declaration of `%s' shadows a symbol from the parameter list",
+ pedwarn ("declaration of %qs shadows a symbol from the parameter list",
IDENTIFIER_POINTER (name));
}
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";
+ warnstring = "declaration of %qs shadows a parameter";
else if (oldlocal != 0)
- warnstring = "declaration of `%s' shadows previous local";
+ warnstring = "declaration of %qs shadows previous local";
else if (IDENTIFIER_GLOBAL_VALUE (name) != 0
&& IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node)
- warnstring = "declaration of `%s' shadows global declaration";
+ warnstring = "declaration of %qs shadows global declaration";
if (warnstring)
- warning (warnstring, IDENTIFIER_POINTER (name));
+ warning (0, warnstring, IDENTIFIER_POINTER (name));
}
#endif
if (DECL_INITIAL (label) == 0)
{
- error ("%Jlabel '%D' used but not defined", label, label);
+ error ("label %q+D used but not defined", 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);
+ warning (0, "label %q+D defined but not used", label);
IDENTIFIER_LABEL_VALUE (DECL_NAME (label)) = 0;
/* Put the labels into the "variables" of the
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);
}
{
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);
}
sprintf (buffer, "ARG_%d", arg_i);
DECL_NAME (parm) = get_identifier (buffer);
}
- SET_DECL_ASSEMBLER_NAME (parm, DECL_NAME (parm));
}
}
}
{
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;
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)
DECL_STRUCT_FUNCTION (fndecl) = NULL;
DECL_INITIAL (fndecl) = NULL_TREE;
}
- if (! flag_unit_at_a_time)
- {
- /* Nulling these fields when we no longer need them saves
- memory. */
- DECL_SAVED_TREE (fndecl) = NULL;
- DECL_STRUCT_FUNCTION (fndecl) = NULL;
- DECL_INITIAL (fndecl) = NULL_TREE;
- }
current_function_decl = NULL_TREE;
}
/* Prepend class initialization for static methods reachable from
other classes. */
- if (METHOD_STATIC (fndecl) && ! METHOD_PRIVATE (fndecl)
+ if (METHOD_STATIC (fndecl)
+ && (! METHOD_PRIVATE (fndecl)
+ || INNER_CLASS_P (DECL_CONTEXT (fndecl)))
&& ! DECL_CLINIT_P (fndecl)
&& ! CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (fndecl))))
{
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);
}
+/* 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. */
java_add_stmt (tree stmt)
{
if (input_filename)
- annotate_with_locus (stmt, input_location);
+ SET_EXPR_LOCATION (stmt, input_location);
return current_binding_level->stmts
= add_stmt_to_compound (current_binding_level->stmts,
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;