Fix 044-proxy. Implement proxy for now, working on x86 and ARM.

Already added a TODO to do the assembly code for x86 and ARM for proxy.
Use LLVM .ll for multi-architecture now.

Change-Id: Ibdeeee113dcf284592e9d7769d3044438cb1e453
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 50ed471..fb6cc19 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -27,6 +27,7 @@
 #include "object.h"
 #include "object_utils.h"
 #include "runtime_support_func.h"
+#include "runtime_support_llvm.h"
 #include "shadow_frame.h"
 #include "stl_util.h"
 #include "stringprintf.h"
@@ -2884,6 +2885,7 @@
   EmitLoadActualParameters(args, callee_method_idx, dec_insn,
                            arg_fmt, is_static);
 
+#if 0
   // Invoke callee
   EmitUpdateLineNumFromDexPC(dex_pc);
   llvm::Value* retval = irb_.CreateCall(code_addr, args);
@@ -2897,6 +2899,72 @@
   if (ret_shorty != 'V') {
     EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
   }
+#else
+  uint32_t callee_access_flags = is_static ? kAccStatic : 0;
+  UniquePtr<OatCompilationUnit> callee_oat_compilation_unit(
+    oat_compilation_unit_->GetCallee(callee_method_idx, callee_access_flags));
+
+  char ret_shorty = callee_oat_compilation_unit->GetShorty()[0];
+
+
+  EmitUpdateLineNumFromDexPC(dex_pc);
+
+
+  llvm::BasicBlock* block_normal = CreateBasicBlockWithDexPC(dex_pc, "normal");
+  llvm::BasicBlock* block_proxy_stub = CreateBasicBlockWithDexPC(dex_pc, "proxy");
+  llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+  llvm::Type* accurate_ret_type = irb_.getJType(ret_shorty, kAccurate);
+  llvm::Value* retval_addr = NULL;
+  if (ret_shorty != 'V') {
+    retval_addr = irb_.CreateAlloca(accurate_ret_type);
+  }
+
+
+  // TODO: Remove this after we solve the proxy trampoline calling convention problem.
+  llvm::Value* code_addr_int = irb_.CreatePtrToInt(code_addr, irb_.getPtrEquivIntTy());
+  llvm::Value* proxy_stub_int = irb_.getPtrEquivInt(special_stub::kProxyStub);
+  llvm::Value* is_proxy_stub = irb_.CreateICmpEQ(code_addr_int, proxy_stub_int);
+  irb_.CreateCondBr(is_proxy_stub, block_proxy_stub, block_normal);
+
+
+  irb_.SetInsertPoint(block_normal);
+  {
+    // Invoke callee
+    llvm::Value* result = irb_.CreateCall(code_addr, args);
+    if (ret_shorty != 'V') {
+      irb_.CreateStore(result, retval_addr);
+    }
+  }
+  irb_.CreateBr(block_continue);
+
+
+  irb_.SetInsertPoint(block_proxy_stub);
+  {
+    llvm::Value* temp_space_addr;
+    if (ret_shorty != 'V') {
+      temp_space_addr = irb_.CreateAlloca(irb_.getJValueTy());
+      args.push_back(temp_space_addr);
+    }
+    irb_.CreateCall(irb_.GetRuntime(ProxyInvokeHandler), args);
+    if (ret_shorty != 'V') {
+      llvm::Value* result_addr =
+          irb_.CreateBitCast(temp_space_addr, accurate_ret_type->getPointerTo());
+      llvm::Value* retval = irb_.CreateLoad(result_addr);
+      irb_.CreateStore(retval, retval_addr);
+    }
+  }
+  irb_.CreateBr(block_continue);
+
+
+  irb_.SetInsertPoint(block_continue);
+
+  if (ret_shorty != 'V') {
+    llvm::Value* retval = irb_.CreateLoad(retval_addr);
+    EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
+  }
+  EmitGuard_ExceptionLandingPad(dex_pc);
+#endif
 
   irb_.CreateBr(GetNextBasicBlock(dex_pc));
 }