/* 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.
#include "cgraph.h"
#include "tree-inline.h"
#include "target.h"
+#include "version.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);
+
+/* Used when computing the ABI version. */
+#define GCJ_BINARYCOMPAT_ADDITION 5
+
+/* 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. */
-
#if defined(DEBUG_JAVA_BINDING_LEVELS)
int binding_depth = 0;
int is_class_level = 0;
}
#endif /* defined(DEBUG_JAVA_BINDING_LEVELS) */
-/* Copy the value in decl into every alias in the same local variable
- slot. */
+/* 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)
+{
+ if (TREE_CODE (decl) == PARM_DECL)
+ return false;
+
+ if (LOCAL_SLOT_P (decl))
+ return false;
+
+ return true;
+}
+
+/* Copy the value in decl into every live alias in the same local
+ variable slot. Some of these will be dead stores removed by the
+ optimizer. */
+
void
-update_aliases (tree decl, int index)
+update_aliases (tree decl, int index, int pc)
{
- tree tmp = TREE_VEC_ELT (decl_map, index);
- tree type = TREE_TYPE (decl);
- while (tmp != NULL_TREE)
+ tree decl_type = TREE_TYPE (decl);
+ tree tmp;
+
+ if (debug_variable_p (decl))
+ abort ();
+
+ for (tmp = TREE_VEC_ELT (decl_map, index);
+ tmp != NULL_TREE;
+ tmp = DECL_LOCAL_SLOT_CHAIN (tmp))
{
+ tree tmp_type = TREE_TYPE (tmp);
if (tmp != decl
- && ! LOCAL_VAR_OUT_OF_SCOPE_P (tmp)
- && TYPE_MODE (type) == TYPE_MODE (TREE_TYPE (tmp)))
+ && LOCAL_SLOT_P (tmp) == 0
+ && (pc == -1
+ || (pc >= DECL_LOCAL_START_PC (tmp)
+ && pc <= DECL_LOCAL_END_PC (tmp)))
+ && (tmp_type == decl_type
+ || (INTEGRAL_TYPE_P (tmp_type)
+ && INTEGRAL_TYPE_P (decl_type)
+ && TYPE_PRECISION (decl_type) <= 32
+ && TYPE_PRECISION (tmp_type) <= 32)
+ || (TREE_CODE (tmp_type) == POINTER_TYPE
+ && TREE_CODE (decl_type) == POINTER_TYPE)))
{
- tree src = build1 (NOP_EXPR, TREE_TYPE (tmp), decl);
- java_add_stmt
- (build (MODIFY_EXPR, TREE_TYPE (tmp), tmp, src));
+ tree src = build1 (NOP_EXPR, tmp_type, decl);
+ if (LOCAL_VAR_OUT_OF_SCOPE_P (tmp))
+ abort ();
+ java_add_stmt (build2 (MODIFY_EXPR, tmp_type, tmp, src));
}
- tmp = DECL_LOCAL_SLOT_CHAIN (tmp);
}
}
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. */
+/* At the point of its creation a local variable decl inherits
+ whatever is already in the same slot. In the case of a local
+ variable that is declared but unused, we won't find anything. */
-static tree
-check_local_named_variable (tree best, tree decl, int pc, int *updated)
+static void
+initialize_local_variable (tree decl, int index)
{
- if (pc >= DECL_LOCAL_START_PC (decl)
- && pc < DECL_LOCAL_END_PC (decl))
+ tree decl_type = TREE_TYPE (decl);
+ if (TREE_CODE (decl_type) == POINTER_TYPE)
{
- if (best == NULL_TREE
- || (DECL_LOCAL_START_PC (decl) > DECL_LOCAL_START_PC (best)
- && DECL_LOCAL_END_PC (decl) < DECL_LOCAL_END_PC (best)))
+ tree tmp = TREE_VEC_ELT (base_decl_map, index);
+
+ if (tmp)
{
- *updated = 1;
- return decl;
+ /* At the point of its creation this decl inherits whatever
+ is in the slot. */
+ tree src = build1 (NOP_EXPR, decl_type, tmp);
+ java_add_stmt (build2 (MODIFY_EXPR, decl_type, decl, src));
}
}
+ else
+ {
+ tree tmp;
- return best;
+ for (tmp = TREE_VEC_ELT (decl_map, index);
+ tmp != NULL_TREE;
+ tmp = DECL_LOCAL_SLOT_CHAIN (tmp))
+ {
+ tree tmp_type = TREE_TYPE (tmp);
+ if (tmp != decl
+ && ! debug_variable_p (tmp)
+ && (tmp_type == decl_type
+ || (INTEGRAL_TYPE_P (tmp_type)
+ && INTEGRAL_TYPE_P (decl_type)
+ && TYPE_PRECISION (decl_type) <= 32
+ && TYPE_PRECISION (tmp_type) <= 32
+ && TYPE_PRECISION (tmp_type)
+ >= TYPE_PRECISION (decl_type))))
+ {
+ java_add_stmt (build2 (MODIFY_EXPR, decl_type, decl, tmp));
+ return;
+ }
+ }
+ }
}
/* Find the best declaration based upon type. If 'decl' fits 'type' better
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;
- }
-
- return best;
+ tree decl_type = TREE_TYPE (decl);
+
+ if (LOCAL_VAR_OUT_OF_SCOPE_P (decl))
+ abort ();
+
+ /* 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;
}
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);
+
+ if (! base_decl)
+ abort ();
+
+ 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 */
builtin_function (const char *name,
tree type,
int function_code,
- enum built_in_class class,
+ enum built_in_class cl,
const char *library_name,
- tree attrs ATTRIBUTE_UNUSED)
+ tree ARG_UNUSED (attrs))
{
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);
+ make_decl_rtl (decl);
pushdecl (decl);
- DECL_BUILT_IN_CLASS (decl) = class;
+ DECL_BUILT_IN_CLASS (decl) = cl;
DECL_FUNCTION_CODE (decl) = function_code;
return decl;
}
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;
+ }
+
+ /* 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 = 10000 * major + 10 * minor;
+ /* It is helpful to distinguish BC ABI from ordinary ABI at this
+ level, since at some point we will recognize a variety of BC ABIs
+ (objects generated by different version of gcj), but will
+ probably always require strict matching for ordinary ABI. */
+ if (flag_indirect_dispatch)
+ abi_version += GCJ_BINARYCOMPAT_ADDITION;
+
+ gcj_abi_version = build_int_cstu (ptr_type_node, abi_version);
+}
void
java_init_decl_processing (void)
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
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);
= 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_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,
#if 0
soft_fmodf_node = built_in_decls[BUILT_IN_FMODF];
#endif
+
+ parse_version ();
}
&& 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));
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
tree block = 0;
tree decl;
tree bind = 0;
- int block_previously_created;
#if defined(DEBUG_JAVA_BINDING_LEVELS)
binding_depth--;
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;
{
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;
+ {
+ end_pc = current_binding_level->end_pc;
+ DECL_LOCAL_END_PC (decl) = end_pc;
+ }
maybe_start_try (pc, end_pc);
{
next = TREE_CHAIN (decl);
push_jvm_slot (DECL_LOCAL_SLOT_NUMBER (decl), decl);
+ pushdecl (decl);
+ initialize_local_variable (decl, DECL_LOCAL_SLOT_NUMBER (decl));
}
}
= 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
&& 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)
/* 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);
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));
+ *tp = build2 (COMPOUND_EXPR, void_type_node, enter,
+ build2 (TRY_FINALLY_EXPR, void_type_node, *tp, exit));
}
+ /* Ensure non-abstract non-static non-private members are defined only once
+ when linking. This is an issue when using CNI to interface with C++ object
+ files. */
+ if (! METHOD_STATIC (fndecl) && ! METHOD_PRIVATE (fndecl)
+ && ! METHOD_ABSTRACT (fndecl))
+ make_decl_one_only (fndecl);
+
/* Prepend class initialization for static methods reachable from
other classes. */
if (METHOD_STATIC (fndecl) && ! METHOD_PRIVATE (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);
+ tree init = build3 (CALL_EXPR, void_type_node,
+ build_address_of (soft_initclass_node),
+ build_tree_list (NULL_TREE, build_class_ref (clas)),
+ NULL_TREE);
+ *tp = build2 (COMPOUND_EXPR, TREE_TYPE (*tp), init, *tp);
}
/* 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. */
if (DECL_RTL_SET_P (decl))
- make_decl_rtl (decl, NULL);
+ make_decl_rtl (decl);
}
void
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
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,