/* Process expressions for the GNU compiler for the Java(TM) language.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2005, 2006, 2007, 2008, 2010 Free Software Foundation, Inc.
This file is part of GCC.
#include "parse.h"
#include "toplev.h"
#include "except.h"
+#include "tm_p.h"
#include "ggc.h"
#include "tree-iterator.h"
#include "gimple.h"
static void expand_java_goto (int);
static tree expand_java_switch (tree, int);
static void expand_java_add_case (tree, int, int);
-static tree pop_arguments (tree);
+static VEC(tree,gc) *pop_arguments (tree);
static void expand_invoke (int, int, int);
static void expand_java_field_op (int, int, int);
static void java_push_constant_from_pool (struct JCF *, int);
{
while (count > 0)
{
- tree type, val;
+ tree type;
gcc_assert (stack_pointer != 0);
type = stack_type_map[stack_pointer - 2];
}
- val = pop_value (type);
+ pop_value (type);
count--;
}
}
flush_quick_stack ();
decl1 = find_stack_slot (stack_pointer - 1, type1);
decl2 = find_stack_slot (stack_pointer - 2, type2);
- temp = build_decl (VAR_DECL, NULL_TREE, type1);
+ temp = build_decl (input_location, VAR_DECL, NULL_TREE, type1);
java_add_local_var (temp);
java_add_stmt (build2 (MODIFY_EXPR, type1, temp, decl1));
java_add_stmt (build2 (MODIFY_EXPR, type2,
expand_java_multianewarray (tree class_type, int ndim)
{
int i;
- tree args = build_tree_list( NULL_TREE, null_pointer_node );
+ VEC(tree,gc) *args = NULL;
+
+ VEC_safe_grow (tree, gc, args, 3 + ndim);
+
+ VEC_replace (tree, args, 0, build_class_ref (class_type));
+ VEC_replace (tree, args, 1, build_int_cst (NULL_TREE, ndim));
- for( i = 0; i < ndim; i++ )
- args = tree_cons (NULL_TREE, pop_value (int_type_node), args);
+ for(i = ndim - 1; i >= 0; i-- )
+ VEC_replace (tree, args, (unsigned)(2 + i), pop_value (int_type_node));
- args = tree_cons (NULL_TREE,
- build_class_ref (class_type),
- tree_cons (NULL_TREE,
- build_int_cst (NULL_TREE, ndim),
- args));
+ VEC_replace (tree, args, 2 + ndim, null_pointer_node);
- push_value (build_call_list (promote_type (class_type),
- build_address_of (soft_multianewarray_node),
- args));
+ push_value (build_call_vec (promote_type (class_type),
+ build_address_of (soft_multianewarray_node),
+ args));
}
/* ARRAY[INDEX] <- RHS. build_java_check_indexed_type makes sure that
MODIFY_EXPR to set the array element. */
access = build_java_arrayaccess (array, rhs_type_node, index);
- temp = build_decl (VAR_DECL, NULL_TREE,
+ temp = build_decl (input_location, VAR_DECL, NULL_TREE,
build_pointer_type (TREE_TYPE (access)));
java_add_local_var (temp);
java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (temp),
generated. To avoid this we create a new local and copy our
value into it. Then we push this new local on the stack.
Hopefully this all gets optimized out. */
- copy = build_decl (VAR_DECL, NULL_TREE, type);
+ copy = build_decl (input_location, VAR_DECL, NULL_TREE, type);
if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
&& TREE_TYPE (copy) != TREE_TYPE (var))
var = convert (type, var);
create_label_decl (tree name)
{
tree decl;
- decl = build_decl (LABEL_DECL, name,
+ decl = build_decl (input_location, LABEL_DECL, name,
TREE_TYPE (return_address_type_node));
DECL_CONTEXT (decl) = current_function_decl;
DECL_IGNORED_P (decl) = 1;
java_add_stmt (switch_expr);
x = build3 (CASE_LABEL_EXPR, void_type_node, NULL_TREE, NULL_TREE,
- create_artificial_label ());
+ create_artificial_label (input_location));
append_to_statement_list (x, &SWITCH_BODY (switch_expr));
x = build1 (GOTO_EXPR, void_type_node, lookup_label (default_pc));
value = build_int_cst (TREE_TYPE (switch_expr), match);
x = build3 (CASE_LABEL_EXPR, void_type_node, value, NULL_TREE,
- create_artificial_label ());
+ create_artificial_label (input_location));
append_to_statement_list (x, &SWITCH_BODY (switch_expr));
x = build1 (GOTO_EXPR, void_type_node, lookup_label (target_pc));
append_to_statement_list (x, &SWITCH_BODY (switch_expr));
}
-static tree
-pop_arguments (tree arg_types)
+static VEC(tree,gc) *
+pop_arguments (tree method_type)
{
- if (arg_types == end_params_node)
- return NULL_TREE;
- if (TREE_CODE (arg_types) == TREE_LIST)
+ function_args_iterator fnai;
+ tree type;
+ VEC(tree,gc) *args = NULL;
+ int arity;
+
+ FOREACH_FUNCTION_ARGS (method_type, type, fnai)
{
- tree tail = pop_arguments (TREE_CHAIN (arg_types));
- tree type = TREE_VALUE (arg_types);
- tree arg = pop_value (type);
+ /* XXX: leaky abstraction. */
+ if (type == void_type_node)
+ break;
+
+ VEC_safe_push (tree, gc, args, type);
+ }
+
+ arity = VEC_length (tree, args);
+
+ while (arity--)
+ {
+ tree arg = pop_value (VEC_index (tree, args, arity));
/* We simply cast each argument to its proper type. This is
needed since we lose type information coming out of the
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)
&& INTEGRAL_TYPE_P (type))
arg = convert (integer_type_node, arg);
- return tree_cons (NULL_TREE, arg, tail);
+
+ VEC_replace (tree, args, arity, arg);
}
- gcc_unreachable ();
+
+ return args;
}
/* Attach to PTR (a block) the declaration found in ENTRY. */
{
/* Build a declaration and mark it as a flag used to track
static class initializations. */
- decl = build_decl (VAR_DECL, NULL_TREE,
+ decl = build_decl (input_location, VAR_DECL, NULL_TREE,
boolean_type_node);
MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
DECL_CONTEXT (decl) = current_function_decl;
const char *new_classname;
const char *new_signature;
int flags;
- tree (*rewrite_arglist) (tree arglist);
+ void (*rewrite_arglist) (VEC(tree,gc) **);
} rewrite_rule;
/* Add __builtin_return_address(0) to the end of an arglist. */
-static tree
-rewrite_arglist_getcaller (tree arglist)
+static void
+rewrite_arglist_getcaller (VEC(tree,gc) **arglist)
{
tree retaddr
= build_call_expr (built_in_decls[BUILT_IN_RETURN_ADDRESS],
1, integer_zero_node);
DECL_UNINLINABLE (current_function_decl) = 1;
-
- return chainon (arglist,
- tree_cons (NULL_TREE, retaddr,
- NULL_TREE));
+
+ VEC_safe_push (tree, gc, *arglist, retaddr);
}
/* Add this.class to the end of an arglist. */
-static tree
-rewrite_arglist_getclass (tree arglist)
+static void
+rewrite_arglist_getclass (VEC(tree,gc) **arglist)
{
- return chainon (arglist,
- tree_cons (NULL_TREE, build_class_ref (output_class),
- NULL_TREE));
+ VEC_safe_push (tree, gc, *arglist, build_class_ref (output_class));
}
static rewrite_rule rules[] =
method, update SPECIAL.*/
void
-maybe_rewrite_invocation (tree *method_p, tree *arg_list_p,
+maybe_rewrite_invocation (tree *method_p, VEC(tree,gc) **arg_list_p,
tree *method_signature_p, tree *special)
{
tree context = DECL_NAME (TYPE_NAME (DECL_CONTEXT (*method_p)));
*method_p = maybe_method;
gcc_assert (*method_p);
if (p->rewrite_arglist)
- *arg_list_p = p->rewrite_arglist (*arg_list_p);
+ p->rewrite_arglist (arg_list_p);
*method_signature_p = get_identifier (p->new_signature);
*special = integer_one_node;
tree
build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED,
tree self_type, tree method_signature ATTRIBUTE_UNUSED,
- tree arg_list ATTRIBUTE_UNUSED, tree special)
+ VEC(tree,gc) *arg_list ATTRIBUTE_UNUSED, tree special)
{
tree func;
if (is_compiled_class (self_type))
}
tree
-invoke_build_dtable (int is_invoke_interface, tree arg_list)
+invoke_build_dtable (int is_invoke_interface, VEC(tree,gc) *arg_list)
{
tree dtable, objectref;
+ tree saved = save_expr (VEC_index (tree, arg_list, 0));
- TREE_VALUE (arg_list) = save_expr (TREE_VALUE (arg_list));
+ VEC_replace (tree, arg_list, 0, saved);
/* If we're dealing with interfaces and if the objectref
argument is an array then get the dispatch table of the class
Object rather than the one from the objectref. */
objectref = (is_invoke_interface
- && is_array_type_p (TREE_TYPE (TREE_VALUE (arg_list)))
- ? build_class_ref (object_type_node) : TREE_VALUE (arg_list));
+ && is_array_type_p (TREE_TYPE (saved))
+ ? build_class_ref (object_type_node) : saved);
if (dtable_ident == NULL_TREE)
dtable_ident = get_identifier ("vtable");
method_ref_index));
const char *const self_name
= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type)));
- tree call, func, method, arg_list, method_type;
+ tree call, func, method, method_type;
+ VEC(tree,gc) *arg_list;
tree check = NULL_TREE;
tree special = NULL_TREE;
just pop the arguments, push a properly-typed zero, and
continue. */
method_type = get_type_from_signature (method_signature);
- pop_arguments (TYPE_ARG_TYPES (method_type));
+ pop_arguments (method_type);
if (opcode != OPCODE_invokestatic)
pop_type (self_type);
method_type = promote_type (TREE_TYPE (method_type));
}
method_type = TREE_TYPE (method);
- arg_list = pop_arguments (TYPE_ARG_TYPES (method_type));
+ arg_list = pop_arguments (method_type);
flush_quick_stack ();
maybe_rewrite_invocation (&method, &arg_list, &method_signature,
We do omit the check if we're calling <init>. */
/* We use a SAVE_EXPR here to make sure we only evaluate
the new `self' expression once. */
- tree save_arg = save_expr (TREE_VALUE (arg_list));
- TREE_VALUE (arg_list) = save_arg;
+ tree save_arg = save_expr (VEC_index (tree, arg_list, 0));
+ VEC_replace (tree, arg_list, 0, save_arg);
check = java_check_reference (save_arg, ! DECL_INIT_P (method));
func = build_known_method_ref (method, method_type, self_type,
method_signature, arg_list, special);
else
func = build1 (NOP_EXPR, build_pointer_type (method_type), func);
- call = build_call_list (TREE_TYPE (method_type), func, arg_list);
+ call = build_call_vec (TREE_TYPE (method_type), func, arg_list);
TREE_SIDE_EFFECTS (call) = 1;
call = check_for_builtin (method, call);
tree
build_jni_stub (tree method)
{
- tree jnifunc, call, args, body, method_sig, arg_types;
+ tree jnifunc, call, body, method_sig, arg_types;
tree jniarg0, jniarg1, jniarg2, jniarg3;
tree jni_func_type, tem;
tree env_var, res_var = NULL_TREE, block;
- tree method_args, res_type;
+ tree method_args;
tree meth_var;
tree bind;
-
+ VEC(tree,gc) *args = NULL;
int args_size = 0;
tree klass = DECL_CONTEXT (method);
DECL_ARTIFICIAL (method) = 1;
DECL_EXTERNAL (method) = 0;
- env_var = build_decl (VAR_DECL, get_identifier ("env"), ptr_type_node);
+ env_var = build_decl (input_location,
+ VAR_DECL, get_identifier ("env"), ptr_type_node);
DECL_CONTEXT (env_var) = method;
if (TREE_TYPE (TREE_TYPE (method)) != void_type_node)
{
- res_var = build_decl (VAR_DECL, get_identifier ("res"),
+ res_var = build_decl (input_location, VAR_DECL, get_identifier ("res"),
TREE_TYPE (TREE_TYPE (method)));
DECL_CONTEXT (res_var) = method;
TREE_CHAIN (env_var) = res_var;
build_address_of (soft_getjnienvnewframe_node),
1, klass));
+ /* The JNIEnv structure is the first argument to the JNI function. */
+ args_size += int_size_in_bytes (TREE_TYPE (env_var));
+ VEC_safe_push (tree, gc, args, env_var);
+
+ /* For a static method the second argument is the class. For a
+ non-static method the second argument is `this'; that is already
+ available in the argument list. */
+ if (METHOD_STATIC (method))
+ {
+ args_size += int_size_in_bytes (TREE_TYPE (klass));
+ VEC_safe_push (tree, gc, args, klass);
+ }
+
/* All the arguments to this method become arguments to the
underlying JNI function. If we had to wrap object arguments in a
special way, we would do that here. */
- args = NULL_TREE;
for (tem = method_args; tem != NULL_TREE; tem = TREE_CHAIN (tem))
{
int arg_bits = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tem)));
#endif
args_size += (arg_bits / BITS_PER_UNIT);
- args = tree_cons (NULL_TREE, tem, args);
+ VEC_safe_push (tree, gc, args, tem);
}
- args = nreverse (args);
arg_types = TYPE_ARG_TYPES (TREE_TYPE (method));
- /* For a static method the second argument is the class. For a
- non-static method the second argument is `this'; that is already
- available in the argument list. */
+ /* Argument types for static methods and the JNIEnv structure.
+ FIXME: Write and use build_function_type_vec to avoid this. */
if (METHOD_STATIC (method))
- {
- args_size += int_size_in_bytes (TREE_TYPE (klass));
- args = tree_cons (NULL_TREE, klass, args);
- arg_types = tree_cons (NULL_TREE, object_ptr_type_node, arg_types);
- }
-
- /* The JNIEnv structure is the first argument to the JNI function. */
- args_size += int_size_in_bytes (TREE_TYPE (env_var));
- args = tree_cons (NULL_TREE, env_var, args);
+ arg_types = tree_cons (NULL_TREE, object_ptr_type_node, arg_types);
arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
/* We call _Jv_LookupJNIMethod to find the actual underlying
garbage-collected. If it is, we end up using canonical types
with different uids for equivalent function types, and this in
turn causes utf8 identifiers and output order to vary. */
- meth_var = build_decl (VAR_DECL, get_identifier ("meth"), jni_func_type);
+ meth_var = build_decl (input_location,
+ VAR_DECL, get_identifier ("meth"), jni_func_type);
TREE_STATIC (meth_var) = 1;
TREE_PUBLIC (meth_var) = 0;
DECL_EXTERNAL (meth_var) = 0;
/* Now we make the actual JNI call via the resulting function
pointer. */
- call = build_call_list (TREE_TYPE (TREE_TYPE (method)),
- jnifunc, args);
+ call = build_call_vec (TREE_TYPE (TREE_TYPE (method)), jnifunc, args);
/* If the JNI call returned a result, capture it here. If we had to
unwrap JNI object results, we would do that here. */
TREE_SIDE_EFFECTS (body) = 1;
/* Finally, do the return. */
- res_type = void_type_node;
if (res_var != NULL_TREE)
{
tree drt;
}
else
{
- tree temp = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (field_ref));
+ tree temp = build_decl (input_location,
+ VAR_DECL, NULL_TREE, TREE_TYPE (field_ref));
java_add_local_var (temp);
if (TREE_THIS_VOLATILE (field_decl))
{ \
int saw_index = 0; \
int index = OPERAND_VALUE; \
+ (void) saw_index; /* Avoid set but not used warning. */ \
build_java_ret \
(find_local_variable (index, return_address_type_node, oldpc)); \
}
tree
build_java_empty_stmt (void)
{
- tree t = build_empty_stmt ();
+ tree t = build_empty_stmt (input_location);
return t;
}
{
tree cpool;
tree d = build_constant_data_ref (flag_indirect_classes);
- tree cpool_ptr = build_decl (VAR_DECL, NULL_TREE,
+ tree cpool_ptr = build_decl (input_location, VAR_DECL, NULL_TREE,
build_pointer_type (TREE_TYPE (d)));
java_add_local_var (cpool_ptr);
TREE_CONSTANT (cpool_ptr) = 1;