diff options
| author | 2012-01-02 23:27:26 +0800 | |
|---|---|---|
| committer | 2012-02-16 23:42:39 -0800 | |
| commit | e27fdbb2c5b4a53b3c40570d861fd62d9fd3601c (patch) | |
| tree | df07318fb3778426dc227dbee1a631e93a736844 /src/compiler_llvm/method_compiler.cc | |
| parent | 61bb614526be29a99b31180c8ac8a695cd813d6c (diff) | |
Implement aget* instructions.
Change-Id: I1b03dd4ca4ab10b09adba4134c0d1198e43ef64f
Diffstat (limited to 'src/compiler_llvm/method_compiler.cc')
| -rw-r--r-- | src/compiler_llvm/method_compiler.cc | 66 |
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)); } |