diff options
author | mikaelpeltier <mikaelpeltier@google.com> | 2015-05-22 16:59:33 +0200 |
---|---|---|
committer | Mikael Peltier <mikaelpeltier@google.com> | 2015-05-28 07:24:53 +0000 |
commit | 18d76d9a6dc022d7d89b3033e15c6945f877b688 (patch) | |
tree | a1e6d603d615111e3fc0982c11f84f27c9465b4b | |
parent | a613d7171d5528580d604d31d19aa9caccfc7a53 (diff) | |
download | toolchain_jill-18d76d9a6dc022d7d89b3033e15c6945f877b688.zip toolchain_jill-18d76d9a6dc022d7d89b3033e15c6945f877b688.tar.gz toolchain_jill-18d76d9a6dc022d7d89b3033e15c6945f877b688.tar.bz2 |
Fix bug when generating floating comparisons
- some combinaison of opcodes could not be rewrite into Jack IR
without adding a not operator on the condition to take into account
the specific NaN values.
Bug: 21384161
Change-Id: I1319e8f926a2b8eff875a5d8dddd31f335aa7fbe
(cherry picked from commit 0c5d494a389849f3745dcb9df6d23a2f1d841079)
-rw-r--r-- | jill/src/com/android/jill/frontend/java/MethodBodyWriter.java | 57 |
1 files changed, 51 insertions, 6 deletions
diff --git a/jill/src/com/android/jill/frontend/java/MethodBodyWriter.java b/jill/src/com/android/jill/frontend/java/MethodBodyWriter.java index 686037f..f68c9e7 100644 --- a/jill/src/com/android/jill/frontend/java/MethodBodyWriter.java +++ b/jill/src/com/android/jill/frontend/java/MethodBodyWriter.java @@ -132,12 +132,15 @@ public class MethodBodyWriter extends JillWriter implements Opcodes { } private static class CmpOperands{ + @Nonnegative + int opcode; @Nonnull Variable lhs; @Nonnull Variable rhs; - public CmpOperands(@Nonnull Variable lhs, @Nonnull Variable rhs) { + public CmpOperands(@Nonnegative int opcode, @Nonnull Variable lhs, @Nonnull Variable rhs) { + this.opcode = opcode; this.lhs = lhs; this.rhs = rhs; } @@ -1379,7 +1382,7 @@ public class MethodBodyWriter extends JillWriter implements Opcodes { Variable lhs = getStackVariable(frame, TOP_OF_STACK - 1); Variable rhs = getStackVariable(frame, TOP_OF_STACK); Variable result = getStackVariable(nextFrame, TOP_OF_STACK); - cmpOperands.put(result, new CmpOperands(lhs, rhs)); + cmpOperands.put(result, new CmpOperands(insn.getOpcode(), lhs, rhs)); break; } case DSUB: @@ -1732,15 +1735,27 @@ public class MethodBodyWriter extends JillWriter implements Opcodes { Variable topOfStackVariable = getStackVariable(frame, TOP_OF_STACK); CmpOperands cmpOps = cmpOperands.get(topOfStackVariable); if (cmpOps != null) { + // CmpOperands concerns double, float and long types assert jumpInsn.getOpcode() != IFNONNULL && jumpInsn.getOpcode() != IFNULL; + // Not operator can be generate only for double and long types to manage comparisons with + // Nan. + Token comparisonToken = getConditionToken(jumpInsn.getOpcode()); + boolean needNotoperator = needNotOperator(comparisonToken, cmpOps); sourceInfoWriter.writeDebugBegin(currentClass, currentLine); writer.writeCatchBlockIds(currentCatchList); writer.writeKeyword(Token.IF_STATEMENT); writer.writeOpen(); - // Condition is inverted to be compliant with language level semantics - // This has been done for comparison to NaN, which forces the branching order. - Token comparisonToken = invertComparisonToken(getConditionToken(jumpInsn.getOpcode())); + if (needNotoperator) { + sourceInfoWriter.writeDebugBegin(currentClass, currentLine); + writer.writeKeyword(Token.PREFIX_NOT_OPERATION); + writer.writeOpen(); + } else { + // Condition is inverted to be compliant with language level semantics + // This has been done for comparison to NaN, which forces the branching order. + comparisonToken = invertComparisonToken(comparisonToken); + } + sourceInfoWriter.writeDebugBegin(currentClass, currentLine); writer.writeKeyword(comparisonToken); writer.writeOpen(); @@ -1748,6 +1763,12 @@ public class MethodBodyWriter extends JillWriter implements Opcodes { writeLocalRef(cmpOps.rhs); sourceInfoWriter.writeDebugEnd(currentClass, currentLine + 1); writer.writeClose(); + + if (needNotoperator) { + sourceInfoWriter.writeDebugEnd(currentClass, currentLine + 1); + writer.writeClose(); + } + int labeledStatmentIndex = insIndex + 1; writeGoto(labeledStatmentIndex); writeGoto(jumpInsn.label); @@ -1757,7 +1778,6 @@ public class MethodBodyWriter extends JillWriter implements Opcodes { insertLabeledStatementIfNecessary(labeledStatmentIndex); cmpOperands.remove(topOfStackVariable); - } else { sourceInfoWriter.writeDebugBegin(currentClass, currentLine); writer.writeCatchBlockIds(currentCatchList); @@ -1891,6 +1911,31 @@ public class MethodBodyWriter extends JillWriter implements Opcodes { } } + @Nonnull + private boolean needNotOperator(@Nonnull Token cmpToken, @Nonnull CmpOperands cmpOps) { + switch (cmpToken) { + case GTE_OPERATION: + case GT_OPERATION: { + return !isCmpg(cmpOps); + } + case LTE_OPERATION: + case LT_OPERATION: { + return !isCmpl(cmpOps); + } + default: { + return false; + } + } + } + + private boolean isCmpl(@Nonnull CmpOperands cmpOps) { + return cmpOps.opcode == DCMPL || cmpOps.opcode == FCMPL; + } + + private boolean isCmpg(@Nonnull CmpOperands cmpOps) { + return cmpOps.opcode == DCMPG || cmpOps.opcode == FCMPG; + } + private void writeGoto(LabelNode labelNode) throws IOException { int insIndex = currentMethod.instructions.indexOf(labelNode); writeGoto(insIndex); |