Fix the bit shift and complement operators
authorLars Knoll <lars.knoll@digia.com>
Wed, 12 Dec 2012 20:33:17 +0000 (21:33 +0100)
committerSimon Hausmann <simon.hausmann@digia.com>
Wed, 12 Dec 2012 23:07:24 +0000 (00:07 +0100)
Take care of some corner cases and make them pass the
test suite.

Change-Id: Ic83508859800c62681ee873968b475ef81fffb82
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
qmljs_runtime.h
qv4codegen.cpp

index 263c151..aa2bc4e 100644 (file)
@@ -472,9 +472,9 @@ inline Value __qmljs_compl(Value value, ExecutionContext *ctx)
 
     int n;
     if (value.isConvertibleToInt())
-        n = ~value.int_32;
+        n = value.int_32;
     else
-        n = Value::toInteger(__qmljs_to_number(value, ctx));
+        n = Value::toInt32(__qmljs_to_number(value, ctx));
 
     return Value::fromInt32(~n);
 }
@@ -588,8 +588,6 @@ inline Value __qmljs_mod(Value left, Value right, ExecutionContext *ctx)
     return Value::fromDouble(fmod(lval, rval));
 }
 
-// ### unsigned shl missing?
-
 inline Value __qmljs_shl(Value left, Value right, ExecutionContext *ctx)
 {
     TRACE2(left, right);
@@ -618,12 +616,18 @@ inline Value __qmljs_ushr(Value left, Value right, ExecutionContext *ctx)
 {
     TRACE2(left, right);
 
-    if (Value::integerCompatible(left, right))
-        return Value::fromInt32(uint(left.integerValue()) >> ((uint(right.integerValue()) & 0x1f)));
+    uint result;
+    if (Value::integerCompatible(left, right)) {
+        result = uint(left.integerValue()) >> (uint(right.integerValue()) & 0x1f);
+    } else {
+        unsigned lval = Value::toUInt32(__qmljs_to_number(left, ctx));
+        unsigned rval = Value::toUInt32(__qmljs_to_number(right, ctx)) & 0x1f;
+        result = lval >> rval;
+    }
 
-    unsigned lval = Value::toUInt32(__qmljs_to_number(left, ctx));
-    unsigned rval = Value::toUInt32(__qmljs_to_number(right, ctx)) & 0x1f;
-    return Value::fromInt32(lval >> rval);
+    if (result > INT_MAX)
+        return Value::fromDouble(result);
+    return Value::fromInt32(result);
 }
 
 inline Value __qmljs_gt(Value left, Value right, ExecutionContext *ctx)
index fef6b4e..7409a54 100644 (file)
@@ -553,13 +553,13 @@ IR::Expr *Codegen::binop(IR::AluOp op, IR::Expr *left, IR::Expr *right)
                 case IR::OpGt: return _block->CONST(IR::BoolType, c1->value > c2->value);
                 case IR::OpLe: return _block->CONST(IR::BoolType, c1->value <= c2->value);
                 case IR::OpLt: return _block->CONST(IR::BoolType, c1->value < c2->value);
-                case IR::OpLShift: return _block->CONST(IR::NumberType, int(c1->value) << int(c2->value));
+                case IR::OpLShift: return _block->CONST(IR::NumberType, VM::Value::toInt32(c1->value) << (VM::Value::toUInt32(c2->value) & 0x1f));
                 case IR::OpMod: return _block->CONST(IR::NumberType, ::fmod(c1->value, c2->value));
                 case IR::OpMul: return _block->CONST(IR::NumberType, c1->value * c2->value);
                 case IR::OpOr: return _block->CONST(IR::NumberType, c1->value ? c1->value : c2->value);
-                case IR::OpRShift: return _block->CONST(IR::NumberType, int(c1->value) >> int(c2->value));
+                case IR::OpRShift: return _block->CONST(IR::NumberType, VM::Value::toInt32(c1->value) << (VM::Value::toUInt32(c2->value) & 0x1f));
                 case IR::OpSub: return _block->CONST(IR::NumberType, c1->value - c2->value);
-                case IR::OpURShift: return _block->CONST(IR::NumberType, unsigned(c1->value) >> int(c2->value));
+                case IR::OpURShift: return _block->CONST(IR::NumberType,VM::Value::toUInt32(c1->value) << (VM::Value::toUInt32(c2->value) & 0x1f));
 
                 case IR::OpInstanceof:
                 case IR::OpIn: