Generate code for conversion to signed int32.
authorErik Verbruggen <erik.verbruggen@me.com>
Fri, 23 Aug 2013 13:10:36 +0000 (15:10 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Thu, 29 Aug 2013 08:20:13 +0000 (10:20 +0200)
Change-Id: I862a8c9c262b658859cc9b57ea0b6e9eb60e32e5
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/qml/compiler/qv4isel_masm.cpp
src/qml/compiler/qv4isel_masm_p.h
src/qml/compiler/qv4regalloc.cpp
src/qml/jsruntime/qv4runtime.cpp
src/qml/jsruntime/qv4runtime_p.h

index c520b95..92be0c1 100644 (file)
@@ -1359,23 +1359,29 @@ void InstructionSelection::callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4
 
 void InstructionSelection::convertType(V4IR::Temp *source, V4IR::Temp *target)
 {
-    if (target->type == V4IR::DoubleType)
+    switch (target->type) {
+    case V4IR::DoubleType:
         convertTypeToDouble(source, target);
-    else if (target->type == V4IR::BoolType)
+        break;
+    case V4IR::BoolType:
         convertTypeToBool(source, target);
-    else
+        break;
+    case V4IR::SInt32Type:
+        convertTypeToSInt32(source, target);
+        break;
+    default:
         convertTypeSlowPath(source, target);
+        break;
+    }
 }
 
 void InstructionSelection::convertTypeSlowPath(V4IR::Temp *source, V4IR::Temp *target)
 {
+    Q_ASSERT(target->type != V4IR::BoolType);
+
     if (target->type & V4IR::NumberType)
         unop(V4IR::OpUPlus, source, target);
-    else if (target->type == V4IR::BoolType) {
-        generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_to_boolean,
-                             Assembler::PointerToValue(source));
-        _as->storeBool(Assembler::ReturnValueRegister, target);
-    } else
+    else
         copyValue(source, target);
 }
 
@@ -1478,6 +1484,74 @@ void InstructionSelection::convertTypeToBool(V4IR::Temp *source, V4IR::Temp *tar
     }
 }
 
