#include "tree-inline.h"
#include "target.h"
#include "version.h"
+#include "tree-iterator.h"
#if defined (DEBUG_JAVA_BINDING_LEVELS)
extern void indent (void);
/* 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;
int is_class_level = 0;
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, int pc)
-{
- 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_SLOT_P (tmp) == 0
- && (pc == -1
- || (pc >= DECL_LOCAL_START_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)
- && 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, tmp_type, decl);
- if (LOCAL_VAR_OUT_OF_SCOPE_P (tmp))
- abort ();
- java_add_stmt (build2 (MODIFY_EXPR, tmp_type, tmp, src));
- }
- }
-}
-
static tree
push_jvm_slot (int index, tree decl)
{
return decl;
}
-/* 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 void
-initialize_local_variable (tree decl, int index)
-{
- tree decl_type = TREE_TYPE (decl);
- if (TREE_CODE (decl_type) == POINTER_TYPE)
- {
- tree tmp = TREE_VEC_ELT (base_decl_map, index);
-
- if (tmp)
- {
- /* 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;
-
- 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
than 'best', return 'decl'. Otherwise return 'best'. */
{
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)
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;
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));
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);
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);
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
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
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;
}
/* 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
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 (0, "%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
truncating variable lifetimes. */
if (end_pc > current_binding_level->end_pc)
{
+ tree t;
end_pc = current_binding_level->end_pc;
- DECL_LOCAL_END_PC (decl) = 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);
- initialize_local_variable (decl, DECL_LOCAL_SLOT_NUMBER (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;
}
}
while (current_binding_level->start_pc > start_pc)
{
if (pedantic && current_binding_level->start_pc > start_pc)
- warning (0, "%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 = build_decl (VAR_DECL, name, type);
if (end_pc > DECL_CODE_LENGTH (current_function_decl))
{
- warning (0, "%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);
}
{
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;
attach_init_test_initialization_flags, block_body);
}
- flag_unit_at_a_time = 0;
finish_method (fndecl);
if (! flag_unit_at_a_time)
static void
java_mark_cni_decl_local (tree decl)
{
- /* Setting DECL_LOCAL_CNI_METHOD_P changes the behaviour of the mangler.
+ /* 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. */
DECL_LOCAL_CNI_METHOD_P (decl) = 1;
}
-/* Use the preceeding two functions and mark all members of the class. */
+/* Use the preceding two functions and mark all members of the class. */
void
java_mark_class_local (tree class)
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)
- SET_EXPR_LOCATION (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);
+
+ 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;