diff options
| author | 2012-02-03 15:34:53 +0800 | |
|---|---|---|
| committer | 2012-02-16 23:15:29 -0800 | |
| commit | 61bb614526be29a99b31180c8ac8a695cd813d6c (patch) | |
| tree | 5455f296095bafa06c0ddcf0604642f196c56597 /src/compiler_llvm/method_compiler.cc | |
| parent | 5b07ea25a064995d0acbb142a768baf356ba5fdf (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.cc | 46 |
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(); |