Simple debugging support for portable path.

Change-Id: Ibdc33b8d7f644c091fdb3ba3ce2ba45804bc4078
diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc
index f3ebf09..1e81458 100644
--- a/src/compiler/codegen/MethodBitcode.cc
+++ b/src/compiler/codegen/MethodBitcode.cc
@@ -61,6 +61,17 @@
   llvm::Instruction* inst = llvm::dyn_cast<llvm::Instruction>(placeholder);
   DCHECK(inst != NULL);
   inst->eraseFromParent();
+
+  // Set vreg for debugging
+  if (!cUnit->compiler->IsDebuggingSupported()) {
+    greenland::IntrinsicHelper::IntrinsicId id =
+        greenland::IntrinsicHelper::SetVReg;
+    llvm::Function* func = cUnit->intrinsic_helper->GetIntrinsicFunction(id);
+    int vReg = SRegToVReg(cUnit, sReg);
+    llvm::Value* tableSlot = cUnit->irb->getInt32(vReg);
+    llvm::Value* args[] = { tableSlot, val };
+    cUnit->irb->CreateCall(func, args);
+  }
 }
 
 llvm::Type* llvmTypeFromLocRec(CompilationUnit* cUnit, RegLocation loc)
@@ -1837,7 +1848,9 @@
             greenland::IntrinsicHelper::AllocaShadowFrame;
     llvm::Function* func = cUnit->intrinsic_helper->GetIntrinsicFunction(id);
     llvm::Value* entries = cUnit->irb->getInt32(cUnit->numShadowFrameEntries);
