The result of i2c, i2b and i2s should be J_INT.
As stated in the JVM specification for i2b instruction:
"The value on the top of the operand stack must be of type int. It is
popped from the operand stack, truncated to a byte, then sign-extended
to an int result. That result is pushed onto the operand stack."

The simmilar applies to i2c and i2s.

Signed-off-by: Tomek Grabiec <tgrab...@gmail.com>
---
 arch/x86/insn-selector.brg         |   45 +++++++++++++++++++++++------------
 include/jit/expression.h           |    9 +++++++
 jit/expression.c                   |   20 +++++++++++++++-
 jit/typeconv-bc.c                  |   22 +++++++++++++++--
 regression/jvm/ConversionTest.java |   15 ++++++++++++
 5 files changed, 91 insertions(+), 20 deletions(-)

diff --git a/arch/x86/insn-selector.brg b/arch/x86/insn-selector.brg
index edea89c..50ec45f 100644
--- a/arch/x86/insn-selector.brg
+++ b/arch/x86/insn-selector.brg
@@ -1404,23 +1404,14 @@ reg:    EXPR_INSTANCEOF(reg)
        select_exception_test(s, tree);
 }
 
-reg:   EXPR_CONVERSION(reg)
+reg:   EXPR_TRUNCATION(reg)
 {
        struct expression *expr, *src;
 
        expr = to_expr(tree);
-       src = to_expr(expr->from_expression);
+       src  = to_expr(expr->from_expression);
 
-       if (src->vm_type == J_INT && expr->vm_type == J_LONG) {
-               state->reg1 = get_var(s->b_parent, J_INT);
-               state->reg2 = get_var(s->b_parent, J_INT);
-
-               select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, 
state->left->reg1, state->reg1));
-               select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, 
state->left->reg1, state->reg2));
-               select_insn(s, tree, imm_reg_insn(INSN_SAR_IMM_REG, 0x1f, 
state->reg2));
-       } else if (src->vm_type == J_LONG && expr->vm_type == J_INT) {
-               state->reg1 = state->left->reg1;
-       } else if (src->vm_type == J_INT && expr->vm_type == J_BYTE) {
+       if (expr->to_type == J_BYTE) {
                struct var_info *tmp;
 
                /*
@@ -1431,14 +1422,36 @@ reg:    EXPR_CONVERSION(reg)
                state->reg1 = state->left->reg1;
                select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, 
state->left->reg1, tmp));
                select_insn(s, tree, reg_reg_insn(INSN_MOVSX_8_REG_REG, tmp, 
state->left->reg1));
-       } else if (src->vm_type == J_INT && expr->vm_type == J_CHAR) {
-               state->reg1 = get_var(s->b_parent, J_INT);
 
-               select_insn(s, tree, reg_reg_insn(INSN_MOVZX_16_REG_REG, 
state->left->reg1, state->reg1));
-       } else if (src->vm_type == J_INT && expr->vm_type == J_SHORT) {
+       } else if (expr->to_type == J_CHAR) {
                state->reg1 = get_var(s->b_parent, J_INT);
+               select_insn(s, tree, reg_reg_insn(INSN_MOVZX_16_REG_REG, 
state->left->reg1, state->reg1));
 
+       } else if (expr->to_type == J_SHORT) {
+               state->reg1 = get_var(s->b_parent, J_INT);
                select_insn(s, tree, reg_reg_insn(INSN_MOVSX_16_REG_REG, 
state->left->reg1, state->reg1));
+
+       } else {
+               die("EXPR_TRUNCATION: invalid conversion from int to %d", 
expr->to_type);
+       }
+}
+
+reg:   EXPR_CONVERSION(reg)
+{
+       struct expression *expr, *src;
+
+       expr = to_expr(tree);
+       src = to_expr(expr->from_expression);
+
+       if (src->vm_type == J_INT && expr->vm_type == J_LONG) {
+               state->reg1 = get_var(s->b_parent, J_INT);
+               state->reg2 = get_var(s->b_parent, J_INT);
+
+               select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, 
state->left->reg1, state->reg1));
+               select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, 
state->left->reg1, state->reg2));
+               select_insn(s, tree, imm_reg_insn(INSN_SAR_IMM_REG, 0x1f, 
state->reg2));
+       } else if (src->vm_type == J_LONG && expr->vm_type == J_INT) {
+               state->reg1 = state->left->reg1;
        } else if (src->vm_type == J_BYTE && expr->vm_type == J_CHAR) {
                state->reg1 = state->left->reg1;
        } else {
diff --git a/include/jit/expression.h b/include/jit/expression.h
index fcb3379..e1cfbfa 100644
--- a/include/jit/expression.h
+++ b/include/jit/expression.h
@@ -57,6 +57,7 @@ enum expression_type {
        EXPR_MULTIARRAY_SIZE_CHECK,
        EXPR_MIMIC_STACK_SLOT,
        EXPR_LOOKUPSWITCH_BSEARCH,
+       EXPR_TRUNCATION,
        EXPR_LAST,      /* Not a real type. Keep this last. */
 };
 
@@ -289,6 +290,13 @@ struct expression {
                        struct tree_node *key;
                        struct lookupswitch *lookupswitch_table;
                };
+
+               /* EXPR_TRUNCATION represents conversion from J_INT to
+                * J_CHAR, J_BYTE or J_SHORT. */
+               struct {
+                       struct tree_node *from_expression;
+                       enum vm_type to_type;
+               };
        };
 };
 
