This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[gcjx] Patch: FYI: foreach
- From: Tom Tromey <tromey at redhat dot com>
- To: Java Patch List <java-patches at gcc dot gnu dot org>
- Date: 03 Apr 2005 18:48:52 -0600
- Subject: [gcjx] Patch: FYI: foreach
- Reply-to: tromey at redhat dot com
I'm checking this in on the gcjx branch.
This implements 'foreach' lowering for the tree back end.
Tom
Index: ChangeLog
from Tom Tromey <tromey@redhat.com>
* lower.cc (visit_bytecode_block): Use add_temporary.
* tree.hh (tree_generator::add_temporary): Declare.
* tree.cc (add_temporary): New method.
(visit_for_enhanced): Wrote.
Index: lower.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/lower.cc,v
retrieving revision 1.1.2.16
diff -u -r1.1.2.16 lower.cc
--- lower.cc 4 Apr 2005 00:49:19 -0000 1.1.2.16
+++ lower.cc 4 Apr 2005 00:49:40 -0000
@@ -92,22 +92,14 @@
{
char name[20];
sprintf (name, "stack%d", i);
- stack_slots[i] = build_decl (VAR_DECL, get_identifier (name),
- type_slot_union);
- DECL_CONTEXT (stack_slots[i]) = current_block;
- TREE_CHAIN (stack_slots[i]) = BLOCK_VARS (current_block);
- BLOCK_VARS (current_block) = stack_slots[i];
+ stack_slots[i] = add_temporary (get_identifier (name), type_slot_union);
}
local_slots = new tree[max_locals];
for (int i = 0; i < max_locals; ++i)
{
char name[20];
sprintf (name, "local%d", i);
- local_slots[i] = build_decl (VAR_DECL, get_identifier (name),
- type_slot_union);
- DECL_CONTEXT (local_slots[i]) = current_block;
- TREE_CHAIN (local_slots[i]) = BLOCK_VARS (current_block);
- BLOCK_VARS (current_block) = local_slots[i];
+ local_slots[i] = add_temporary (get_identifier (name), type_slot_union);
}
model_unit_class *unit
@@ -588,10 +580,8 @@
tree expr1 = find_slot (stack_top - 1, stack_types[stack_top - 1]);
tree expr2 = find_slot (stack_top - 2, stack_types[stack_top - 2]);
- tree temp = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (expr1));
- DECL_CONTEXT (temp) = current_block;
- TREE_CHAIN (temp) = BLOCK_VARS (current_block);
- BLOCK_VARS (current_block) = temp;
+ tree temp = add_temporary (gcc_builtins->get_symbol (),
+ TREE_TYPE (expr1));
tree decl1 = find_slot (stack_top - 2, TREE_TYPE (expr1));
tree decl2 = find_slot (stack_top - 1, TREE_TYPE (expr2));
Index: tree.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/tree.cc,v
retrieving revision 1.1.2.39
diff -u -r1.1.2.39 tree.cc
--- tree.cc 4 Apr 2005 00:47:21 -0000 1.1.2.39
+++ tree.cc 4 Apr 2005 00:49:40 -0000
@@ -85,6 +85,16 @@
return var;
}
+tree
+tree_generator::add_temporary (tree name, tree type)
+{
+ tree var = build_decl (VAR_DECL, name, type);
+ DECL_CONTEXT (var) = method_tree;
+ TREE_CHAIN (var) = BLOCK_VARS (current_block);
+ BLOCK_VARS (current_block) = var;
+ return var;
+}
+
void
tree_generator::emit_type_assertion (model_type *to_type,
model_type *from_type)
@@ -583,19 +593,156 @@
DECL_CONTEXT (done_tree) = current_block;
target_map[fstmt] = std::make_pair (update_tree, done_tree);
+ // Push a new block around the loop.
+ save_tree saver (current_block, make_node (BLOCK));
+ BLOCK_SUPERCONTEXT (current_block) = saver.get ();
+
tree body_tree = alloc_stmt_list ();
tree_stmt_iterator out = tsi_start (body_tree);
+ // Generate code to find the container.
+ container->visit (this);
+ tree container_tree = save_expr (current);
+ tree container_ptr_type = TREE_TYPE (current);
+
+ model_type *ctype = container->type ();
+ gcc_builtins->lay_out_class (assert_cast<model_class *> (ctype));
+
+ // The user's variable.
+ tree var_decl = add_var (var);
+
+ tree exit_expr, update_expr, assign_rhs;
+
if (container->type ()->array_p ())
{
+ // Make some temporaries: one to hold the index and one to hold
+ // the length of the array.
+ tree index_tree = add_temporary (gcc_builtins->get_symbol (), type_jint);
+ tree len_tree = add_temporary (gcc_builtins->get_symbol (), type_jint);
+
+ tree container_type = TREE_TYPE (container_ptr_type);
+ tree lenfield = gcc_builtins->find_decl (container_type, "length");
+ tree datafield = gcc_builtins->find_decl (container_type, "data");
+
+ // Compute and save the length of the array.
+ tree get_len
+ = build3 (COMPONENT_REF, type_jint,
+ build1 (INDIRECT_REF, container_type,
+ // FIXME: there is probably a more optimal
+ // approach here.
+ gcc_builtins->check_reference (container_tree)),
+ lenfield, NULL_TREE);
+ get_len = build2 (MODIFY_EXPR, type_jint, len_tree, get_len);
+ TREE_SIDE_EFFECTS (get_len) = 1;
+ tsi_link_after (&out, get_len, TSI_CONTINUE_LINKING);
+
+ // Initialize the index.
+ tree init = build2 (MODIFY_EXPR, type_jint, index_tree,
+ fold (convert (type_jint, integer_zero_node)));
+ TREE_SIDE_EFFECTS (init) = 1;
+ tsi_link_after (&out, init, TSI_CONTINUE_LINKING);
+
+ // Code for the exit expression.
+ exit_expr = build2 (EQ_EXPR, type_jboolean, index_tree, len_tree);
+
+ // Code for the update expression.
+ update_expr = build2 (PREINCREMENT_EXPR, type_jint, index_tree,
+ fold (convert (type_jint, integer_one_node)));
+ TREE_SIDE_EFFECTS (update_expr) = 1;
+
+ // Code to compute the new user variable value.
+ assign_rhs = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (datafield)),
+ build3 (COMPONENT_REF, TREE_TYPE (datafield),
+ build1 (INDIRECT_REF, container_type,
+ container_tree),
+ datafield, NULL_TREE),
+ index_tree, NULL_TREE, NULL_TREE);
}
else
{
// Use an iterator.
- }
- tsi_link_after (&out, done_tree, TSI_CONTINUE_LINKING);
- current = body_tree;
+ model_class *iterator_type
+ = global->get_compiler ()->java_util_Iterator ();
+ model_class *object_type
+ = global->get_compiler ()->java_lang_Object ();
+ model_class *iterable_type
+ = global->get_compiler ()->java_lang_Iterable ();
+
+ model_method *iter_meth = find_method ("iterator", iterable_type, NULL,
+ iterator_type, fstmt);
+ model_method *has_next_meth = find_method ("hasNext", iterator_type,
+ NULL, primitive_boolean_type,
+ fstmt);
+ model_method *next_meth = find_method ("next", iterator_type, NULL,
+ object_type, fstmt);
+
+ // Introduce a new variable that holds the iterator.
+ tree iter_tree = add_temporary (gcc_builtins->get_symbol (),
+ gcc_builtins->map_type (iterator_type));
+
+ // Initialize the iterator and link it in.
+ tree init = build2 (MODIFY_EXPR, TREE_TYPE (iter_tree),
+ iter_tree,
+ gcc_builtins->map_method_call (class_wrapper,
+ container_tree,
+ NULL_TREE, iter_meth,
+ false));
+ TREE_SIDE_EFFECTS (init) = 1;
+ tsi_link_after (&out, init, TSI_CONTINUE_LINKING);
+
+ // Compute the exit expression.
+ exit_expr = build1 (TRUTH_NOT_EXPR, type_jboolean,
+ gcc_builtins->map_method_call (class_wrapper,
+ iter_tree, NULL_TREE,
+ has_next_meth,
+ false));
+ TREE_SIDE_EFFECTS (exit_expr) = 1;
+
+ // Code for the update expression.
+ assign_rhs = gcc_builtins->map_method_call (class_wrapper,
+ iter_tree, NULL_TREE,
+ next_meth, false);
+ TREE_SIDE_EFFECTS (assign_rhs) = 1;
+
+ // We don't need a different update expression.
+ update_expr = build_empty_stmt ();
+ }
+
+ // We've already linked in the initialization code. Now start the
+ // loop body.
+ tree loop_tree = alloc_stmt_list ();
+ tree_stmt_iterator loop_out = tsi_start (loop_tree);
+
+ // Link in the exit expression.
+ tsi_link_after (&loop_out, build1 (EXIT_EXPR, void_type_node, exit_expr),
+ TSI_CONTINUE_LINKING);
+ // Link in the user variable assignment.
+ tree user_assign = build2 (MODIFY_EXPR, TREE_TYPE (var_decl),
+ var_decl,
+ convert (TREE_TYPE (var_decl), assign_rhs));
+ TREE_SIDE_EFFECTS (user_assign) = 1;
+ tsi_link_after (&loop_out, user_assign, TSI_CONTINUE_LINKING);
+
+ // Compute and link in the body of the loop.
+ body->visit (this);
+ tsi_link_after (&loop_out, current, TSI_CONTINUE_LINKING);
+
+ // Link in the update label and the update expression.
+ tsi_link_after (&loop_out, wrap_label (update_tree, fstmt),
+ TSI_CONTINUE_LINKING);
+ tsi_link_after (&loop_out, update_expr, TSI_CONTINUE_LINKING);
+
+ // Wrap up the loop body and link it into the outer statement list.
+ tree loop_contents = build1 (LOOP_EXPR, void_type_node, loop_tree);
+ TREE_SIDE_EFFECTS (loop_contents) = 1;
+ annotate (loop_contents, fstmt);
+ tsi_link_after (&out, loop_contents, TSI_CONTINUE_LINKING);
+
+ tsi_link_after (&out, wrap_label (done_tree, fstmt), TSI_CONTINUE_LINKING);
+
+ current = build3 (BIND_EXPR, void_type_node, BLOCK_VARS (current_block),
+ body_tree, current_block);
}
void
Index: tree.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/tree.hh,v
retrieving revision 1.1.2.11
diff -u -r1.1.2.11 tree.hh
--- tree.hh 4 Apr 2005 00:49:19 -0000 1.1.2.11
+++ tree.hh 4 Apr 2005 00:49:40 -0000
@@ -104,6 +104,7 @@
tree wrap_synchronized (tree, tree);
tree wrap_label (tree, model_element *);
tree add_var (const ref_variable_decl &);
+ tree add_temporary (tree, tree);
tree build_class_ref (model_type *, model_element *);
tree build_class_ref (const std::string &);
tree handle_instanceof (tree, tree);