From: Tom Tromey <tromey@redhat.com>
To: Java Patch List <java-patches@gcc.gnu.org>
Subject: [gcjx] Patch: FYI: code for 'enum' switches
Date: Mon, 12 Dec 2005 16:29:00 -0000 [thread overview]
Message-ID: <m3wtias2r6.fsf@localhost.localdomain> (raw)
I'm checking this in on the gcjx branch.
We weren't generating bytecode for an enum-typed switch.
This adds code generator support for this.
Tom
Index: ChangeLog
from Tom Tromey <tromey@redhat.com>
* model/memberref.cc (resolve_as_enum_constant): Resolve 'real'.
* bytecode/generate.hh (bytecode_generator::handle_enum_switch):
Declare.
* bytecode/generate.cc (handle_enum_switch): New method.
(visit_switch): Use it.
Index: model/memberref.cc
===================================================================
--- model/memberref.cc (revision 107914)
+++ model/memberref.cc (working copy)
@@ -27,6 +27,9 @@
const std::string &field_name)
{
std::set<model_field *> result;
+ // FIXME: it isn't enough here to look for a member. We must also
+ // verify that it is really an enum constant and not just some field
+ // with the right type.
klass->find_members (field_name, result, scope->get_current_class (), NULL);
if (result.empty ())
throw error ("no %<enum%> constant named %1 in %2")
@@ -40,6 +43,8 @@
rf->set_field (*(result.begin ()));
real = rf;
+ real->resolve (scope);
+
set_type (klass);
}
Index: bytecode/generate.cc
===================================================================
--- bytecode/generate.cc (revision 107975)
+++ bytecode/generate.cc (working copy)
@@ -967,12 +967,108 @@
}
void
+bytecode_generator::handle_enum_switch (model_switch *swstmt,
+ const ref_expression &expr,
+ const std::list<ref_switch_block> &blocks)
+{
+ assert (expr->type ()->reference_p ());
+
+ // Compute the expression. Note that we must throw a null pointer
+ // exception if it evaluates to 'null'.
+ {
+ push_expr_target push (this, ON_STACK);
+ emit_null_pointer_check (expr.get ());
+ }
+
+ model_type *sw_type = expr->type ();
+ model_switch_block *default_block = swstmt->get_default ();
+ bytecode_block *default_bytecode = NULL;
+
+ bytecode_block *done = new_bytecode_block ();
+ bytecode_block *next_one = NULL;
+
+ target_map[swstmt] = std::make_pair ((bytecode_block *) NULL, done);
+
+ for (std::list<ref_switch_block>::const_iterator i = blocks.begin ();
+ i != blocks.end ();
+ ++i)
+ {
+ // We generate:
+ //
+ // nextOne1:
+ // if (<expr> == <label1>) goto thisOne;
+ // if (<expr> == <label2>) goto thisOne;
+ // goto nextOne2;
+ // thisOne: body;
+
+ if (next_one != NULL)
+ define (next_one);
+ next_one = new_bytecode_block ();
+ bytecode_block *this_one = new_bytecode_block ();
+
+ std::list<ref_expression> labels = (*i)->get_labels ();
+ for (std::list<ref_expression>::const_iterator j = labels.begin ();
+ j != labels.end ();
+ ++j)
+ {
+ emit (op_dup);
+ increase_stack (sw_type);
+
+ {
+ push_expr_target push (this, ON_STACK);
+ (*j)->visit (this);
+ }
+
+ emit_relocation (if_acmpeq, this_one);
+ reduce_stack (sw_type);
+ reduce_stack (sw_type);
+ }
+ emit_relocation (reloc_goto, next_one);
+
+ define (this_one);
+ if (*i == default_block)
+ {
+ assert (! default_bytecode);
+ default_bytecode = this_one;
+ }
+ (*i)->visit (this);
+ // If the switch block falls through, we must go to the next
+ // block. Otherwise we don't need to do anything.
+ if ((*i)->can_complete_normally ())
+ emit_relocation (reloc_goto, next_one);
+ }
+
+ // Define the final 'next'.
+ if (next_one)
+ define (next_one);
+
+ // If there was a default block, emit a 'goto' to it.
+ if (default_block)
+ {
+ assert (default_bytecode);
+ emit_relocation (reloc_goto, default_bytecode);
+ }
+
+ // We're done. Be sure to pop the expression now.
+ define (done);
+ emit (op_pop);
+ reduce_stack (sw_type);
+}
+
+void
bytecode_generator::visit_switch (model_switch *swstmt,
const ref_expression &expr,
const std::list<ref_switch_block> &blocks)
{
note_line (swstmt);
+ // Enum-valued switches require different treatment.
+ if (expr->type ()->reference_p ())
+ {
+ handle_enum_switch (swstmt, expr, blocks);
+ return;
+ }
+
// Push a dummy finally handler that tells call_cleanups to exit
// early.
finally_handler dummy (swstmt);
Index: bytecode/generate.hh
===================================================================
--- bytecode/generate.hh (revision 107975)
+++ bytecode/generate.hh (working copy)
@@ -280,6 +280,8 @@
void emit_null_pointer_check (model_expression *);
void handle_block_statements (const std::list<ref_stmt> &);
+ void handle_enum_switch (model_switch *, const ref_expression &,
+ const std::list<ref_switch_block> &);
void binary_arith_operator (java_opcode,
const ref_expression &,
reply other threads:[~2005-12-12 16:29 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=m3wtias2r6.fsf@localhost.localdomain \
--to=tromey@redhat.com \
--cc=java-patches@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).