| // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import "package:expect/expect.dart"; | |
| import "package:compiler/src/inferrer/abstract_value_domain.dart"; | |
| import "package:compiler/src/ssa/nodes.dart"; | |
| import "package:compiler/src/ssa/value_range_analyzer.dart"; | |
| ValueRangeInfo info = ValueRangeInfo(); | |
| class AbstractValueDomainMock implements AbstractValueDomain { | |
| const AbstractValueDomainMock(); | |
| @override | |
| noSuchMethod(Invocation invocation) => null; | |
| } | |
| AbstractValueDomain abstractValueDomain = const AbstractValueDomainMock(); | |
| class HBreakMock implements HBreak { | |
| @override | |
| noSuchMethod(Invocation invocation) => null; | |
| } | |
| Value instructionValue = info.newInstructionValue(HBreakMock()); | |
| Value lengthValue = info.newPositiveValue(HBreakMock()); | |
| Range createSingleRange(Value value) => info.newNormalizedRange(value, value); | |
| Range createSingleIntRange(int value) { | |
| return createSingleRange(info.newIntValue(new BigInt.from(value))); | |
| } | |
| Range createSingleInstructionRange() => createSingleRange(instructionValue); | |
| Range createSingleLengthRange() => createSingleRange(lengthValue); | |
| Range createIntRange(int lower, int upper) { | |
| return info.newNormalizedRange( | |
| info.newIntValue(new BigInt.from(lower)), | |
| info.newIntValue(new BigInt.from(upper)), | |
| ); | |
| } | |
| Range createLengthRange(int lower) { | |
| return info.newNormalizedRange( | |
| info.newIntValue(new BigInt.from(lower)), | |
| lengthValue, | |
| ); | |
| } | |
| Range createInstructionRange(int lower) { | |
| return info.newNormalizedRange( | |
| info.newIntValue(new BigInt.from(lower)), | |
| instructionValue, | |
| ); | |
| } | |
| Range instruction = createSingleInstructionRange(); | |
| Range FF = createSingleIntRange(0xFF); | |
| Range FA = createSingleIntRange(0xFA); | |
| Range nFF = createSingleIntRange(-0xFF); | |
| Range length = createSingleLengthRange(); | |
| Range _FA_FF = createIntRange(0xFA, 0xFF); | |
| Range _0_FF = createIntRange(0, 0xFF); | |
| Range _nFF_FF = createIntRange(-0xFF, 0xFF); | |
| Range _nFF_0 = createIntRange(-0xFF, 0); | |
| Range _0_length = createLengthRange(0); | |
| Range _0_instruction = createInstructionRange(0); | |
| checkAndRange(Range one, Range two, lower, upper) { | |
| if (lower is num) lower = info.newIntValue(new BigInt.from(lower)); | |
| if (upper is num) upper = info.newIntValue(new BigInt.from(upper)); | |
| Range range = info.newNormalizedRange(lower, upper); | |
| Expect.equals(range, one & two); | |
| } | |
| checkSubRange(Range one, Range two, [lower, upper]) { | |
| buildBound(one, two) { | |
| // Create a bound just like our current implementation in dart2js does. | |
| if (two is IntValue) { | |
| if (two.isNegative) { | |
| return info.newAddValue(one, -two); | |
| } else if (two.isZero) { | |
| return one; | |
| } | |
| } | |
| if (one is IntValue) { | |
| if (one.isNegative) { | |
| return info.newSubtractValue(-two, -one); | |
| } else if (one.isZero) { | |
| return -two; | |
| } | |
| } | |
| return info.newSubtractValue(one, two); | |
| } | |
| if (lower == null) { | |
| lower = buildBound(one.lower, two.upper); | |
| } else if (lower is num) { | |
| lower = info.newIntValue(new BigInt.from(lower)); | |
| } | |
| if (upper == null) { | |
| upper = buildBound(one.upper, two.lower); | |
| } else if (upper is num) { | |
| upper = info.newIntValue(new BigInt.from(upper)); | |
| } | |
| Expect.equals(info.newNormalizedRange(lower, upper), one - two); | |
| } | |
| checkNegateRange(Range range, [arg1, arg2]) { | |
| if (arg1 is Range) { | |
| Expect.equals(arg1, -range); | |
| } else { | |
| Value low, up; | |
| if (arg1 is num) { | |
| low = info.newIntValue(new BigInt.from(arg1)); | |
| } else if (arg1 == null) { | |
| low = info.newNegateValue(range.upper); | |
| } else { | |
| low = arg1; | |
| } | |
| if (arg2 is num) { | |
| up = info.newIntValue(new BigInt.from(arg2)); | |
| } else if (arg2 == null) { | |
| up = info.newNegateValue(range.lower); | |
| } else { | |
| up = arg2; | |
| } | |
| Expect.equals(info.newNormalizedRange(low, up), -range); | |
| } | |
| } | |
| testNegate() { | |
| checkNegateRange(instruction); | |
| checkNegateRange(FF, nFF); | |
| checkNegateRange(nFF, FF); | |
| checkNegateRange(FA, -0xFA, -0xFA); | |
| checkNegateRange(length); | |
| checkNegateRange(_FA_FF, -0xFF, -0xFA); | |
| checkNegateRange(_0_FF, _nFF_0); | |
| checkNegateRange(_nFF_FF, _nFF_FF); | |
| checkNegateRange(_nFF_0, _0_FF); | |
| checkNegateRange(_0_length, -lengthValue, 0); | |
| checkNegateRange(_0_instruction, -instructionValue, 0); | |
| } | |
| bits32(value) => value & 0xFFFFFFFF; | |
| testAnd() { | |
| checkAndRange(instruction, instruction, info.minIntValue, info.maxIntValue); | |
| checkAndRange(instruction, FF, 0, 0xFF); | |
| checkAndRange(instruction, FA, 0, 0xFA); | |
| checkAndRange(instruction, nFF, info.minIntValue, info.maxIntValue); | |
| checkAndRange(instruction, length, 0, length.upper); | |
| checkAndRange(instruction, _FA_FF, 0, 0xFF); | |
| checkAndRange(instruction, _0_FF, 0, 0xFF); | |
| checkAndRange(instruction, _nFF_FF, info.minIntValue, info.maxIntValue); | |
| checkAndRange(instruction, _nFF_0, info.minIntValue, info.maxIntValue); | |
| checkAndRange(instruction, _0_length, 0, _0_length.upper); | |
| checkAndRange(instruction, _0_instruction, 0, _0_instruction.upper); | |
| checkAndRange(length, FF, 0, 0xFF); | |
| checkAndRange(length, FA, 0, 0xFA); | |
| checkAndRange(length, nFF, 0, length.upper); | |
| checkAndRange(length, length, 0, length.upper); | |
| checkAndRange(length, _FA_FF, 0, 0xFF); | |
| checkAndRange(length, _0_FF, 0, 0xFF); | |
| checkAndRange(length, _nFF_FF, 0, length.upper); | |
| checkAndRange(length, _nFF_0, 0, length.upper); | |
| checkAndRange(length, _0_length, 0, length.upper); | |
| checkAndRange(length, _0_instruction, 0, info.maxIntValue); | |
| checkAndRange(FF, FF, 0xFF, 0xFF); | |
| checkAndRange(FF, FA, 0xFA, 0xFA); | |
| checkAndRange(FF, nFF, 1, 1); | |
| checkAndRange(FF, length, 0, 0xFF); | |
| checkAndRange(FF, _FA_FF, 0, 0xFF); | |
| checkAndRange(FF, _0_FF, 0, 0xFF); | |
| checkAndRange(FF, _nFF_FF, 0, 0xFF); | |
| checkAndRange(FF, _nFF_0, 0, 0xFF); | |
| checkAndRange(FF, _0_length, 0, 0xFF); | |
| checkAndRange(FF, _0_instruction, 0, 0xFF); | |
| checkAndRange(FA, FF, 0xFA, 0xFA); | |
| checkAndRange(FA, FA, 0xFA, 0xFA); | |
| checkAndRange(FA, nFF, 0, 0); | |
| checkAndRange(FA, length, 0, 0xFA); | |
| checkAndRange(FA, _FA_FF, 0, 0xFA); | |
| checkAndRange(FA, _0_FF, 0, 0xFA); | |
| checkAndRange(FA, _nFF_FF, 0, 0xFA); | |
| checkAndRange(FA, _nFF_0, 0, 0xFA); | |
| checkAndRange(FA, _0_length, 0, 0xFA); | |
| checkAndRange(FA, _0_instruction, 0, 0xFA); | |
| checkAndRange(nFF, FF, 1, 1); | |
| checkAndRange(nFF, FA, 0, 0); | |
| checkAndRange(nFF, nFF, bits32(-0xFF), bits32(-0xFF)); | |
| checkAndRange(nFF, length, 0, length.upper); | |
| checkAndRange(nFF, _FA_FF, 0, 0xFF); | |
| checkAndRange(nFF, _0_FF, 0, 0xFF); | |
| checkAndRange(nFF, _nFF_FF, info.minIntValue, info.maxIntValue); | |
| checkAndRange(nFF, _nFF_0, info.minIntValue, info.maxIntValue); | |
| checkAndRange(nFF, _0_length, 0, _0_length.upper); | |
| checkAndRange(nFF, _0_instruction, 0, _0_instruction.upper); | |
| checkAndRange(_FA_FF, FF, 0, 0xFF); | |
| checkAndRange(_FA_FF, FA, 0, 0xFA); | |
| checkAndRange(_FA_FF, nFF, 0, 0xFF); | |
| checkAndRange(_FA_FF, length, 0, 0xFF); | |
| checkAndRange(_FA_FF, _FA_FF, 0, 0xFF); | |
| checkAndRange(_FA_FF, _0_FF, 0, 0xFF); | |
| checkAndRange(_FA_FF, _nFF_FF, 0, 0xFF); | |
| checkAndRange(_FA_FF, _nFF_0, 0, 0xFF); | |
| checkAndRange(_FA_FF, _0_length, 0, 0xFF); | |
| checkAndRange(_FA_FF, _0_instruction, 0, 0xFF); | |
| checkAndRange(_0_FF, FF, 0, 0xFF); | |
| checkAndRange(_0_FF, FA, 0, 0xFA); | |
| checkAndRange(_0_FF, nFF, 0, 0xFF); | |
| checkAndRange(_0_FF, length, 0, 0xFF); | |
| checkAndRange(_0_FF, _FA_FF, 0, 0xFF); | |
| checkAndRange(_0_FF, _0_FF, 0, 0xFF); | |
| checkAndRange(_0_FF, _nFF_FF, 0, 0xFF); | |
| checkAndRange(_0_FF, _nFF_0, 0, 0xFF); | |
| checkAndRange(_0_FF, _0_length, 0, 0xFF); | |
| checkAndRange(_0_FF, _0_instruction, 0, 0xFF); | |
| checkAndRange(_nFF_FF, FF, 0, 0xFF); | |
| checkAndRange(_nFF_FF, FA, 0, 0xFA); | |
| checkAndRange(_nFF_FF, nFF, info.minIntValue, info.maxIntValue); | |
| checkAndRange(_nFF_FF, length, 0, length.upper); | |
| checkAndRange(_nFF_FF, _FA_FF, 0, 0xFF); | |
| checkAndRange(_nFF_FF, _0_FF, 0, 0xFF); | |
| checkAndRange(_nFF_FF, _nFF_FF, info.minIntValue, info.maxIntValue); | |
| checkAndRange(_nFF_FF, _nFF_0, info.minIntValue, info.maxIntValue); | |
| checkAndRange(_nFF_FF, _0_length, 0, _0_length.upper); | |
| checkAndRange(_nFF_FF, _0_instruction, 0, _0_instruction.upper); | |
| checkAndRange(_nFF_0, FF, 0, 0xFF); | |
| checkAndRange(_nFF_0, FA, 0, 0xFA); | |
| checkAndRange(_nFF_0, nFF, info.minIntValue, info.maxIntValue); | |
| checkAndRange(_nFF_0, length, 0, length.upper); | |
| checkAndRange(_nFF_0, _FA_FF, 0, 0xFF); | |
| checkAndRange(_nFF_0, _0_FF, 0, 0xFF); | |
| checkAndRange(_nFF_0, _nFF_FF, info.minIntValue, info.maxIntValue); | |
| checkAndRange(_nFF_0, _nFF_0, info.minIntValue, info.maxIntValue); | |
| checkAndRange(_nFF_0, _0_length, 0, _0_length.upper); | |
| checkAndRange(_nFF_0, _0_instruction, 0, _0_instruction.upper); | |
| checkAndRange(_0_length, FF, 0, 0xFF); | |
| checkAndRange(_0_length, FA, 0, 0xFA); | |
| checkAndRange(_0_length, nFF, 0, _0_length.upper); | |
| checkAndRange(_0_length, length, 0, length.upper); | |
| checkAndRange(_0_length, _FA_FF, 0, 0xFF); | |
| checkAndRange(_0_length, _0_FF, 0, 0xFF); | |
| checkAndRange(_0_length, _nFF_FF, 0, _0_length.upper); | |
| checkAndRange(_0_length, _nFF_0, 0, _0_length.upper); | |
| checkAndRange(_0_length, _0_length, 0, _0_length.upper); | |
| checkAndRange(_0_length, _0_instruction, 0, info.maxIntValue); | |
| checkAndRange(_0_instruction, FF, 0, 0xFF); | |
| checkAndRange(_0_instruction, FA, 0, 0xFA); | |
| checkAndRange(_0_instruction, nFF, 0, _0_instruction.upper); | |
| checkAndRange(_0_instruction, length, 0, info.maxIntValue); | |
| checkAndRange(_0_instruction, _FA_FF, 0, 0xFF); | |
| checkAndRange(_0_instruction, _0_FF, 0, 0xFF); | |
| checkAndRange(_0_instruction, _nFF_FF, 0, _0_instruction.upper); | |
| checkAndRange(_0_instruction, _nFF_0, 0, _0_instruction.upper); | |
| checkAndRange(_0_instruction, _0_length, 0, info.maxIntValue); | |
| checkAndRange(_0_instruction, _0_instruction, 0, _0_instruction.upper); | |
| } | |
| testSub() { | |
| checkSubRange(instruction, instruction, 0, 0); | |
| checkSubRange(instruction, FF); | |
| checkSubRange(instruction, FA); | |
| checkSubRange(instruction, nFF); | |
| checkSubRange(instruction, length); | |
| checkSubRange(instruction, _FA_FF); | |
| checkSubRange(instruction, _0_FF, null, instruction.upper); | |
| checkSubRange(instruction, _nFF_FF); | |
| checkSubRange(instruction, _nFF_0, instruction.lower, null); | |
| checkSubRange(instruction, _0_length, null, instruction.upper); | |
| checkSubRange(instruction, _0_instruction, 0, _0_instruction.upper); | |
| checkSubRange(length, FF); | |
| checkSubRange(length, FA); | |
| checkSubRange(length, nFF); | |
| checkSubRange(length, length, 0, 0); | |
| checkSubRange(length, _FA_FF); | |
| checkSubRange(length, _0_FF, null, length.upper); | |
| checkSubRange(length, _nFF_FF); | |
| checkSubRange(length, _nFF_0, length.lower, null); | |
| checkSubRange(length, _0_length, 0, length.upper); | |
| checkSubRange(length, _0_instruction, null, length.upper); | |
| checkSubRange(FF, FF, 0, 0); | |
| checkSubRange(FF, FA, 0xFF - 0xFA, 0xFF - 0xFA); | |
| checkSubRange(FF, nFF, 0xFF + 0xFF, 0xFF + 0xFF); | |
| checkSubRange(FF, length); | |
| checkSubRange(FF, _FA_FF, 0, 0xFF - 0xFA); | |
| checkSubRange(FF, _0_FF, 0, 0xFF); | |
| checkSubRange(FF, _nFF_FF, 0, 0xFF + 0xFF); | |
| checkSubRange(FF, _nFF_0, 0xFF, 0xFF + 0xFF); | |
| checkSubRange(FF, _0_length, null, 0xFF); | |
| checkSubRange(FF, _0_instruction, null, 0xFF); | |
| checkSubRange(FA, FF, 0xFA - 0xFF, 0xFA - 0xFF); | |
| checkSubRange(FA, FA, 0, 0); | |
| checkSubRange(FA, nFF, 0xFA + 0xFF, 0xFA + 0xFF); | |
| checkSubRange(FA, length); | |
| checkSubRange(FA, _FA_FF, 0xFA - 0xFF, 0); | |
| checkSubRange(FA, _0_FF, 0xFA - 0xFF, 0xFA); | |
| checkSubRange(FA, _nFF_FF, 0xFA - 0xFF, 0xFA + 0xFF); | |
| checkSubRange(FA, _nFF_0, 0xFA, 0xFA + 0xFF); | |
| checkSubRange(FA, _0_length, null, 0xFA); | |
| checkSubRange(FA, _0_instruction, null, 0xFA); | |
| checkSubRange(nFF, FF, -0xFF - 0xFF, -0xFF - 0xFF); | |
| checkSubRange(nFF, FA, -0xFF - 0xFA, -0xFF - 0xFA); | |
| checkSubRange(nFF, nFF, 0, 0); | |
| checkSubRange(nFF, length); | |
| checkSubRange(nFF, _FA_FF, -0xFF - 0xFF, -0xFF - 0xFA); | |
| checkSubRange(nFF, _0_FF, -0xFF - 0xFF, -0xFF); | |
| checkSubRange(nFF, _nFF_FF, -0xFF - 0xFF, 0); | |
| checkSubRange(nFF, _nFF_0, -0xFF, 0); | |
| checkSubRange(nFF, _0_length, null, -0xFF); | |
| checkSubRange(nFF, _0_instruction, null, -0xFF); | |
| checkSubRange(_FA_FF, FF, 0xFA - 0xFF, 0); | |
| checkSubRange(_FA_FF, FA, 0, 0xFF - 0xFA); | |
| checkSubRange(_FA_FF, nFF, 0xFA + 0xFF, 0xFF + 0xFF); | |
| checkSubRange(_FA_FF, length); | |
| checkSubRange(_FA_FF, _FA_FF, 0xFA - 0xFF, 0xFF - 0xFA); | |
| checkSubRange(_FA_FF, _0_FF, 0xFA - 0xFF, 0xFF); | |
| checkSubRange(_FA_FF, _nFF_FF, 0xFA - 0xFF, 0xFF + 0xFF); | |
| checkSubRange(_FA_FF, _nFF_0, 0xFA, 0xFF + 0xFF); | |
| checkSubRange(_FA_FF, _0_length, null, 0xFF); | |
| checkSubRange(_FA_FF, _0_instruction, null, 0xFF); | |
| checkSubRange(_0_FF, FF, -0xFF, 0); | |
| checkSubRange(_0_FF, FA, -0xFA, 0xFF - 0xFA); | |
| checkSubRange(_0_FF, nFF, 0xFF, 0xFF + 0xFF); | |
| checkSubRange(_0_FF, length); | |
| checkSubRange(_0_FF, _FA_FF, -0xFF, 0xFF - 0xFA); | |
| checkSubRange(_0_FF, _0_FF, -0xFF, 0xFF); | |
| checkSubRange(_0_FF, _nFF_FF, -0xFF, 0xFF + 0xFF); | |
| checkSubRange(_0_FF, _nFF_0, 0, 0xFF + 0xFF); | |
| checkSubRange(_0_FF, _0_length, null, 0xFF); | |
| checkSubRange(_0_FF, _0_instruction, null, 0xFF); | |
| checkSubRange(_nFF_FF, FF, -0xFF - 0xFF, 0); | |
| checkSubRange(_nFF_FF, FA, -0xFF - 0xFA, 0xFF - 0xFA); | |
| checkSubRange(_nFF_FF, nFF, 0, 0xFF + 0xFF); | |
| checkSubRange(_nFF_FF, length); | |
| checkSubRange(_nFF_FF, _FA_FF, -0xFF - 0xFF, 0xFF - 0xFA); | |
| checkSubRange(_nFF_FF, _0_FF, -0xFF - 0xFF, 0xFF); | |
| checkSubRange(_nFF_FF, _nFF_FF, -0xFF - 0xFF, 0xFF + 0xFF); | |
| checkSubRange(_nFF_FF, _nFF_0, -0xFF, 0xFF + 0xFF); | |
| checkSubRange(_nFF_FF, _0_length, null, 0xFF); | |
| checkSubRange(_nFF_FF, _0_instruction, null, 0xFF); | |
| checkSubRange(_nFF_0, FF, -0xFF - 0xFF, -0xFF); | |
| checkSubRange(_nFF_0, FA, -0xFF - 0xFA, -0xFA); | |
| checkSubRange(_nFF_0, nFF, 0, 0xFF); | |
| checkSubRange(_nFF_0, length); | |
| checkSubRange(_nFF_0, _FA_FF, -0xFF - 0xFF, -0xFA); | |
| checkSubRange(_nFF_0, _0_FF, -0xFF - 0xFF, 0); | |
| checkSubRange(_nFF_0, _nFF_FF, -0xFF - 0xFF, 0xFF); | |
| checkSubRange(_nFF_0, _nFF_0, -0xFF, 0xFF); | |
| checkSubRange(_nFF_0, _0_length, null, 0); | |
| checkSubRange(_nFF_0, _0_instruction, null, 0); | |
| checkSubRange(_0_length, FF, -0xFF, null); | |
| checkSubRange(_0_length, FA, -0xFA, null); | |
| checkSubRange(_0_length, nFF, 0xFF, null); | |
| checkSubRange(_0_length, length, null, 0); | |
| checkSubRange(_0_length, _FA_FF, -0xFF, null); | |
| checkSubRange(_0_length, _0_FF, -0xFF, _0_length.upper); | |
| checkSubRange(_0_length, _nFF_FF, -0xFF, null); | |
| checkSubRange(_0_length, _nFF_0, 0, null); | |
| checkSubRange(_0_length, _0_length, null, _0_length.upper); | |
| checkSubRange(_0_length, _0_instruction, null, _0_length.upper); | |
| checkSubRange(_0_instruction, FF, -0xFF, null); | |
| checkSubRange(_0_instruction, FA, -0xFA, null); | |
| checkSubRange(_0_instruction, nFF, 0xFF, null); | |
| checkSubRange(_0_instruction, length); | |
| checkSubRange(_0_instruction, _FA_FF, -0xFF, null); | |
| checkSubRange(_0_instruction, _0_FF, -0xFF, _0_instruction.upper); | |
| checkSubRange(_0_instruction, _nFF_FF, -0xFF, null); | |
| checkSubRange(_0_instruction, _nFF_0, 0, null); | |
| checkSubRange(_0_instruction, _0_length, null, _0_instruction.upper); | |
| checkSubRange(_0_instruction, _0_instruction, null, _0_instruction.upper); | |
| } | |
| main() { | |
| HInstruction.idCounter = 0; | |
| testAnd(); | |
| testSub(); | |
| testNegate(); | |
| } |