diff options
author | Erik Verbruggen <[email protected]> | 2014-02-03 16:30:50 +0100 |
---|---|---|
committer | The Qt Project <[email protected]> | 2014-02-14 12:35:38 +0100 |
commit | 093fe73f915dbd2554fa4e109bfda59eeecb9a17 (patch) | |
tree | 0af491fb0c181b0e1a3001b63cfad5ad62f80447 /src/qml/compiler/qv4ssa.cpp | |
parent | 7fc6d58629d1fce4421e49b1c5a03e8af90381d8 (diff) |
V4: Do not reverse-propagate int32 conversion through unary minus.
Conversion to int32 might truncate, and because int32 is two's
complement, INT_MIN might get converted incorrectly.
Change-Id: Iaf893d3bd619f4c5791654e609f96cffca5c6917
Reviewed-by: Simon Hausmann <[email protected]>
Reviewed-by: Lars Knoll <[email protected]>
Diffstat (limited to 'src/qml/compiler/qv4ssa.cpp')
-rw-r--r-- | src/qml/compiler/qv4ssa.cpp | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp index ab20696e01..52c546039c 100644 --- a/src/qml/compiler/qv4ssa.cpp +++ b/src/qml/compiler/qv4ssa.cpp @@ -2323,12 +2323,14 @@ public: propagator.run(t, SInt32Type); if (Stmt *defStmt = _defUses.defStmt(t)) { if (Move *m = defStmt->asMove()) { - if (Convert *c = m->source->asConvert()) + if (Convert *c = m->source->asConvert()) { c->type = SInt32Type; - else if (Unop *u = m->source->asUnop()) - u->type = SInt32Type; - else if (Binop *b = m->source->asBinop()) + } else if (Unop *u = m->source->asUnop()) { + if (u->op != OpUMinus) + u->type = SInt32Type; + } else if (Binop *b = m->source->asBinop()) { b->type = SInt32Type; + } } } } @@ -2505,6 +2507,29 @@ public: } *conversion.expr = source; + } else if (Unop *u = (*conversion.expr)->asUnop()) { + // convert: + // int32{%2} = double{-double{%1}}; + // to: + // double{%3} = double{-double{%1}}; + // int32{%2} = int32{convert(double{%3})}; + Temp *tmp = bb->TEMP(bb->newTemp()); + tmp->type = u->type; + Move *extraMove = f->New<Move>(); + extraMove->init(tmp, u); + _defUses.addTemp(tmp, extraMove, bb); + + if (Temp *unopOperand = u->expr->asTemp()) { + _defUses.addUse(*unopOperand, extraMove); + _defUses.removeUse(move, *unopOperand); + } + + int idx = bb->statements.indexOf(conversion.stmt); + Q_ASSERT(idx != -1); + bb->statements.insert(idx, extraMove); + + *conversion.expr = bb->CONVERT(tmp, conversion.targetType); + _defUses.addUse(*tmp, move); } else { Q_UNREACHABLE(); } |