summaryrefslogtreecommitdiff
path: root/src/compiler_llvm/method_compiler.cc
diff options
context:
space:
mode:
author Logan Chien <loganchien@google.com> 2012-01-02 23:27:26 +0800
committer Shih-wei Liao <sliao@google.com> 2012-02-16 23:42:39 -0800
commite27fdbb2c5b4a53b3c40570d861fd62d9fd3601c (patch)
treedf07318fb3778426dc227dbee1a631e93a736844 /src/compiler_llvm/method_compiler.cc
parent61bb614526be29a99b31180c8ac8a695cd813d6c (diff)
Implement aget* instructions.
Change-Id: I1b03dd4ca4ab10b09adba4134c0d1198e43ef64f
Diffstat (limited to 'src/compiler_llvm/method_compiler.cc')
-rw-r--r--src/compiler_llvm/method_compiler.cc66
1 files changed, 65 insertions, 1 deletions
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index c23e943ffd..4864eb43b1 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -1592,10 +1592,74 @@ llvm::Value* MethodCompiler::EmitConditionResult(llvm::Value* lhs,
}
+void
+MethodCompiler::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
+ llvm::Value* array,
+ llvm::Value* index) {
+ llvm::Value* array_len = EmitLoadArrayLength(array);
+
+ llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
+
+ llvm::BasicBlock* block_exception =
+ CreateBasicBlockWithDexPC(dex_pc, "overflow");
+
+ llvm::BasicBlock* block_continue =
+ CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+ irb_.CreateCondBr(cmp, block_exception, block_continue);
+
+ irb_.SetInsertPoint(block_exception);
+ irb_.CreateCall2(irb_.GetRuntime(ThrowIndexOutOfBounds), index, array_len);
+ EmitBranchExceptionLandingPad(dex_pc);
+
+ irb_.SetInsertPoint(block_continue);
+}
+
+
+void MethodCompiler::EmitGuard_ArrayException(uint32_t dex_pc,
+ llvm::Value* array,
+ llvm::Value* index) {
+ EmitGuard_NullPointerException(dex_pc, array);
+ EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array, index);
+}
+
+
+// Emit Array GetElementPtr
+llvm::Value* MethodCompiler::EmitArrayGEP(llvm::Value* array_addr,
+ llvm::Value* index_value,
+ llvm::Type* elem_type) {
+
+ llvm::Constant* data_offset_value =
+ irb_.getPtrEquivInt(Array::DataOffset().Int32Value());
+
+ llvm::Value* array_data_addr =
+ irb_.CreatePtrDisp(array_addr, data_offset_value,
+ elem_type->getPointerTo());
+
+ return irb_.CreateGEP(array_data_addr, index_value);
+}
+
+
void MethodCompiler::EmitInsn_AGet(uint32_t dex_pc,
Instruction const* insn,
JType elem_jty) {
- // UNIMPLEMENTED(WARNING);
+
+ Instruction::DecodedInstruction dec_insn(insn);
+
+ llvm::Value* array_addr = EmitLoadDalvikReg(dec_insn.vB_, kObject, kAccurate);
+ llvm::Value* index_value = EmitLoadDalvikReg(dec_insn.vC_, kInt, kAccurate);
+
+ EmitGuard_ArrayException(dex_pc, array_addr, index_value);
+
+ llvm::Type* elem_type = irb_.getJType(elem_jty, kArray);
+
+ llvm::Value* array_elem_addr =
+ EmitArrayGEP(array_addr, index_value, elem_type);
+
+ llvm::Value* array_elem_value = irb_.CreateLoad(array_elem_addr);
+
+ EmitStoreDalvikReg(dec_insn.vA_, elem_jty, kArray, array_elem_value);
+
irb_.CreateBr(GetNextBasicBlock(dex_pc));
}