-    cUnit->irb->CreateCall(func, entries);
+    llvm::Value* dalvikRegs = cUnit->irb->getInt32(cUnit->numDalvikRegisters);
+    llvm::Value* args[] = { entries, dalvikRegs };
+    cUnit->irb->CreateCall(func, args);
   } else if (bb->blockType == kExitBlock) {
     /*
      * Because of the differences between how MIR/LIR and llvm handle exit
@@ -2998,6 +3011,7 @@
               case greenland::IntrinsicHelper::AllocaShadowFrame:
               case greenland::IntrinsicHelper::SetShadowFrameEntry:
               case greenland::IntrinsicHelper::PopShadowFrame:
+              case greenland::IntrinsicHelper::SetVReg:
                 // Ignore shadow frame stuff for quick compiler
                 break;
               case greenland::IntrinsicHelper::CopyInt:
diff --git a/src/compiler_llvm/art_module.ll b/src/compiler_llvm/art_module.ll
index 3c3c90b..1c04dc8 100644
--- a/src/compiler_llvm/art_module.ll
+++ b/src/compiler_llvm/art_module.ll
@@ -26,6 +26,7 @@
                     , i32                  ; Line number for stack backtrace
                     , i32                  ; Number of references
                     ; [0 x %JavaObject*]   ; References
+                    ; [0 x i32]            ; VRegs
                     }
 
 declare void @__art_type_list(%JavaObject*, %ShadowFrame*)
diff --git a/src/compiler_llvm/dalvik_reg.cc b/src/compiler_llvm/dalvik_reg.cc
index c3263ae..dc73e75 100644
--- a/src/compiler_llvm/dalvik_reg.cc
+++ b/src/compiler_llvm/dalvik_reg.cc
@@ -27,9 +27,9 @@
 // Dalvik Register
 //----------------------------------------------------------------------------
 
-DalvikReg::DalvikReg(MethodCompiler& method_compiler, const std::string& name)
+DalvikReg::DalvikReg(MethodCompiler& method_compiler, const std::string& name, llvm::Value* vreg)
 : method_compiler_(&method_compiler), irb_(method_compiler.GetIRBuilder()),
-  reg_name_(name), reg_32_(NULL), reg_64_(NULL), reg_obj_(NULL) {
+  reg_name_(name), reg_32_(NULL), reg_64_(NULL), reg_obj_(NULL), vreg_(vreg) {
 }
 
 
@@ -118,10 +118,6 @@
       return NULL;
     }
     break;
-
-  default:
-    LOG(FATAL) << "Couldn't GetValue of JType " << jty;
-    return NULL;
   }
 
   if (jty == kFloat || jty == kDouble) {
@@ -141,13 +137,13 @@
   switch (space) {
   case kReg:
   case kField:
-    irb_.CreateStore(value, GetAddr(jty), kTBAARegister);
-    return;
+    break;
 
   case kAccurate:
   case kArray:
     switch (jty) {
     case kVoid:
+      LOG(FATAL) << "Dalvik register with void type has no value";
       break;
 
     case kBoolean:
@@ -155,7 +151,7 @@
       // NOTE: In accurate type space, we have to zero extend boolean from
       // i1 to i32, and char from i16 to i32.  In array type space, we have
       // to zero extend boolean from i8 to i32, and char from i16 to i32.
-      irb_.CreateStore(RegCat1ZExt(value), GetAddr(jty), kTBAARegister);
+      value = RegCat1ZExt(value);
       break;
 
     case kByte:
@@ -163,7 +159,7 @@
       // NOTE: In accurate type space, we have to signed extend byte from
       // i8 to i32, and short from i16 to i32.  In array type space, we have
       // to sign extend byte from i8 to i32, and short from i16 to i32.
-      irb_.CreateStore(RegCat1SExt(value), GetAddr(jty), kTBAARegister);
+      value = RegCat1SExt(value);
       break;
 
     case kInt:
@@ -171,13 +167,19 @@
     case kFloat:
     case kDouble:
     case kObject:
-      irb_.CreateStore(value, GetAddr(jty), kTBAARegister);
       break;
 
     default:
       LOG(FATAL) << "Unknown java type: " << jty;
     }
   }
+
+  irb_.CreateStore(value, GetAddr(jty), kTBAARegister);
+  if (vreg_ != NULL) {
+    irb_.CreateStore(value,
+                     irb_.CreateBitCast(vreg_, value->getType()->getPointerTo()),
+                     kTBAAShadowFrame);
+  }
 }
 
 
diff --git a/src/compiler_llvm/dalvik_reg.h b/src/compiler_llvm/dalvik_reg.h
index f950771..ac0f421 100644
--- a/src/compiler_llvm/dalvik_reg.h
+++ b/src/compiler_llvm/dalvik_reg.h
@@ -39,7 +39,7 @@
 
   static char GetRegCategoryNamePrefix(RegCategory reg_cat);
 
-  DalvikReg(MethodCompiler& method_compiler, const std::string& name);
+  DalvikReg(MethodCompiler& method_compiler, const std::string& name, llvm::Value* vreg);
 
   ~DalvikReg();
 
@@ -70,6 +70,7 @@
   llvm::Value* reg_32_;
   llvm::Value* reg_64_;
   llvm::Value* reg_obj_;
+  llvm::Value* vreg_;
 };
 
 } // namespace compiler_llvm
diff --git a/src/compiler_llvm/gbc_expander.cc b/src/compiler_llvm/gbc_expander.cc
index 18cef41..c094397 100644
--- a/src/compiler_llvm/gbc_expander.cc
+++ b/src/compiler_llvm/gbc_expander.cc
@@ -60,7 +60,6 @@
  private:
   llvm::AllocaInst* shadow_frame_;
   llvm::Value* old_shadow_frame_;
-  uint16_t num_shadow_frame_refs_;
 
  private:
   art::Compiler* compiler_;
@@ -217,10 +216,12 @@
 
   llvm::Value* Expand_DivRem(llvm::CallInst& call_inst, bool is_div, JType op_jty);
 
-  void Expand_AllocaShadowFrame(llvm::Value* num_entry_value);
+  void Expand_AllocaShadowFrame(llvm::Value* num_entry_value, llvm::Value* num_vregs_value);
 
   void Expand_SetShadowFrameEntry(llvm::Value* obj, llvm::Value* entry_idx);
 
+  void Expand_SetVReg(llvm::Value* entry_idx, llvm::Value* obj);
+
   void Expand_PopShadowFrame();
 
   void Expand_UpdateDexPC(llvm::Value* dex_pc_value);
@@ -326,7 +327,7 @@
   GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb)
       : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
         context_(irb.getContext()), rtb_(irb.Runtime()),
-        shadow_frame_(NULL), old_shadow_frame_(NULL), num_shadow_frame_refs_(0),
+        shadow_frame_(NULL), old_shadow_frame_(NULL),
         compiler_(NULL), dex_file_(NULL), code_item_(NULL),
         oat_compilation_unit_(NULL), method_idx_(-1u), func_(NULL),
         changed_(false)
@@ -336,7 +337,7 @@
                   art::Compiler* compiler, art::OatCompilationUnit* oat_compilation_unit)
       : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
         context_(irb.getContext()), rtb_(irb.Runtime()),
-        shadow_frame_(NULL), old_shadow_frame_(NULL), num_shadow_frame_refs_(0),
+        shadow_frame_(NULL), old_shadow_frame_(NULL),
         compiler_(compiler),
         dex_file_(oat_compilation_unit->GetDexFile()),
         code_item_(oat_compilation_unit->GetCodeItem()),
@@ -366,7 +367,6 @@
   // Setup rewrite context
   shadow_frame_ = NULL;
   old_shadow_frame_ = NULL;
-  num_shadow_frame_refs_ = 0;
   func_ = &func;
   changed_ = false; // Assume unchanged
 
@@ -1092,14 +1092,17 @@
   return result;
 }
 
-void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_entry_value) {
+void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_entry_value,
+                                               llvm::Value* num_vregs_value) {
   // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
   // MethodCompiler::EmitPushShadowFrame
-  num_shadow_frame_refs_ =
+  uint16_t num_shadow_frame_refs =
     llvm::cast<llvm::ConstantInt>(num_entry_value)->getZExtValue();
+  uint16_t num_vregs =
+    llvm::cast<llvm::ConstantInt>(num_vregs_value)->getZExtValue();
 
   llvm::StructType* shadow_frame_type =
-    irb_.getShadowFrameTy(num_shadow_frame_refs_);
+    irb_.getShadowFrameTy(num_shadow_frame_refs, num_vregs);
 
   shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
 
@@ -1126,14 +1129,15 @@
 
   llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
                                                  method_object_addr,
-                                                 num_shadow_frame_refs_,
-                                                 0);
+                                                 num_shadow_frame_refs,
+                                                 num_vregs);
 
   irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
 
   return;
 }
 
+// TODO: We will remove ShadowFrameEntry later, so I just copy/paste from ShadowFrameEntry.
 void GBCExpanderPass::Expand_SetShadowFrameEntry(llvm::Value* obj,
                                                  llvm::Value* entry_idx) {
   DCHECK(shadow_frame_ != NULL);
@@ -1154,6 +1158,24 @@
   return;
 }
 
+void GBCExpanderPass::Expand_SetVReg(llvm::Value* entry_idx,
+                                     llvm::Value* value) {
+  DCHECK(shadow_frame_ != NULL);
+
+  llvm::Value* gep_index[] = {
+    irb_.getInt32(0), // No pointer displacement
+    irb_.getInt32(2), // VRegs
+    entry_idx // Pointer field
+  };
+
+  llvm::Value* vreg_addr = irb_.CreateGEP(shadow_frame_, gep_index);
+
+  irb_.CreateStore(value,
+                   irb_.CreateBitCast(vreg_addr, value->getType()->getPointerTo()),
+                   kTBAAShadowFrame);
+  return;
+}
+
 void GBCExpanderPass::Expand_PopShadowFrame() {
 #if defined(ART_USE_PORTABLE_COMPILER)
   if (old_shadow_frame_ == NULL) {
@@ -3455,7 +3477,8 @@
 
     //==- Shadow Frame -----------------------------------------------------==//
     case IntrinsicHelper::AllocaShadowFrame: {
-      Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
+      Expand_AllocaShadowFrame(call_inst.getArgOperand(0),
+                               call_inst.getArgOperand(1));
       return NULL;
     }
     case IntrinsicHelper::SetShadowFrameEntry: {
@@ -3463,6 +3486,11 @@
                                  call_inst.getArgOperand(1));
       return NULL;
     }
+    case IntrinsicHelper::SetVReg: {
+      Expand_SetVReg(call_inst.getArgOperand(0),
+                     call_inst.getArgOperand(1));
+      return NULL;
+    }
     case IntrinsicHelper::PopShadowFrame: {
       Expand_PopShadowFrame();
       return NULL;
diff --git a/src/compiler_llvm/ir_builder.cc b/src/compiler_llvm/ir_builder.cc
index 8ee4f3e..b271002 100644
--- a/src/compiler_llvm/ir_builder.cc
+++ b/src/compiler_llvm/ir_builder.cc
@@ -151,8 +151,8 @@
 }
 
 
-llvm::StructType* IRBuilder::getShadowFrameTy(uint32_t sirt_size) {
-  std::string name(StringPrintf("ShadowFrame%u", sirt_size));
+llvm::StructType* IRBuilder::getShadowFrameTy(uint32_t sirt_size, uint32_t vreg_size) {
+  std::string name(StringPrintf("ShadowFrame%u_vreg%u", sirt_size, vreg_size));
 
   // Try to find the existing struct type definition
   if (llvm::Type* type = module_->getTypeByName(name)) {
@@ -164,6 +164,7 @@
   llvm::Type* elem_types[] = {
     art_frame_type_,
     llvm::ArrayType::get(jobject_type_, sirt_size),
+    llvm::ArrayType::get(getInt32Ty(), vreg_size),
   };
 
   return llvm::StructType::create(elem_types, name);
diff --git a/src/compiler_llvm/ir_builder.h b/src/compiler_llvm/ir_builder.h
index 5df9831..cc0bc8e 100644
--- a/src/compiler_llvm/ir_builder.h
+++ b/src/compiler_llvm/ir_builder.h
@@ -315,7 +315,7 @@
     return getJLongTy();
   }
 
-  llvm::StructType* getShadowFrameTy(uint32_t sirt_size);
+  llvm::StructType* getShadowFrameTy(uint32_t sirt_size, uint32_t vreg_size);
 
 
   //--------------------------------------------------------------------------
diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc
index 7001ec3..d5a7869 100644
--- a/src/compiler_llvm/jni_compiler.cc
+++ b/src/compiler_llvm/jni_compiler.cc
@@ -101,7 +101,7 @@
   }
 
   // Shadow stack
-  llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(sirt_size);
+  llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(sirt_size, 0);
   llvm::AllocaInst* shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
 
   // Store the dex pc
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index fea0c72..f09553c 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -175,7 +175,7 @@
 #if !defined(NDEBUG)
     name = StringPrintf("%u", r);
 #endif
-    regs_[r] = new DalvikReg(*this, name);
+    regs_[r] = new DalvikReg(*this, name, GetVRegEntry(r));
 
     // Cache shadow frame entry address
     shadow_frame_entries_[r] = GetShadowFrameEntry(r);
@@ -185,7 +185,7 @@
 #if !defined(NDEBUG)
   name = "_res";
 #endif
-  retval_reg_.reset(new DalvikReg(*this, name));
+  retval_reg_.reset(new DalvikReg(*this, name, NULL));
 
   // Store argument to dalvik register
   irb_.SetInsertPoint(basic_block_reg_arg_init_);
@@ -284,7 +284,8 @@
     }
   }
 
-  llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(num_shadow_frame_refs_);
+  llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(num_shadow_frame_refs_,
+                                                              code_item_->registers_size_);
   shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
 
   // Alloca a pointer to old shadow frame
@@ -3802,6 +3803,43 @@
 }
 
 
+// TODO: We will remove ShadowFrameEntry later, so I just copy/paste from ShadowFrameEntry.
+llvm::Value* MethodCompiler::GetVRegEntry(uint32_t reg_idx) {
+  if (!compiler_->IsDebuggingSupported()) {
+    return NULL;
+  }
+
+  if (!method_info_.need_shadow_frame_entry) {
+    return NULL;
+  }
+
+  std::string reg_name;
+
+#if !defined(NDEBUG)
+  StringAppendF(&reg_name, "v%u", reg_idx);
+#endif
+
+  // Save current IR builder insert point
+  llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
+
+  irb_.SetInsertPoint(basic_block_shadow_frame_);
+
+  llvm::Value* gep_index[] = {
+    irb_.getInt32(0), // No pointer displacement
+    irb_.getInt32(2), // VRegs
+    irb_.getInt32(reg_idx) // Pointer field
+  };
+
+  llvm::Value* reg_addr = irb_.CreateGEP(shadow_frame_, gep_index, reg_name);
+
+  // Restore IRBuilder insert point
+  irb_.restoreIP(irb_ip_original);
+
+  DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
+  return reg_addr;
+}
+
+
 void MethodCompiler::EmitPushShadowFrame(bool is_inline) {
   if (!method_info_.need_shadow_frame) {
     return;
@@ -3819,11 +3857,13 @@
   llvm::Value* result;
   if (is_inline) {
     result = irb_.Runtime().EmitPushShadowFrame(shadow_frame_upcast, method_object_addr,
-                                                num_shadow_frame_refs_, 0);
+                                                num_shadow_frame_refs_,
+                                                code_item_->registers_size_);
   } else {
     DCHECK(num_shadow_frame_refs_ == 0);
     result = irb_.Runtime().EmitPushShadowFrameNoInline(shadow_frame_upcast, method_object_addr,
-                                                        num_shadow_frame_refs_, 0);
+                                                        num_shadow_frame_refs_,
+                                                        code_item_->registers_size_);
   }
   irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
 }
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index 0b6fcfd..02c3d6a 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -90,6 +90,8 @@
 
   llvm::Value* GetShadowFrameEntry(uint32_t reg_idx);
 
+  llvm::Value* GetVRegEntry(uint32_t reg_idx);
+
 
  private:
   void CreateFunction();
@@ -460,6 +462,7 @@
 
   std::vector<DalvikReg*> regs_;
   std::vector<llvm::Value*> shadow_frame_entries_;
+  std::vector<llvm::Value*> vregs_;
   std::vector<int32_t> reg_to_shadow_frame_index_;
   UniquePtr<DalvikReg> retval_reg_;
 
diff --git a/src/greenland/intrinsic_func_list.def b/src/greenland/intrinsic_func_list.def
index 8ea69fe..57faf4c 100644
--- a/src/greenland/intrinsic_func_list.def
+++ b/src/greenland/intrinsic_func_list.def
@@ -1546,7 +1546,7 @@
                           dex_lang_alloca_shadow_frame,
                           kAttrNoThrow,
                           kVoidTy,
-                          _EXPAND_ARG1(kInt32ConstantTy))
+                          _EXPAND_ARG2(kInt32ConstantTy, kInt32ConstantTy))
 
 // void dex_lang_set_shadow_frame_entry(JavaObject* obj, int entry_idx)
 _EVAL_DEF_INTRINSICS_FUNC(SetShadowFrameEntry,
@@ -1555,6 +1555,13 @@
                           kVoidTy,
                           _EXPAND_ARG2(kJavaObjectTy, kInt32ConstantTy))
 
+// void dex_lang_set_vreg(int entry_idx, ...)
+_EVAL_DEF_INTRINSICS_FUNC(SetVReg,
+                          dex_lang_set_vreg,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32ConstantTy, kVarArgTy))
+
 // void dex_lang_pop_shadow_frame()
 _EVAL_DEF_INTRINSICS_FUNC(PopShadowFrame,
                           dex_lang_pop_shadow_frame,
diff --git a/src/stack.cc b/src/stack.cc
index b244975..8a741c6 100644
--- a/src/stack.cc
+++ b/src/stack.cc
@@ -66,9 +66,9 @@
 
 
 uint32_t StackVisitor::GetVReg(AbstractMethod* m, int vreg) const {
+  DCHECK(m == GetMethod());
   if (cur_quick_frame_ != NULL) {
     DCHECK(context_ != NULL); // You can't reliably read registers without a context.
-    DCHECK(m == GetMethod());
     uint32_t core_spills = m->GetCoreSpillMask();
     const VmapTable vmap_table(m->GetVmapTableRaw());
     uint32_t vmap_offset;
@@ -95,8 +95,7 @@
       return GetVReg(cur_quick_frame_, code_item, core_spills, fp_spills, frame_size, vreg);
     }
   } else {
-    LOG(FATAL) << "Unimplemented - shadow frame GetVReg";
-    return 0;  // Keep GCC happy.
+    return cur_shadow_frame_->GetVReg(vreg);
   }
 }