summaryrefslogtreecommitdiffstats
path: root/compiler/utils
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2014-06-11 21:56:39 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2014-06-10 22:20:24 +0000
commit16e1eda5b1fcaf617371072692503714c7a6afe8 (patch)
tree70de80df0b476bdbd75d26f4624d631c1622f76f /compiler/utils
parentc879aaec949f429c9b029bbbfaa76be8872cef0a (diff)
parent5408b6ba5d73ac0890683ebd7ddb4151a8ac2721 (diff)
downloadart-16e1eda5b1fcaf617371072692503714c7a6afe8.zip
art-16e1eda5b1fcaf617371072692503714c7a6afe8.tar.gz
art-16e1eda5b1fcaf617371072692503714c7a6afe8.tar.bz2
Merge "x86_64: Fix issue in JNI compiler"
Diffstat (limited to 'compiler/utils')
-rw-r--r--compiler/utils/x86_64/assembler_x86_64.cc6
-rw-r--r--compiler/utils/x86_64/assembler_x86_64.h7
-rw-r--r--compiler/utils/x86_64/assembler_x86_64_test.cc118
3 files changed, 128 insertions, 3 deletions
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc
index a14551c..b07eed3 100644
--- a/compiler/utils/x86_64/assembler_x86_64.cc
+++ b/compiler/utils/x86_64/assembler_x86_64.cc
@@ -1650,7 +1650,7 @@ void X86_64Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
pushq(spill_regs.at(i).AsX86_64().AsCpuRegister());
}
// return address then method on stack
- addq(CpuRegister(RSP), Immediate(-frame_size + (spill_regs.size() * kFramePointerSize) +
+ addq(CpuRegister(RSP), Immediate(-static_cast<int64_t>(frame_size) + (spill_regs.size() * kFramePointerSize) +
sizeof(StackReference<mirror::ArtMethod>) /*method*/ +
kFramePointerSize /*return address*/));
@@ -1682,7 +1682,7 @@ void X86_64Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
void X86_64Assembler::RemoveFrame(size_t frame_size,
const std::vector<ManagedRegister>& spill_regs) {
CHECK_ALIGNED(frame_size, kStackAlignment);
- addq(CpuRegister(RSP), Immediate(frame_size - (spill_regs.size() * kFramePointerSize) - kFramePointerSize));
+ addq(CpuRegister(RSP), Immediate(static_cast<int64_t>(frame_size) - (spill_regs.size() * kFramePointerSize) - kFramePointerSize));
for (size_t i = 0; i < spill_regs.size(); ++i) {
popq(spill_regs.at(i).AsX86_64().AsCpuRegister());
}
@@ -1691,7 +1691,7 @@ void X86_64Assembler::RemoveFrame(size_t frame_size,
void X86_64Assembler::IncreaseFrameSize(size_t adjust) {
CHECK_ALIGNED(adjust, kStackAlignment);
- addq(CpuRegister(RSP), Immediate(-adjust));
+ addq(CpuRegister(RSP), Immediate(-static_cast<int64_t>(adjust)));
}
void X86_64Assembler::DecreaseFrameSize(size_t adjust) {
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index 548d379..6276603 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -29,6 +29,13 @@
namespace art {
namespace x86_64 {
+// Encodes an immediate value for operands.
+//
+// Note: Immediates can be 64b on x86-64 for certain instructions, but are often restricted
+// to 32b.
+//
+// Note: As we support cross-compilation, the value type must be int64_t. Please be aware of
+// conversion rules in expressions regarding negation, especially size_t on 32b.
class Immediate {
public:
explicit Immediate(int64_t value) : value_(value) {}
diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc
index 7201d04..799db9f 100644
--- a/compiler/utils/x86_64/assembler_x86_64_test.cc
+++ b/compiler/utils/x86_64/assembler_x86_64_test.cc
@@ -200,4 +200,122 @@ TEST_F(AssemblerX86_64Test, SetCC) {
DriverFn(&setcc_test_fn, "setcc");
}
+static x86_64::X86_64ManagedRegister ManagedFromCpu(x86_64::Register r) {
+ return x86_64::X86_64ManagedRegister::FromCpuRegister(r);
+}
+
+static x86_64::X86_64ManagedRegister ManagedFromFpu(x86_64::FloatRegister r) {
+ return x86_64::X86_64ManagedRegister::FromXmmRegister(r);
+}
+
+std::string buildframe_test_fn(x86_64::X86_64Assembler* assembler) {
+ // TODO: more interesting spill registers / entry spills.
+
+ // Two random spill regs.
+ std::vector<ManagedRegister> spill_regs;
+ spill_regs.push_back(ManagedFromCpu(x86_64::R10));
+ spill_regs.push_back(ManagedFromCpu(x86_64::RSI));
+
+ // Three random entry spills.
+ ManagedRegisterEntrySpills entry_spills;
+ ManagedRegisterSpill spill(ManagedFromCpu(x86_64::RAX), 8, 0);
+ entry_spills.push_back(spill);
+ ManagedRegisterSpill spill2(ManagedFromCpu(x86_64::RBX), 8, 8);
+ entry_spills.push_back(spill2);
+ ManagedRegisterSpill spill3(ManagedFromFpu(x86_64::XMM1), 8, 16);
+ entry_spills.push_back(spill3);
+
+ x86_64::X86_64ManagedRegister method_reg = ManagedFromCpu(x86_64::RDI);
+
+ size_t frame_size = 10 * kStackAlignment;
+ assembler->BuildFrame(10 * kStackAlignment, method_reg, spill_regs, entry_spills);
+
+ // Construct assembly text counterpart.
+ std::ostringstream str;
+ // 1) Push the spill_regs.
+ str << "pushq %rsi\n";
+ str << "pushq %r10\n";
+ // 2) Move down the stack pointer.
+ ssize_t displacement = -static_cast<ssize_t>(frame_size) + spill_regs.size() * 8 +
+ sizeof(StackReference<mirror::ArtMethod>) + 8;
+ str << "addq $" << displacement << ", %rsp\n";
+ // 3) Make space for method reference, and store it.
+ str << "subq $4, %rsp\n";
+ str << "movl %edi, (%rsp)\n";
+ // 4) Entry spills.
+ str << "movq %rax, " << frame_size + 0 << "(%rsp)\n";
+ str << "movq %rbx, " << frame_size + 8 << "(%rsp)\n";
+ str << "movsd %xmm1, " << frame_size + 16 << "(%rsp)\n";
+
+ return str.str();
+}
+
+TEST_F(AssemblerX86_64Test, BuildFrame) {
+ DriverFn(&buildframe_test_fn, "BuildFrame");
+}
+
+std::string removeframe_test_fn(x86_64::X86_64Assembler* assembler) {
+ // TODO: more interesting spill registers / entry spills.
+
+ // Two random spill regs.
+ std::vector<ManagedRegister> spill_regs;
+ spill_regs.push_back(ManagedFromCpu(x86_64::R10));
+ spill_regs.push_back(ManagedFromCpu(x86_64::RSI));
+
+ size_t frame_size = 10 * kStackAlignment;
+ assembler->RemoveFrame(10 * kStackAlignment, spill_regs);
+
+ // Construct assembly text counterpart.
+ std::ostringstream str;
+ // 1) Move up the stack pointer.
+ ssize_t displacement = static_cast<ssize_t>(frame_size) - spill_regs.size() * 8 - 8;
+ str << "addq $" << displacement << ", %rsp\n";
+ // 2) Pop spill regs.
+ str << "popq %r10\n";
+ str << "popq %rsi\n";
+ str << "ret\n";
+
+ return str.str();
+}
+
+TEST_F(AssemblerX86_64Test, RemoveFrame) {
+ DriverFn(&removeframe_test_fn, "RemoveFrame");
+}
+
+std::string increaseframe_test_fn(x86_64::X86_64Assembler* assembler) {
+ assembler->IncreaseFrameSize(0U);
+ assembler->IncreaseFrameSize(kStackAlignment);
+ assembler->IncreaseFrameSize(10 * kStackAlignment);
+
+ // Construct assembly text counterpart.
+ std::ostringstream str;
+ str << "addq $0, %rsp\n";
+ str << "addq $-" << kStackAlignment << ", %rsp\n";
+ str << "addq $-" << 10 * kStackAlignment << ", %rsp\n";
+
+ return str.str();
+}
+
+TEST_F(AssemblerX86_64Test, IncreaseFrame) {
+ DriverFn(&increaseframe_test_fn, "IncreaseFrame");
+}
+
+std::string decreaseframe_test_fn(x86_64::X86_64Assembler* assembler) {
+ assembler->DecreaseFrameSize(0U);
+ assembler->DecreaseFrameSize(kStackAlignment);
+ assembler->DecreaseFrameSize(10 * kStackAlignment);
+
+ // Construct assembly text counterpart.
+ std::ostringstream str;
+ str << "addq $0, %rsp\n";
+ str << "addq $" << kStackAlignment << ", %rsp\n";
+ str << "addq $" << 10 * kStackAlignment << ", %rsp\n";
+
+ return str.str();
+}
+
+TEST_F(AssemblerX86_64Test, DecreaseFrame) {
+ DriverFn(&decreaseframe_test_fn, "DecreaseFrame");
+}
+
} // namespace art