Implement array-length instruction.

Change-Id: I722af27990fc5d179857e886d00dab11b2cd4ca8
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index e001f4a..c23e943 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -1243,9 +1243,33 @@
 }
 
 
+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_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();
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index edde6ff..a1f1802 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -294,10 +294,15 @@
                                              llvm::Value* rhs,
                                              FPArithmKind arithm);
 
+  llvm::Value* EmitLoadArrayLength(llvm::Value* array);
+
   void EmitGuard_DivZeroException(uint32_t dex_pc,
                                   llvm::Value* denominator,
                                   JType op_jty);
 
+  void EmitGuard_NullPointerException(uint32_t dex_pc,
+                                      llvm::Value* object);
+
   RegCategory GetInferredRegCategory(uint32_t dex_pc, uint16_t reg);