diff options
author | Erik Verbruggen <erik.verbruggen@me.com> | 2013-08-23 15:10:36 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-08-29 10:20:13 +0200 |
commit | b9308169341a9756c0047760c9a4d7e357b3bb0d (patch) | |
tree | 5316d887099b4bc664f441b3e1b98b4a85110f15 | |
parent | cba526a9581a7e0fac1b6ef183631574cc759ed5 (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.cpp | 90 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_masm_p.h | 7 | ||||
-rw-r--r-- | src/qml/compiler/qv4regalloc.cpp | 8 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime_p.h | 6 |
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) { |