From b9308169341a9756c0047760c9a4d7e357b3bb0d Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 23 Aug 2013 15:10:36 +0200 Subject: Generate code for conversion to signed int32. Change-Id: I862a8c9c262b658859cc9b57ea0b6e9eb60e32e5 Reviewed-by: Simon Hausmann --- src/qml/compiler/qv4isel_masm.cpp | 90 +++++++++++++++++++++++++++++++++++---- src/qml/compiler/qv4isel_masm_p.h | 7 ++- src/qml/compiler/qv4regalloc.cpp | 8 ++-- 3 files changed, 90 insertions(+), 15 deletions(-) (limited to 'src/qml/compiler') 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: -- cgit v1.2.3