aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@me.com>2013-08-23 15:10:36 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-08-29 10:20:13 +0200
commitb9308169341a9756c0047760c9a4d7e357b3bb0d (patch)
tree5316d887099b4bc664f441b3e1b98b4a85110f15
parentcba526a9581a7e0fac1b6ef183631574cc759ed5 (diff)
Generate code for conversion to signed int32.
Change-Id: I862a8c9c262b658859cc9b57ea0b6e9eb60e32e5 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
-rw-r--r--src/qml/compiler/qv4isel_masm.cpp90
-rw-r--r--src/qml/compiler/qv4isel_masm_p.h7
-rw-r--r--src/qml/compiler/qv4regalloc.cpp8
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp4
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h6
5 files changed, 94 insertions, 21 deletions
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp
index c520b9556f..92be0c183c 100644
--- a/src/qml/compiler/qv4isel_masm.cpp
+++ b/src/qml/compiler/qv4isel_masm.cpp
@@ -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);
diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/compiler/qv4isel_masm_p.h
index 283c6cb983..f89d469515 100644
--- a/src/qml/compiler/qv4isel_masm_p.h
+++ b/src/qml/compiler/qv4isel_masm_p.h
@@ -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)
{
diff --git a/src/qml/compiler/qv4regalloc.cpp b/src/qml/compiler/qv4regalloc.cpp
index 67f2234fab..f82a5fcf1c 100644
--- a/src/qml/compiler/qv4regalloc.cpp
+++ b/src/qml/compiler/qv4regalloc.cpp
@@ -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:
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index f91f8690f8..dadb1c7249 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -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);
}
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index af293a2df1..b38f833ad0 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -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)
{