Fix GEP & refactor compiler_llvm::JniCompiler.

Three major changes:

   o Use member offset instead of hard coded constant.
     We use GetElementPtr before, but it needs the ordinal number of
     field. If we reorder the members, we need to correct all the
     constants.

   o Remove the type parameter in the StoreToObjectOffset().
     LLVM IR is strongly typed, we can get the type by the new_value.

   o Add more comments.

Change-Id: I133ac3d96e2f6482af09ef32b86cc7591b161163
diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc
index ad730dc..255e99a 100644
--- a/src/compiler_llvm/jni_compiler.cc
+++ b/src/compiler_llvm/jni_compiler.cc
@@ -27,6 +27,7 @@
 #include "object.h"
 #include "runtime.h"
 #include "runtime_support_func.h"
+#include "shadow_frame.h"
 #include "utils_llvm.h"
 
 #include <llvm/Analysis/Verifier.h>
@@ -90,6 +91,7 @@
   // Start to build IR
   irb_.SetInsertPoint(basic_block_);
 
+  // Get thread object
   llvm::Value* thread_object_addr =
     irb_.CreateCall(irb_.GetRuntime(runtime_support::GetCurrentThread));
 
@@ -100,35 +102,28 @@
   // Zero-initialization of the shadow frame
   llvm::ConstantAggregateZero* zero_initializer =
     llvm::ConstantAggregateZero::get(shadow_frame_type);
-
   irb_.CreateStore(zero_initializer, shadow_frame_);
 
-  // Variables for GetElementPtr
-  llvm::Constant* zero = irb_.getInt32(0);
-  llvm::Value* gep_index[] = {
-    zero, // No displacement for shadow frame pointer
-    zero, // Get the %ArtFrame data structure
-    NULL,
-  };
-
   // Store the method pointer
-  gep_index[2] = irb_.getInt32(2);
-  llvm::Value* method_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
+  llvm::Value* method_field_addr =
+    irb_.CreatePtrDisp(shadow_frame_,
+                       irb_.getPtrEquivInt(ShadowFrame::MethodOffset()),
+                       irb_.getJObjectTy()->getPointerTo());
   irb_.CreateStore(method_object_addr, method_field_addr);
 
   // Store the number of the pointer slots
-  gep_index[2] = irb_.getInt32(0);
-  llvm::Value* size_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
-  llvm::ConstantInt* sirt_size_value = irb_.getInt32(sirt_size);
-  irb_.CreateStore(sirt_size_value, size_field_addr);
+  StoreToObjectOffset(shadow_frame_,
+                      ShadowFrame::NumberOfReferencesOffset(),
+                      irb_.getInt32(sirt_size));
 
   // Push the shadow frame
   llvm::Value* shadow_frame_upcast = irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
   irb_.CreateCall(irb_.GetRuntime(runtime_support::PushShadowFrame), shadow_frame_upcast);
 
   // Set top of managed stack to the method field in the SIRT
-  StoreToObjectOffset(thread_object_addr, Thread::TopOfManagedStackOffset().Int32Value(),
-                      method_field_addr->getType(), method_field_addr);
+  StoreToObjectOffset(thread_object_addr,
+                      Thread::TopOfManagedStackOffset().Int32Value(),
+                      method_field_addr);
 
   // Get JNIEnv
   llvm::Value* jni_env_object_addr = LoadFromObjectOffset(thread_object_addr,
@@ -136,8 +131,9 @@
                                                           irb_.getJObjectTy());
 
   // Set thread state to kNative
-  StoreToObjectOffset(thread_object_addr, Thread::StateOffset().Int32Value(),
-                      irb_.getInt32Ty(), irb_.getInt32(Thread::kNative));
+  StoreToObjectOffset(thread_object_addr,
+                      Thread::StateOffset().Int32Value(),
+                      irb_.getInt32(Thread::kNative));
 
   // Get callee code_addr
   llvm::Value* code_addr =
@@ -149,26 +145,35 @@
   // Load actual parameters
   std::vector<llvm::Value*> args;
 
+  // The 1st parameter: JNIEnv*
   args.push_back(jni_env_object_addr);
-  //args.push_back(method_object_addr); // method object for callee
 
-  // Store arguments to SIRT, and push back to args
-  gep_index[1] = irb_.getInt32(1); // SIRT
+  // Variables for GetElementPtr
+  llvm::Value* gep_index[] = {
+    irb_.getInt32(0), // No displacement for shadow frame pointer
+    irb_.getInt32(1), // SIRT
+    NULL,
+  };
+
   size_t sirt_member_index = 0;
 
   // Push class argument if this method is static
   if (is_static) {
+    // Load class object
     llvm::Value* class_object_addr =
         LoadFromObjectOffset(method_object_addr,
                              Method::DeclaringClassOffset().Int32Value(),
                              irb_.getJObjectTy());
     gep_index[2] = irb_.getInt32(sirt_member_index++);
+    // Store the class argument to SIRT
     llvm::Value* sirt_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
     irb_.CreateStore(class_object_addr, sirt_field_addr);
     args.push_back(irb_.CreateBitCast(sirt_field_addr, irb_.getJObjectTy()));
   }
