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;
#include "mirror/art_method.h"
#include "mirror/class.h"
#include "thread.h"
-#include "utils/assembler.h"
+#include "utils.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 {
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:
}
break;
- case Primitive::kPrimInt:
case Primitive::kPrimFloat:
case Primitive::kPrimDouble:
LOG(FATAL) << "Type conversion from " << input_type
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());
+ __ LoadImmediate(out.As<Register>(),
+ Low32Bits(in.GetConstant()->AsLongConstant()->GetValue()));
+ }
+ 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:
}
break;
- case Primitive::kPrimInt:
case Primitive::kPrimFloat:
case Primitive::kPrimDouble:
LOG(FATAL) << "Type conversion from " << input_type
#include "mirror/art_method.h"
#include "mirror/class.h"
#include "thread.h"
+#include "utils.h"
#include "utils/assembler.h"
#include "utils/stack_checks.h"
#include "utils/x86/assembler_x86.h"
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:
}
break;
- case Primitive::kPrimInt:
case Primitive::kPrimFloat:
case Primitive::kPrimDouble:
LOG(FATAL) << "Type conversion from " << input_type
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());
+ __ movl(out.As<Register>(),
+ Immediate(Low32Bits(in.GetConstant()->AsLongConstant()->GetValue())));
+ }
+ 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:
}
break;
- case Primitive::kPrimInt:
case Primitive::kPrimFloat:
case Primitive::kPrimDouble:
LOG(FATAL) << "Type conversion from " << input_type
#include "mirror/class.h"
#include "mirror/object_reference.h"
#include "thread.h"
+#include "utils.h"
#include "utils/assembler.h"
#include "utils/stack_checks.h"
#include "utils/x86_64/assembler_x86_64.h"
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:
}
break;
- case Primitive::kPrimInt:
case Primitive::kPrimFloat:
case Primitive::kPrimDouble:
LOG(FATAL) << "Type conversion from " << input_type
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());
+ __ movl(out.As<CpuRegister>(),
+ Immediate(Low32Bits(in.GetConstant()->AsLongConstant()->GetValue())));
+ }
+ 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());
}
break;
- case Primitive::kPrimInt:
case Primitive::kPrimFloat:
case Primitive::kPrimDouble:
LOG(FATAL) << "Type conversion from " << input_type
#undef NOT_LONG_TEST
+TEST(CodegenTest, IntToLongOfLongToInt) {
+ 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,
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
//
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)
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 {
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.
// 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);
}
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; }
}