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