Implement filled-new-array instruction.

Change-Id: I0cabb5e617f0d248a96ea318dd2ce91964a14cb6
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index f4a8a36..eaaac72 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -33,6 +33,8 @@
 #include <llvm/Analysis/Verifier.h>
 #include <llvm/BasicBlock.h>
 #include <llvm/Function.h>
+#include <llvm/GlobalVariable.h>
+#include <llvm/Intrinsics.h>
 
 namespace art {
 namespace compiler_llvm {
@@ -1593,7 +1595,66 @@
 void MethodCompiler::EmitInsn_FilledNewArray(uint32_t dex_pc,
                                              Instruction const* insn,
                                              bool is_range) {
-  // UNIMPLEMENTED(WARNING);
+
+  Instruction::DecodedInstruction dec_insn(insn);
+
+  llvm::Value* object_addr =
+    EmitAllocNewArray(dex_pc, dec_insn.vA_, dec_insn.vB_, true);
+
+  if (dec_insn.vA_ > 0) {
+    llvm::Value* object_addr_int =
+      irb_.CreatePtrToInt(object_addr, irb_.getPtrEquivIntTy());
+
+    llvm::Value* data_field_offset =
+      irb_.getPtrEquivInt(Array::DataOffset().Int32Value());
+
+    llvm::Value* data_field_addr_int =
+      irb_.CreateAdd(object_addr_int, data_field_offset);
+
+    Class* klass = method_->GetDexCacheResolvedTypes()->Get(dec_insn.vB_);
+    CHECK_NE(klass, static_cast<Class*>(NULL));
+    // Moved this below already: CHECK(!klass->IsPrimitive() || klass->IsPrimitiveInt());
+
+    llvm::Constant* word_size = irb_.getSizeOfPtrEquivIntValue();
+
+    llvm::Type* field_type;
+    if (klass->IsPrimitiveInt()) {
+      field_type = irb_.getJIntTy()->getPointerTo();
+    } else {
+      CHECK(!klass->IsPrimitive());
+      field_type = irb_.getJObjectTy()->getPointerTo();
+    }
+
+    // TODO: Tune this code.  Currently we are generating one instruction for
+    // one element which may be very space consuming.  Maybe changing to use
+    // memcpy may help; however, since we can't guarantee that the alloca of
+    // dalvik register are continuous, we can't perform such optimization yet.
+    for (uint32_t i = 0; i < dec_insn.vA_; ++i) {
+      llvm::Value* data_field_addr =
+        irb_.CreateIntToPtr(data_field_addr_int, field_type);
+
+      int reg_index;
+      if (is_range) {
+        reg_index = dec_insn.vC_ + i;
+      } else {
+        reg_index = dec_insn.arg_[i];
+      }
+
+      llvm::Value* reg_value;
+      if (klass->IsPrimitiveInt()) {
+        reg_value = EmitLoadDalvikReg(reg_index, kInt, kAccurate);
+      } else {
+        reg_value = EmitLoadDalvikReg(reg_index, kObject, kAccurate);
+      }
+
+      irb_.CreateStore(reg_value, data_field_addr);
+
+      data_field_addr_int = irb_.CreateAdd(data_field_addr_int, word_size);
+    }
+  }
+
+  EmitStoreDalvikRetValReg(kObject, kAccurate, object_addr);
+
   irb_.CreateBr(GetNextBasicBlock(dex_pc));
 }