diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2018-06-05 13:06:54 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2018-06-21 15:05:57 +0000 |
commit | 75306a2f438e1d2b3969a7a3b7ffd8e39b84cd11 (patch) | |
tree | 30e5f2e2ea27c0e7bc6bb22f385b7bca7ba8f9ef | |
parent | cb9537d83046dfbfdbe4977999b606fed879d2d7 (diff) |
Fix truncating of doubles to integers
When analyzing the data flow and determining that a double is or'ed with
0, we correctly assume a cast to an integer and insert a convert
instruction in the IR instead of the actual bitwise or.. The JIT
implements that, but the interpreter doesn't, resulting in incorrect
values.
This problem is specific to the SSA optimizer and the underlying isel
requirements in 5.9 and does not apply to the design of the code
generator in 5.11 and onwards.
Task-number: QTBUG-68640
Change-Id: I954086b118b022bc6a8e00f17517c2d378825613
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 14 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_moth.cpp | 19 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 8 |
3 files changed, 41 insertions, 0 deletions
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index fbd513b537..5de5025a75 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -158,6 +158,8 @@ QT_BEGIN_NAMESPACE F(ShlConst, shlConst) \ F(Mul, mul) \ F(Sub, sub) \ + F(DoubleToInt, doubleToInt) \ + F(DoubleToUInt, doubleToUInt) \ F(BinopContext, binopContext) \ F(LoadThis, loadThis) \ F(LoadQmlContext, loadQmlContext) \ @@ -769,6 +771,16 @@ union Instr Param rhs; Param result; }; + struct instr_doubleToInt { + MOTH_INSTR_HEADER + Param source; + Param result; + }; + struct instr_doubleToUInt { + MOTH_INSTR_HEADER + Param source; + Param result; + }; struct instr_binopContext { MOTH_INSTR_HEADER uint alu; // offset inside the runtime methods @@ -884,6 +896,8 @@ union Instr instr_shlConst shlConst; instr_mul mul; instr_sub sub; + instr_doubleToInt doubleToInt; + instr_doubleToUInt doubleToUInt; instr_binopContext binopContext; instr_loadThis loadThis; instr_loadQmlContext loadQmlContext; diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp index c29ffa10c2..ae50153c1f 100644 --- a/src/qml/compiler/qv4isel_moth.cpp +++ b/src/qml/compiler/qv4isel_moth.cpp @@ -375,6 +375,25 @@ void InstructionSelection::callSubscript(IR::Expr *base, IR::Expr *index, IR::Ex void InstructionSelection::convertType(IR::Expr *source, IR::Expr *target) { + if (source->type == IR::DoubleType) { + switch (target->type) { + case IR::SInt32Type: + Instruction::DoubleToInt d2i; + d2i.source = getParam(source); + d2i.result = getParam(target); + addInstruction(d2i); + return; + case IR::UInt32Type: + Instruction::DoubleToUInt d2ui; + d2ui.source = getParam(source); + d2ui.result = getParam(target); + addInstruction(d2ui); + return; + default: + break; + } + } + // FIXME: do something more useful with this info if (target->type & IR::NumberType && !(source->type & IR::NumberType)) unop(IR::OpUPlus, source, target); diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 3d95353fc0..6b0540edac 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -892,6 +892,14 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code) STOREVALUE(instr.result, Runtime::method_sub(VALUE(instr.lhs), VALUE(instr.rhs))); MOTH_END_INSTR(Sub) + MOTH_BEGIN_INSTR(DoubleToInt) + STOREVALUE(instr.result, Encode(Runtime::method_doubleToInt(VALUE(instr.source).asDouble()))); + MOTH_END_INSTR(DoubleToInt) + + MOTH_BEGIN_INSTR(DoubleToUInt) + STOREVALUE(instr.result, Encode(Runtime::method_doubleToUInt(VALUE(instr.source).asDouble()))); + MOTH_END_INSTR(DoubleToUInt) + MOTH_BEGIN_INSTR(BinopContext) QV4::Runtime::BinaryOperationContext op = *reinterpret_cast<QV4::Runtime::BinaryOperationContext *>(reinterpret_cast<char *>(&engine->runtime.runtimeMethods[instr.alu])); STOREVALUE(instr.result, op(engine, VALUE(instr.lhs), VALUE(instr.rhs))); |