diff options
-rw-r--r-- | compiler/optimizing/builder.cc | 5 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 53 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 50 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 51 | ||||
-rw-r--r-- | compiler/optimizing/codegen_test.cc | 21 | ||||
-rw-r--r-- | compiler/utils/x86_64/assembler_x86_64.cc | 1 | ||||
-rw-r--r-- | test/415-optimizing-arith-neg/src/Main.java | 16 | ||||
-rw-r--r-- | test/416-optimizing-arith-not/src/Main.java | 24 | ||||
-rw-r--r-- | test/422-type-conversion/src/Main.java | 119 |
9 files changed, 273 insertions, 67 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index 76a2be927e..11dd0f39f9 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -961,6 +961,11 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 break; } + case Instruction::LONG_TO_INT: { + Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimInt); + break; + } + case Instruction::ADD_INT: { Binop_23x<HAdd>(instruction, Primitive::kPrimInt); break; diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index b0a56d58a3..0958cdf742 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -22,9 +22,9 @@ #include "mirror/art_method.h" #include "mirror/class.h" #include "thread.h" -#include "utils/assembler.h" #include "utils/arm/assembler_arm.h" #include "utils/arm/managed_register_arm.h" +#include "utils/assembler.h" #include "utils/stack_checks.h" namespace art { @@ -1345,6 +1345,26 @@ void LocationsBuilderARM::VisitTypeConversion(HTypeConversion* conversion) { Primitive::Type result_type = conversion->GetResultType(); Primitive::Type input_type = conversion->GetInputType(); switch (result_type) { + case Primitive::kPrimInt: + switch (input_type) { + case Primitive::kPrimLong: + // long-to-int conversion. + locations->SetInAt(0, Location::Any()); + locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); + break; + + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Type conversion from " << input_type + << " to " << result_type << " not yet implemented"; + break; + + default: + LOG(FATAL) << "Unexpected type conversion from " << input_type + << " to " << result_type; + } + break; + case Primitive::kPrimLong: switch (input_type) { case Primitive::kPrimByte: @@ -1368,7 +1388,6 @@ void LocationsBuilderARM::VisitTypeConversion(HTypeConversion* conversion) { } break; - case Primitive::kPrimInt: case Primitive::kPrimFloat: case Primitive::kPrimDouble: LOG(FATAL) << "Type conversion from " << input_type @@ -1388,6 +1407,35 @@ void InstructionCodeGeneratorARM::VisitTypeConversion(HTypeConversion* conversio Primitive::Type result_type = conversion->GetResultType(); Primitive::Type input_type = conversion->GetInputType(); switch (result_type) { + case Primitive::kPrimInt: + switch (input_type) { + case Primitive::kPrimLong: + // long-to-int conversion. + DCHECK(out.IsRegister()); + if (in.IsRegisterPair()) { + __ Mov(out.As<Register>(), in.AsRegisterPairLow<Register>()); + } else if (in.IsDoubleStackSlot()) { + __ LoadFromOffset(kLoadWord, out.As<Register>(), SP, in.GetStackIndex()); + } else { + DCHECK(in.IsConstant()); + DCHECK(in.GetConstant()->IsLongConstant()); + int64_t value = in.GetConstant()->AsLongConstant()->GetValue(); + __ LoadImmediate(out.As<Register>(), static_cast<int32_t>(value)); + } + break; + + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Type conversion from " << input_type + << " to " << result_type << " not yet implemented"; + break; + + default: + LOG(FATAL) << "Unexpected type conversion from " << input_type + << " to " << result_type; + } + break; + case Primitive::kPrimLong: switch (input_type) { case Primitive::kPrimByte: @@ -1416,7 +1464,6 @@ void InstructionCodeGeneratorARM::VisitTypeConversion(HTypeConversion* conversio } break; - case Primitive::kPrimInt: case Primitive::kPrimFloat: case Primitive::kPrimDouble: LOG(FATAL) << "Type conversion from " << input_type diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index aa609a629c..14c7fe4456 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -1277,6 +1277,26 @@ void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) { Primitive::Type result_type = conversion->GetResultType(); Primitive::Type input_type = conversion->GetInputType(); switch (result_type) { + case Primitive::kPrimInt: + switch (input_type) { + case Primitive::kPrimLong: + // long-to-int conversion. + locations->SetInAt(0, Location::Any()); + locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); + break; + + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Type conversion from " << input_type + << " to " << result_type << " not yet implemented"; + break; + + default: + LOG(FATAL) << "Unexpected type conversion from " << input_type + << " to " << result_type; + } + break; + case Primitive::kPrimLong: switch (input_type) { case Primitive::kPrimByte: @@ -1300,7 +1320,6 @@ void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) { } break; - case Primitive::kPrimInt: case Primitive::kPrimFloat: case Primitive::kPrimDouble: LOG(FATAL) << "Type conversion from " << input_type @@ -1320,6 +1339,34 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio Primitive::Type result_type = conversion->GetResultType(); Primitive::Type input_type = conversion->GetInputType(); switch (result_type) { + case Primitive::kPrimInt: + switch (input_type) { + case Primitive::kPrimLong: + // long-to-int conversion. + if (in.IsRegisterPair()) { + __ movl(out.As<Register>(), in.AsRegisterPairLow<Register>()); + } else if (in.IsDoubleStackSlot()) { + __ movl(out.As<Register>(), Address(ESP, in.GetStackIndex())); + } else { + DCHECK(in.IsConstant()); + DCHECK(in.GetConstant()->IsLongConstant()); + int64_t value = in.GetConstant()->AsLongConstant()->GetValue(); + __ movl(out.As<Register>(), Immediate(static_cast<int32_t>(value))); + } + break; + + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Type conversion from " << input_type + << " to " << result_type << " not yet implemented"; + break; + + default: + LOG(FATAL) << "Unexpected type conversion from " << input_type + << " to " << result_type; + } + break; + case Primitive::kPrimLong: switch (input_type) { case Primitive::kPrimByte: @@ -1345,7 +1392,6 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio } break; - case Primitive::kPrimInt: case Primitive::kPrimFloat: case Primitive::kPrimDouble: LOG(FATAL) << "Type conversion from " << input_type diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index bd1e4f4f04..5667fa725a 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -1276,6 +1276,26 @@ void LocationsBuilderX86_64::VisitTypeConversion(HTypeConversion* conversion) { Primitive::Type result_type = conversion->GetResultType(); Primitive::Type input_type = conversion->GetInputType(); switch (result_type) { + case Primitive::kPrimInt: + switch (input_type) { + case Primitive::kPrimLong: + // long-to-int conversion. + locations->SetInAt(0, Location::Any()); + locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); + break; + + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Type conversion from " << input_type + << " to " << result_type << " not yet implemented"; + break; + + default: + LOG(FATAL) << "Unexpected type conversion from " << input_type + << " to " << result_type; + } + break; + case Primitive::kPrimLong: switch (input_type) { case Primitive::kPrimByte: @@ -1301,7 +1321,6 @@ void LocationsBuilderX86_64::VisitTypeConversion(HTypeConversion* conversion) { } break; - case Primitive::kPrimInt: case Primitive::kPrimFloat: case Primitive::kPrimDouble: LOG(FATAL) << "Type conversion from " << input_type @@ -1321,6 +1340,35 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver Primitive::Type result_type = conversion->GetResultType(); Primitive::Type input_type = conversion->GetInputType(); switch (result_type) { + case Primitive::kPrimInt: + switch (input_type) { + case Primitive::kPrimLong: + // long-to-int conversion. + if (in.IsRegister()) { + __ movl(out.As<CpuRegister>(), in.As<CpuRegister>()); + } else if (in.IsDoubleStackSlot()) { + __ movl(out.As<CpuRegister>(), + Address(CpuRegister(RSP), in.GetStackIndex())); + } else { + DCHECK(in.IsConstant()); + DCHECK(in.GetConstant()->IsLongConstant()); + int64_t value = in.GetConstant()->AsLongConstant()->GetValue(); + __ movl(out.As<CpuRegister>(), Immediate(static_cast<int32_t>(value))); + } + break; + + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Type conversion from " << input_type + << " to " << result_type << " not yet implemented"; + break; + + default: + LOG(FATAL) << "Unexpected type conversion from " << input_type + << " to " << result_type; + } + break; + case Primitive::kPrimLong: switch (input_type) { DCHECK(out.IsRegister()); @@ -1345,7 +1393,6 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver } break; - case Primitive::kPrimInt: case Primitive::kPrimFloat: case Primitive::kPrimDouble: LOG(FATAL) << "Type conversion from " << input_type diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc index ecee44392e..9752b1d34b 100644 --- a/compiler/optimizing/codegen_test.cc +++ b/compiler/optimizing/codegen_test.cc @@ -362,6 +362,27 @@ NOT_LONG_TEST(ReturnNotLongINT64_MAX, #undef NOT_LONG_TEST +#if defined(__aarch64__) +TEST(CodegenTest, DISABLED_IntToLongOfLongToInt) { +#else +TEST(CodegenTest, IntToLongOfLongToInt) { +#endif + const int64_t input = INT64_C(4294967296); // 2^32 + const uint16_t word0 = Low16Bits(Low32Bits(input)); // LSW. + const uint16_t word1 = High16Bits(Low32Bits(input)); + const uint16_t word2 = Low16Bits(High32Bits(input)); + const uint16_t word3 = High16Bits(High32Bits(input)); // MSW. + const uint16_t data[] = FIVE_REGISTERS_CODE_ITEM( + Instruction::CONST_WIDE | 0 << 8, word0, word1, word2, word3, + Instruction::CONST_WIDE | 2 << 8, 1, 0, 0, 0, + Instruction::ADD_LONG | 0, 0 << 8 | 2, // v0 <- 2^32 + 1 + Instruction::LONG_TO_INT | 4 << 8 | 0 << 12, + Instruction::INT_TO_LONG | 2 << 8 | 4 << 12, + Instruction::RETURN_WIDE | 2 << 8); + + TestCodeLong(data, true, 1); +} + TEST(CodegenTest, ReturnAdd1) { const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( Instruction::CONST_4 | 3 << 12 | 0, diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc index bc547024bf..c75fa786e8 100644 --- a/compiler/utils/x86_64/assembler_x86_64.cc +++ b/compiler/utils/x86_64/assembler_x86_64.cc @@ -120,6 +120,7 @@ void X86_64Assembler::movq(CpuRegister dst, const Immediate& imm) { void X86_64Assembler::movl(CpuRegister dst, const Immediate& imm) { + CHECK(imm.is_int32()); AssemblerBuffer::EnsureCapacity ensured(&buffer_); EmitOptionalRex32(dst); EmitUint8(0xB8 + dst.LowBits()); diff --git a/test/415-optimizing-arith-neg/src/Main.java b/test/415-optimizing-arith-neg/src/Main.java index e2850ca760..d9f8bcf0c2 100644 --- a/test/415-optimizing-arith-neg/src/Main.java +++ b/test/415-optimizing-arith-neg/src/Main.java @@ -71,8 +71,8 @@ public class Main { assertEquals(0, $opt$NegInt(0)); assertEquals(51, $opt$NegInt(-51)); assertEquals(-51, $opt$NegInt(51)); - assertEquals(2147483647, $opt$NegInt(-2147483647)); // (2^31 - 1) - assertEquals(-2147483647, $opt$NegInt(2147483647)); // -(2^31 - 1) + assertEquals(2147483647, $opt$NegInt(-2147483647)); // -(2^31 - 1) + assertEquals(-2147483647, $opt$NegInt(2147483647)); // 2^31 - 1 // From the Java 7 SE Edition specification: // http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.15.4 // @@ -98,13 +98,13 @@ public class Main { assertEquals(51L, $opt$NegLong(-51L)); assertEquals(-51L, $opt$NegLong(51L)); - assertEquals(2147483647L, $opt$NegLong(-2147483647L)); // (2^31 - 1) - assertEquals(-2147483647L, $opt$NegLong(2147483647L)); // -(2^31 - 1) - assertEquals(2147483648L, $opt$NegLong(-2147483648L)); // 2^31 - assertEquals(-2147483648L, $opt$NegLong(2147483648L)); // -(2^31) + assertEquals(2147483647L, $opt$NegLong(-2147483647L)); // -(2^31 - 1) + assertEquals(-2147483647L, $opt$NegLong(2147483647L)); // (2^31 - 1) + assertEquals(2147483648L, $opt$NegLong(-2147483648L)); // -(2^31) + assertEquals(-2147483648L, $opt$NegLong(2147483648L)); // 2^31 - assertEquals(9223372036854775807L, $opt$NegLong(-9223372036854775807L)); // (2^63 - 1) - assertEquals(-9223372036854775807L, $opt$NegLong(9223372036854775807L)); // -(2^63 - 1) + assertEquals(9223372036854775807L, $opt$NegLong(-9223372036854775807L)); // -(2^63 - 1) + assertEquals(-9223372036854775807L, $opt$NegLong(9223372036854775807L)); // 2^63 - 1 // See remark regarding the negation of the maximum negative // (long) value in negInt(). assertEquals(-9223372036854775808L, $opt$NegLong(-9223372036854775808L)); // -(2^63) diff --git a/test/416-optimizing-arith-not/src/Main.java b/test/416-optimizing-arith-not/src/Main.java index 26e206c94d..44c7d3cfb0 100644 --- a/test/416-optimizing-arith-not/src/Main.java +++ b/test/416-optimizing-arith-not/src/Main.java @@ -40,10 +40,10 @@ public class Main { expectEquals(0, smaliNotInt(-1)); expectEquals(-1, smaliNotInt(0)); expectEquals(-2, smaliNotInt(1)); - expectEquals(2147483647, smaliNotInt(-2147483648)); // (2^31) - 1 - expectEquals(2147483646, smaliNotInt(-2147483647)); // (2^31) - 2 - expectEquals(-2147483647, smaliNotInt(2147483646)); // -(2^31) - 1 - expectEquals(-2147483648, smaliNotInt(2147483647)); // -(2^31) + expectEquals(2147483647, smaliNotInt(-2147483648)); // -(2^31) + expectEquals(2147483646, smaliNotInt(-2147483647)); // -(2^31 - 1) + expectEquals(-2147483647, smaliNotInt(2147483646)); // 2^31 - 2 + expectEquals(-2147483648, smaliNotInt(2147483647)); // 2^31 - 1 } private static void notLong() throws Exception { @@ -51,14 +51,14 @@ public class Main { expectEquals(0L, smaliNotLong(-1L)); expectEquals(-1L, smaliNotLong(0L)); expectEquals(-2L, smaliNotLong(1L)); - expectEquals(2147483647L, smaliNotLong(-2147483648L)); // (2^31) - 1 - expectEquals(2147483646L, smaliNotLong(-2147483647L)); // (2^31) - 2 - expectEquals(-2147483647L, smaliNotLong(2147483646L)); // -(2^31) - 1 - expectEquals(-2147483648L, smaliNotLong(2147483647L)); // -(2^31) - expectEquals(9223372036854775807L, smaliNotLong(-9223372036854775808L)); // (2^63) - 1 - expectEquals(9223372036854775806L, smaliNotLong(-9223372036854775807L)); // (2^63) - 2 - expectEquals(-9223372036854775807L, smaliNotLong(9223372036854775806L)); // -(2^63) - 1 - expectEquals(-9223372036854775808L, smaliNotLong(9223372036854775807L)); // -(2^63) + expectEquals(2147483647L, smaliNotLong(-2147483648L)); // -(2^31) + expectEquals(2147483646L, smaliNotLong(-2147483647L)); // -(2^31 - 1) + expectEquals(-2147483647L, smaliNotLong(2147483646L)); // 2^31 - 2 + expectEquals(-2147483648L, smaliNotLong(2147483647L)); // 2^31 - 1 + expectEquals(9223372036854775807L, smaliNotLong(-9223372036854775808L)); // -(2^63) + expectEquals(9223372036854775806L, smaliNotLong(-9223372036854775807L)); // -(2^63 - 1) + expectEquals(-9223372036854775807L, smaliNotLong(9223372036854775806L)); // 2^63 - 2 + expectEquals(-9223372036854775808L, smaliNotLong(9223372036854775807L)); // 2^63 - 1 } // Wrappers around methods located in file not.smali. diff --git a/test/422-type-conversion/src/Main.java b/test/422-type-conversion/src/Main.java index d61f255179..a4232ed3a5 100644 --- a/test/422-type-conversion/src/Main.java +++ b/test/422-type-conversion/src/Main.java @@ -18,7 +18,13 @@ // it does compile the method. public class Main { - public static void assertEquals(long expected, long result) { + public static void assertIntEquals(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + public static void assertLongEquals(long expected, long result) { if (expected != result) { throw new Error("Expected: " + expected + ", found: " + result); } @@ -26,63 +32,96 @@ public class Main { public static void main(String[] args) { byteToLong(); - charToLong(); shortToLong(); intToLong(); + charToLong(); + + longToInt(); } private static void byteToLong() { - assertEquals(1L, $opt$ByteToLong((byte)1)); - assertEquals(0L, $opt$ByteToLong((byte)0)); - assertEquals(-1L, $opt$ByteToLong((byte)-1)); - assertEquals(51L, $opt$ByteToLong((byte)51)); - assertEquals(-51L, $opt$ByteToLong((byte)-51)); - assertEquals(127L, $opt$ByteToLong((byte)127)); // (2^7) - 1 - assertEquals(-127L, $opt$ByteToLong((byte)-127)); // -(2^7) - 1 - assertEquals(-128L, $opt$ByteToLong((byte)-128)); // -(2^7) + assertLongEquals(1L, $opt$ByteToLong((byte)1)); + assertLongEquals(0L, $opt$ByteToLong((byte)0)); + assertLongEquals(-1L, $opt$ByteToLong((byte)-1)); + assertLongEquals(51L, $opt$ByteToLong((byte)51)); + assertLongEquals(-51L, $opt$ByteToLong((byte)-51)); + assertLongEquals(127L, $opt$ByteToLong((byte)127)); // 2^7 - 1 + assertLongEquals(-127L, $opt$ByteToLong((byte)-127)); // -(2^7 - 1) + assertLongEquals(-128L, $opt$ByteToLong((byte)-128)); // -(2^7) } private static void shortToLong() { - assertEquals(1L, $opt$ShortToLong((short)1)); - assertEquals(0L, $opt$ShortToLong((short)0)); - assertEquals(-1L, $opt$ShortToLong((short)-1)); - assertEquals(51L, $opt$ShortToLong((short)51)); - assertEquals(-51L, $opt$ShortToLong((short)-51)); - assertEquals(32767L, $opt$ShortToLong((short)32767)); // (2^15) - 1 - assertEquals(-32767L, $opt$ShortToLong((short)-32767)); // -(2^15) - 1 - assertEquals(-32768L, $opt$ShortToLong((short)-32768)); // -(2^15) + assertLongEquals(1L, $opt$ShortToLong((short)1)); + assertLongEquals(0L, $opt$ShortToLong((short)0)); + assertLongEquals(-1L, $opt$ShortToLong((short)-1)); + assertLongEquals(51L, $opt$ShortToLong((short)51)); + assertLongEquals(-51L, $opt$ShortToLong((short)-51)); + assertLongEquals(32767L, $opt$ShortToLong((short)32767)); // 2^15 - 1 + assertLongEquals(-32767L, $opt$ShortToLong((short)-32767)); // -(2^15 - 1) + assertLongEquals(-32768L, $opt$ShortToLong((short)-32768)); // -(2^15) } private static void intToLong() { - assertEquals(1L, $opt$IntToLong(1)); - assertEquals(0L, $opt$IntToLong(0)); - assertEquals(-1L, $opt$IntToLong(-1)); - assertEquals(51L, $opt$IntToLong(51)); - assertEquals(-51L, $opt$IntToLong(-51)); - assertEquals(2147483647L, $opt$IntToLong(2147483647)); // (2^31) - 1 - assertEquals(-2147483647L, $opt$IntToLong(-2147483647)); // -(2^31) - 1 - assertEquals(-2147483648L, $opt$IntToLong(-2147483648)); // -(2^31) + assertLongEquals(1L, $opt$IntToLong(1)); + assertLongEquals(0L, $opt$IntToLong(0)); + assertLongEquals(-1L, $opt$IntToLong(-1)); + assertLongEquals(51L, $opt$IntToLong(51)); + assertLongEquals(-51L, $opt$IntToLong(-51)); + assertLongEquals(2147483647L, $opt$IntToLong(2147483647)); // 2^31 - 1 + assertLongEquals(-2147483647L, $opt$IntToLong(-2147483647)); // -(2^31 - 1) + assertLongEquals(-2147483648L, $opt$IntToLong(-2147483648)); // -(2^31) } private static void charToLong() { - assertEquals(1L, $opt$CharToLong((char)1)); - assertEquals(0L, $opt$CharToLong((char)0)); - assertEquals(51L, $opt$CharToLong((char)51)); - assertEquals(32767L, $opt$CharToLong((char)32767)); // (2^15) - 1 - assertEquals(65535L, $opt$CharToLong((char)65535)); // (2^16) - 1 - - assertEquals(0L, $opt$CharToLong('\u0000')); - assertEquals(65535L, $opt$CharToLong('\uFFFF')); // (2^16) - 1 - - assertEquals(65535L, $opt$CharToLong((char)-1)); - assertEquals(65485L, $opt$CharToLong((char)-51)); - assertEquals(32769L, $opt$CharToLong((char)-32767)); // -(2^15) - 1 - assertEquals(32768L, $opt$CharToLong((char)-32768)); // -(2^15) + assertLongEquals(1L, $opt$CharToLong((char)1)); + assertLongEquals(0L, $opt$CharToLong((char)0)); + assertLongEquals(51L, $opt$CharToLong((char)51)); + assertLongEquals(32767L, $opt$CharToLong((char)32767)); // 2^15 - 1 + assertLongEquals(65535L, $opt$CharToLong((char)65535)); // 2^16 - 1 + + assertLongEquals(0L, $opt$CharToLong('\u0000')); + assertLongEquals(65535L, $opt$CharToLong('\uFFFF')); // 2^16 - 1 + + assertLongEquals(65535L, $opt$CharToLong((char)-1)); + assertLongEquals(65485L, $opt$CharToLong((char)-51)); + assertLongEquals(32769L, $opt$CharToLong((char)-32767)); // -(2^15 - 1) + assertLongEquals(32768L, $opt$CharToLong((char)-32768)); // -(2^15) } - // All these methods produce an int-to-long Dex instruction. + private static void longToInt() { + assertIntEquals(1, $opt$LongToInt(1L)); + assertIntEquals(0, $opt$LongToInt(0L)); + assertIntEquals(-1, $opt$LongToInt(-1L)); + assertIntEquals(51, $opt$LongToInt(51L)); + assertIntEquals(-51, $opt$LongToInt(-51L)); + assertIntEquals(2147483647, $opt$LongToInt(2147483647L)); // 2^31 - 1 + assertIntEquals(-2147483647, $opt$LongToInt(-2147483647L)); // -(2^31 - 1) + assertIntEquals(-2147483648, $opt$LongToInt(-2147483648L)); // -(2^31) + assertIntEquals(-2147483648, $opt$LongToInt(2147483648L)); // (2^31) + assertIntEquals(2147483647, $opt$LongToInt(-2147483649L)); // -(2^31 + 1) + assertIntEquals(-1, $opt$LongToInt(9223372036854775807L)); // 2^63 - 1 + assertIntEquals(1, $opt$LongToInt(-9223372036854775807L)); // -(2^63 - 1) + assertIntEquals(0, $opt$LongToInt(-9223372036854775808L)); // -(2^63) + + assertIntEquals(42, $opt$LongLiteralToInt()); + + // Ensure long-to-int conversions truncates values as expected. + assertLongEquals(1L, $opt$IntToLong($opt$LongToInt(4294967297L))); // 2^32 + 1 + assertLongEquals(0L, $opt$IntToLong($opt$LongToInt(4294967296L))); // 2^32 + assertLongEquals(-1L, $opt$IntToLong($opt$LongToInt(4294967295L))); // 2^32 - 1 + assertLongEquals(0L, $opt$IntToLong($opt$LongToInt(0L))); + assertLongEquals(1L, $opt$IntToLong($opt$LongToInt(-4294967295L))); // -(2^32 - 1) + assertLongEquals(0L, $opt$IntToLong($opt$LongToInt(-4294967296L))); // -(2^32) + assertLongEquals(-1, $opt$IntToLong($opt$LongToInt(-4294967297L))); // -(2^32 + 1) + } + + // These methods produce int-to-long Dex instructions. static long $opt$ByteToLong(byte a) { return a; } static long $opt$ShortToLong(short a) { return a; } static long $opt$IntToLong(int a) { return a; } static long $opt$CharToLong(int a) { return a; } + + // These methods produce long-to-int Dex instructions. + static int $opt$LongToInt(long a){ return (int)a; } + static int $opt$LongLiteralToInt(){ return (int)42L; } } |