summaryrefslogtreecommitdiff
path: root/src/compiler_llvm/method_compiler.cc
diff options
context:
space:
mode:
author Logan Chien <loganchien@google.com> 2012-02-03 15:34:53 +0800
committer Shih-wei Liao <sliao@google.com> 2012-02-16 23:15:29 -0800
commit61bb614526be29a99b31180c8ac8a695cd813d6c (patch)
tree5455f296095bafa06c0ddcf0604642f196c56597 /src/compiler_llvm/method_compiler.cc
parent5b07ea25a064995d0acbb142a768baf356ba5fdf (diff)
Implement array-length instruction.
Change-Id: I722af27990fc5d179857e886d00dab11b2cd4ca8
Diffstat (limited to 'src/compiler_llvm/method_compiler.cc')
-rw-r--r--src/compiler_llvm/method_compiler.cc46
1 files changed, 45 insertions, 1 deletions
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index e001f4a0f6..c23e943ffd 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -1243,9 +1243,33 @@ void MethodCompiler::EmitInsn_InstanceOf(uint32_t dex_pc,
}
+llvm::Value* MethodCompiler::EmitLoadArrayLength(llvm::Value* array) {
+ // Load array length field address
+ llvm::Constant* array_len_field_offset =
+ irb_.getPtrEquivInt(Array::LengthOffset().Int32Value());
+
+ llvm::Value* array_len_field_addr =
+ irb_.CreatePtrDisp(array, array_len_field_offset,
+ irb_.getJIntTy()->getPointerTo());
+
+ // Load array length
+ return irb_.CreateLoad(array_len_field_addr);
+}
+
+
void MethodCompiler::EmitInsn_ArrayLength(uint32_t dex_pc,
Instruction const* insn) {
- // UNIMPLEMENTED(WARNING);
+
+ Instruction::DecodedInstruction dec_insn(insn);
+
+ // Get the array object address
+ llvm::Value* array_addr = EmitLoadDalvikReg(dec_insn.vB_, kObject, kAccurate);
+ EmitGuard_NullPointerException(dex_pc, array_addr);
+
+ // Get the array length and store it to the register
+ llvm::Value* array_len = EmitLoadArrayLength(array_addr);
+ EmitStoreDalvikReg(dec_insn.vA_, kInt, kAccurate, array_len);
+
irb_.CreateBr(GetNextBasicBlock(dex_pc));
}
@@ -2042,6 +2066,26 @@ void MethodCompiler::EmitGuard_DivZeroException(uint32_t dex_pc,
}
+void MethodCompiler::EmitGuard_NullPointerException(uint32_t dex_pc,
+ llvm::Value* object) {
+ llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.getJNull());
+
+ llvm::BasicBlock* block_exception =
+ CreateBasicBlockWithDexPC(dex_pc, "nullp");
+
+ llvm::BasicBlock* block_continue =
+ CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+ irb_.CreateCondBr(equal_null, block_exception, block_continue);
+
+ irb_.SetInsertPoint(block_exception);
+ irb_.CreateCall(irb_.GetRuntime(ThrowNullPointerException));
+ EmitBranchExceptionLandingPad(dex_pc);
+
+ irb_.SetInsertPoint(block_continue);
+}
+
+
CompiledMethod *MethodCompiler::Compile() {
// Code generation
CreateFunction();