@@ -365,6 +373,7 @@ struct expression *multiarray_size_check_expr(struct 
expression *);
 struct expression *dup_expr(struct parse_context *, struct expression *);
 struct expression *get_pure_expr(struct parse_context *, struct expression *);
 struct expression *lookupswitch_bsearch_expr(struct expression *, struct 
lookupswitch *);
+struct expression *truncation_expr(enum vm_type, struct expression *);
 unsigned long nr_args(struct expression *);
 int expr_nr_kids(struct expression *);
 int expr_is_pure(struct expression *);
diff --git a/jit/expression.c b/jit/expression.c
index a7247e4..ff80c1f 100644
--- a/jit/expression.c
+++ b/jit/expression.c
@@ -13,6 +13,7 @@
 #include "vm/method.h"
 #include "vm/object.h"
 #include "vm/die.h"
+#include "vm/stack-trace.h"
 
 #include <stdlib.h>
 #include <string.h>
@@ -41,6 +42,7 @@ int expr_nr_kids(struct expression *expr)
        case EXPR_ARGS_LIST:
                return 2;
        case EXPR_UNARY_OP:
+       case EXPR_TRUNCATION:
        case EXPR_CONVERSION:
        case EXPR_CONVERSION_FLOAT_TO_DOUBLE:
        case EXPR_CONVERSION_DOUBLE_TO_FLOAT:
@@ -103,6 +105,7 @@ int expr_is_pure(struct expression *expr)
                 */
        case EXPR_ARGS_LIST:
        case EXPR_UNARY_OP:
+       case EXPR_TRUNCATION:
        case EXPR_CONVERSION:
        case EXPR_CONVERSION_FLOAT_TO_DOUBLE:
        case EXPR_CONVERSION_DOUBLE_TO_FLOAT:
@@ -201,7 +204,7 @@ struct expression *expr_get(struct expression *expr)
 
        return expr;
 }
-extern void print_trace(void);
+
 void expr_put(struct expression *expr)
 {
        if (!(expr->refcount > 0))
@@ -636,3 +639,18 @@ struct expression *lookupswitch_bsearch_expr(struct 
expression *key, struct look
 
        return expr;
 }
+
+struct expression *truncation_expr(enum vm_type to_type,
+                                  struct expression *from_expression)
+{
+       struct expression *expr;
+
+       expr = alloc_expression(EXPR_TRUNCATION, J_INT);
+       if (!expr)
+               return NULL;
+
+       expr->from_expression = &from_expression->node;
+       expr->to_type = to_type;
+
+       return expr;
+}
diff --git a/jit/typeconv-bc.c b/jit/typeconv-bc.c
index 3a3b0e7..fbac2a1 100644
--- a/jit/typeconv-bc.c
+++ b/jit/typeconv-bc.c
@@ -48,6 +48,22 @@ static int convert_conversion(struct parse_context *ctx, 
enum vm_type to_type)
        return 0;
 }
 
+static int convert_truncation(struct parse_context *ctx, enum vm_type to_type)
+{
+       struct expression *from_expression, *expr;
+
+       from_expression = stack_pop(ctx->bb->mimic_stack);
+       assert(from_expression->vm_type == J_INT);
+
+       expr = truncation_expr(to_type, from_expression);
+       if (!expr)
+               return warn("out of memory"), -ENOMEM;
+
+       convert_expression(ctx, expr);
+       return 0;
+}
+
+
 int convert_i2l(struct parse_context *ctx)
 {
        return convert_conversion(ctx, J_LONG);
@@ -110,15 +126,15 @@ int convert_d2f(struct parse_context *ctx)
 
 int convert_i2b(struct parse_context *ctx)
 {
-       return convert_conversion(ctx, J_BYTE);
+       return convert_truncation(ctx, J_BYTE);
 }
 
 int convert_i2c(struct parse_context *ctx)
 {
-       return convert_conversion(ctx, J_CHAR);
+       return convert_truncation(ctx, J_CHAR);
 }
 
 int convert_i2s(struct parse_context *ctx)
 {
-       return convert_conversion(ctx, J_SHORT);
+       return convert_truncation(ctx, J_SHORT);
 }
diff --git a/regression/jvm/ConversionTest.java 
b/regression/jvm/ConversionTest.java
index 93b2a95..a6b7c09 100644
--- a/regression/jvm/ConversionTest.java
+++ b/regression/jvm/ConversionTest.java
@@ -97,6 +97,20 @@ public class ConversionTest extends TestCase {
         assertEquals((char) 0xffc0, b2c((byte) -0x40));
     }
 
+    public static void testConversionFromIntPushesInt() {
+        char c1, c2;
+        int i = 1;
+
+        // conversion from int to byte should push int onto mimic stack
+        // so the following expression should not trigger byte -> char
+        // and short -> char conversion.
+        c1 = (char) (byte) i;
+        c2 = (char) (short) i;
+
+        takeInt(c1);
+        takeInt(c2);
+    }
+
     public static void main(String[] args) {
         testLongToIntegerConversion();
         testIntegerToLongConversion();
@@ -104,5 +118,6 @@ public class ConversionTest extends TestCase {
         testIntegerToCharConversion();
         testIntegerToShortConversion();
         testByteToCharConversion();
+        testConversionFromIntPushesInt();
     }
 }
-- 
1.6.0.6


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to