+void InstructionSelection::convertTypeToSInt32(V4IR::Temp *source, V4IR::Temp *target)
+{
+    switch (source->type) {
+    case V4IR::ObjectType: {
+        // load the tag:
+        Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+        tagAddr.offset += 4;
+        _as->load32(tagAddr, Assembler::ScratchRegister);
+
+        // check if it's an int32:
+        Assembler::Jump isNoInt = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
+                                                Assembler::TrustedImm32(Value::_Integer_Type));
+        Assembler::Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+        if (target->kind == V4IR::Temp::StackSlot) {
+            _as->load32(addr, Assembler::ScratchRegister);
+            Assembler::Pointer targetAddr = _as->stackSlotPointer(target);
+            _as->store32(Assembler::ScratchRegister, targetAddr);
+            targetAddr.offset += 4;
+            _as->store32(Assembler::TrustedImm32(Value::_Integer_Type), targetAddr);
+        } else {
+            _as->load32(addr, (Assembler::RegisterID) target->index);
+        }
+        Assembler::Jump intDone = _as->jump();
+
+        // not an int:
+        isNoInt.link(_as);
+        generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_int32,
+                             _as->loadTempAddress(Assembler::ScratchRegister, source));
+        _as->storeInt32(Assembler::ReturnValueRegister, target);
+
+        intDone.link(_as);
+    } break;
+    case V4IR::DoubleType: {
+        Assembler::FPRegisterID reg = _as->toDoubleRegister(source);
+        Assembler::Jump success =
+                _as->branchTruncateDoubleToInt32(reg, Assembler::ReturnValueRegister,
+                                                 Assembler::BranchIfTruncateSuccessful);
+        generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_double_to_int32,
+                             Assembler::PointerToValue(source));
+        success.link(_as);
+        _as->storeInt32(Assembler::ReturnValueRegister, target);
+    } break;
+    case V4IR::UInt32Type: {
+        Assembler::RegisterID reg = _as->toUInt32Register(source, Assembler::ReturnValueRegister);
+        Assembler::Jump easy = _as->branch32(Assembler::GreaterThanOrEqual, reg, Assembler::TrustedImm32(0));
+        generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_int32,
+                             Assembler::PointerToValue(source));
+        easy.link(_as);
+        _as->storeInt32(Assembler::ReturnValueRegister, target);
+    } break;
+    case V4IR::NullType:
+    case V4IR::UndefinedType:
+        _as->move(Assembler::TrustedImm32(0), Assembler::ReturnValueRegister);
+        _as->storeInt32(Assembler::ReturnValueRegister, target);
+        break;
+    case V4IR::StringType:
+        generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_int32,
+                             _as->loadTempAddress(Assembler::ScratchRegister, source));
+        _as->storeInt32(Assembler::ReturnValueRegister, target);
+        break;
+    case V4IR::BoolType:
+        _as->storeInt32(_as->toInt32Register(source, Assembler::ReturnValueRegister), target);
+        break;
+    default:
+        break;
+    } // switch (source->type)
+}
+
 void InstructionSelection::constructActivationProperty(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result)
 {
     assert(func != 0);
index 283c6cb..f89d469 100644 (file)
@@ -1028,11 +1028,9 @@ public:
     {
         if (target->kind == V4IR::Temp::PhysicalRegister) {
             move(reg, (RegisterID) target->index);
-        } else if (target->kind == V4IR::Temp::StackSlot) {
-            Pointer addr = stackSlotPointer(target);
-            storeInt32(reg, addr);
         } else {
-            Q_UNIMPLEMENTED();
+            Pointer addr = loadTempAddress(ScratchRegister, target);
+            storeInt32(reg, addr);
         }
     }
 
@@ -1241,6 +1239,7 @@ private:
     void convertTypeSlowPath(V4IR::Temp *source, V4IR::Temp *target);
     void convertTypeToDouble(V4IR::Temp *source, V4IR::Temp *target);
     void convertTypeToBool(V4IR::Temp *source, V4IR::Temp *target);
+    void convertTypeToSInt32(V4IR::Temp *source, V4IR::Temp *target);
 
     void convertIntToDouble(V4IR::Temp *source, V4IR::Temp *target)
     {
index 67f2234..f82a5fc 100644 (file)
@@ -234,13 +234,11 @@ protected: // IRDecoder
 
     virtual void convertType(V4IR::Temp *source, V4IR::Temp *target)
     {
-        // TODO: do not generate a call (meaning: block all registers), but annotate the conversion with registers that need to be saved and have masm take care of that.
         addDef(target);
 
         bool needsCall = true;
         Use::RegisterFlag sourceReg = Use::CouldHaveRegister;
 
-        // TODO: verify this method
         switch (target->type) {
         case DoubleType:
             if (source->type == UInt32Type) {
@@ -248,8 +246,12 @@ protected: // IRDecoder
                 needsCall = false;
                 break;
             }
-#if 0 // TODO: change masm to generate code
         case SInt32Type:
+            if (source->type == DoubleType || source->type == UInt32Type) {
+                // this might need a call
+                break;
+            }
+#if 0 // TODO: change masm to generate code
         case UInt32Type:
 #endif
         case BoolType:
index f91f869..dadb1c7 100644 (file)
@@ -1242,7 +1242,7 @@ int __qmljs_value_to_int32(const Value &value)
     return value.toInt32();
 }
 
-int __qmljs_double_to_int32(double d)
+int __qmljs_double_to_int32(const double &d)
 {
     return Value::toInt32(d);
 }
@@ -1252,7 +1252,7 @@ unsigned __qmljs_value_to_uint32(const Value &value)
     return value.toUInt32();
 }
 
-unsigned __qmljs_double_to_uint32(double d)
+unsigned __qmljs_double_to_uint32(const double &d)
 {
     return Value::toUInt32(d);
 }
index af293a2..b38f833 100644 (file)
@@ -180,9 +180,9 @@ void __qmljs_decrement(QV4::Value *result, const QV4::Value &value);
 
 Q_QML_EXPORT void __qmljs_value_to_double(double *result, const Value &value);
 Q_QML_EXPORT int __qmljs_value_to_int32(const Value &value);
-Q_QML_EXPORT int __qmljs_double_to_int32(double d);
+Q_QML_EXPORT int __qmljs_double_to_int32(const double &d);
 Q_QML_EXPORT unsigned __qmljs_value_to_uint32(const Value &value);
-Q_QML_EXPORT unsigned __qmljs_double_to_uint32(double d);
+Q_QML_EXPORT unsigned __qmljs_double_to_uint32(const double &d);
 
 void __qmljs_delete_subscript(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &base, const QV4::Value &index);
 void __qmljs_delete_member(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &base, QV4::String *name);
@@ -304,9 +304,7 @@ inline double __qmljs_to_number(const QV4::Value &value)
 }
 
 Q_QML_EXPORT int __qmljs_value_to_int32(const QV4::Value &value);
-Q_QML_EXPORT int __qmljs_double_to_int32(double);
 Q_QML_EXPORT unsigned __qmljs_value_to_uint32(const QV4::Value &value);
-Q_QML_EXPORT unsigned __qmljs_double_to_uint32(double);
 
 inline QV4::Value __qmljs_to_string(const QV4::Value &value, QV4::ExecutionContext *ctx)
 {