+  // Store arguments to SIRT, and push back to args
   for (arg_iter = arg_begin; arg_iter != arg_end; ++arg_iter) {
     if (arg_iter->getType() == irb_.getJObjectTy()) {
+      // Store the reference type arguments to SIRT
       gep_index[2] = irb_.getInt32(sirt_member_index++);
       llvm::Value* sirt_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
       irb_.CreateStore(arg_iter, sirt_field_addr);
@@ -199,7 +204,6 @@
                            irb_.getInt32Ty());
   StoreToObjectOffset(jni_env_object_addr,
                       JNIEnvExt::LocalRefCookieOffset().Int32Value(),
-                      irb_.getInt32Ty(),
                       segment_state);
 
 
@@ -208,8 +212,9 @@
 
 
   // Set thread state to kRunnable
-  StoreToObjectOffset(thread_object_addr, Thread::StateOffset().Int32Value(),
-                      irb_.getInt32Ty(), irb_.getInt32(Thread::kRunnable));
+  StoreToObjectOffset(thread_object_addr,
+                      Thread::StateOffset().Int32Value(),
+                      irb_.getInt32(Thread::kRunnable));
 
   // Get return shorty
   DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx_);
@@ -220,7 +225,8 @@
   if (ret_shorty == 'L') {
     // If the return value is reference, it may point to SIRT, we should decode it.
     retval = irb_.CreateCall2(irb_.GetRuntime(runtime_support::DecodeJObjectInThread),
-                              thread_object_addr, retval);
+                              thread_object_addr,
+                              retval);
   }
 
   // env->locals.segment_state = env->local_ref_cookie
@@ -230,12 +236,12 @@
                            irb_.getInt32Ty());
   StoreToObjectOffset(jni_env_object_addr,
                       JNIEnvExt::SegmentStateOffset().Int32Value(),
-                      irb_.getInt32Ty(),
                       local_ref_cookie);
 
   // env->local_ref_cookie = saved_local_ref_cookie
-  StoreToObjectOffset(jni_env_object_addr, JNIEnvExt::LocalRefCookieOffset().Int32Value(),
-                      irb_.getInt32Ty(), saved_local_ref_cookie);
+  StoreToObjectOffset(jni_env_object_addr,
+                      JNIEnvExt::LocalRefCookieOffset().Int32Value(),
+                      saved_local_ref_cookie);
 
   // Pop the shadow frame
   irb_.CreateCall(irb_.GetRuntime(runtime_support::PopShadowFrame));
@@ -305,7 +311,8 @@
   return llvm::FunctionType::get(ret_type, args_type, false);
 }
 
-llvm::Value* JniCompiler::LoadFromObjectOffset(llvm::Value* object_addr, int32_t offset,
+llvm::Value* JniCompiler::LoadFromObjectOffset(llvm::Value* object_addr,
+                                               int32_t offset,
                                                llvm::Type* type) {
   // Convert offset to llvm::value
   llvm::Value* llvm_offset = irb_.getPtrEquivInt(offset);
@@ -315,14 +322,17 @@
   return irb_.CreateLoad(value_addr);
 }
 
-void JniCompiler::StoreToObjectOffset(llvm::Value* object_addr, int32_t offset,
-                                      llvm::Type* type, llvm::Value* value) {
+void JniCompiler::StoreToObjectOffset(llvm::Value* object_addr,
+                                      int32_t offset,
+                                      llvm::Value* new_value) {
   // Convert offset to llvm::value
   llvm::Value* llvm_offset = irb_.getPtrEquivInt(offset);
   // Calculate the value's address
-  llvm::Value* value_addr = irb_.CreatePtrDisp(object_addr, llvm_offset, type->getPointerTo());
+  llvm::Value* value_addr = irb_.CreatePtrDisp(object_addr,
+                                               llvm_offset,
+                                               new_value->getType()->getPointerTo());
   // Store
-  irb_.CreateStore(value, value_addr);
+  irb_.CreateStore(new_value, value_addr);
 }
 
 } // namespace compiler_llvm
diff --git a/src/compiler_llvm/jni_compiler.h b/src/compiler_llvm/jni_compiler.h
index 98129d1..a6ddce3 100644
--- a/src/compiler_llvm/jni_compiler.h
+++ b/src/compiler_llvm/jni_compiler.h
@@ -66,8 +66,7 @@
  private:
   llvm::Value* LoadFromObjectOffset(llvm::Value* object_addr, int32_t offset, llvm::Type* type);
 
-  void StoreToObjectOffset(llvm::Value* object_addr, int32_t offset,
-                           llvm::Type* type, llvm::Value* value);
+  void StoreToObjectOffset(llvm::Value* object_addr, int32_t offset, llvm::Value* new_value);
 
   CompilationUnit* cunit_;
   Compiler const* compiler_;