Implement CheckPutArrayElement.

Change-Id: Ie9617df1debb57c80b937bc033ff231c4daedd0d
diff --git a/src/compiler_llvm/art_module.ll b/src/compiler_llvm/art_module.ll
index b85ba7c..d18080f 100644
--- a/src/compiler_llvm/art_module.ll
+++ b/src/compiler_llvm/art_module.ll
@@ -135,8 +135,9 @@
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-; RTTI
+; Type Checking, in the nature of casting
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 declare i32 @art_is_assignable_from_code(%JavaObject*, %JavaObject*)
 declare void @art_check_cast_from_code(%JavaObject*, %JavaObject*)
+declare void @art_check_put_array_element_from_code(%JavaObject*, %JavaObject*)
diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc
index 973ef06..07fc6a3 100644
--- a/src/compiler_llvm/generated/art_module.cc
+++ b/src/compiler_llvm/generated/art_module.cc
@@ -773,6 +773,17 @@
 AttrListPtr func_art_check_cast_from_code_PAL;
 func_art_check_cast_from_code->setAttributes(func_art_check_cast_from_code_PAL);
 
+Function* func_art_check_put_array_element_from_code = mod->getFunction("art_check_put_array_element_from_code");
+if (!func_art_check_put_array_element_from_code) {
+func_art_check_put_array_element_from_code = Function::Create(
+ /*Type=*/FuncTy_27,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_check_put_array_element_from_code", mod); // (external, no body)
+func_art_check_put_array_element_from_code->setCallingConv(CallingConv::C);
+}
+AttrListPtr func_art_check_put_array_element_from_code_PAL;
+func_art_check_put_array_element_from_code->setAttributes(func_art_check_put_array_element_from_code_PAL);
+
 // Global Variable Declarations
 
 
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index bcd40de..8b1cef6 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -2328,6 +2328,14 @@
 
   llvm::Value* new_value = EmitLoadDalvikReg(dec_insn.vA, elem_jty, kArray);
 
+  if (elem_jty == kObject) { // If put an object, check the type.
+    llvm::Function* runtime_func = irb_.GetRuntime(CheckPutArrayElement);
+
+    irb_.CreateCall2(runtime_func, new_value, array_addr);
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+  }
+
   irb_.CreateStore(new_value, array_elem_addr);
 
   irb_.CreateBr(GetNextBasicBlock(dex_pc));
diff --git a/src/compiler_llvm/runtime_support_func_list.h b/src/compiler_llvm/runtime_support_func_list.h
index 1c21d48..518a175 100644
--- a/src/compiler_llvm/runtime_support_func_list.h
+++ b/src/compiler_llvm/runtime_support_func_list.h
@@ -31,6 +31,7 @@
   V(InitializeType, art_initialize_type_from_code) \
   V(IsAssignable, art_is_assignable_from_code) \
   V(CheckCast, art_check_cast_from_code) \
+  V(CheckPutArrayElement, art_check_put_array_element_from_code) \
   V(AllocObject, art_alloc_object_from_code) \
   V(AllocObjectWithAccessCheck, art_alloc_object_from_code_with_access_check) \
   V(AllocArray, art_alloc_array_from_code) \
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index 6ad80f8..ff31825 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -39,7 +39,7 @@
 
 void art_set_current_thread_from_code(void* thread_object_addr) {
   // TODO: LLVM IR generating something like "r9 = thread_object_addr"
-  UNIMPLEMENTED(WARNING);
+  // UNIMPLEMENTED(WARNING);
 }
 
 void art_lock_object_from_code(Object* obj) {
@@ -438,7 +438,7 @@
 }
 
 void art_check_cast_from_code(const Class* dest_type, const Class* src_type) {
-DCHECK(dest_type->IsClass()) << PrettyClass(dest_type);
+  DCHECK(dest_type->IsClass()) << PrettyClass(dest_type);
   DCHECK(src_type->IsClass()) << PrettyClass(src_type);
   if (UNLIKELY(!dest_type->IsAssignableFrom(src_type))) {
     Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
@@ -448,6 +448,24 @@
   }
 }
 
+void art_check_put_array_element_from_code(const Object* element, const Object* array) {
+  if (element == NULL) {
+    return;
+  }
+  DCHECK(array != NULL);
+  Class* array_class = array->GetClass();
+  DCHECK(array_class != NULL);
+  Class* component_type = array_class->GetComponentType();
+  Class* element_class = element->GetClass();
+  if (UNLIKELY(!component_type->IsAssignableFrom(element_class))) {
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
+        "%s cannot be stored in an array of type %s",
+        PrettyDescriptor(element_class).c_str(),
+        PrettyDescriptor(array_class).c_str());
+  }
+  return;
+}
+
 //----------------------------------------------------------------------------
 // Runtime Support Function Lookup Callback
 //----------------------------------------------------------------------------