/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "object_utils.h"

#include <llvm/ADT/DepthFirstIterator.h>
#include <llvm/Analysis/Verifier.h>
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/IR/Instruction.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/Metadata.h>
#include <llvm/IR/Type.h>
#include <llvm/Support/Casting.h>
#include <llvm/Support/InstIterator.h>
#include <llvm/Support/ToolOutputFile.h>

#include "dex/compiler_internals.h"
#include "dex/dataflow_iterator-inl.h"
#include "dex/frontend.h"
#include "mir_to_gbc.h"

#include "llvm/llvm_compilation_unit.h"
#include "llvm/utils_llvm.h"

const char* kLabelFormat = "%c0x%x_%d";
const char kInvalidBlock = 0xff;
const char kNormalBlock = 'L';
const char kCatchBlock = 'C';

namespace art {

::llvm::BasicBlock* MirConverter::GetLLVMBlock(int id) {
  return id_to_block_map_.Get(id);
}

::llvm::Value* MirConverter::GetLLVMValue(int s_reg) {
  return llvm_values_.Get(s_reg);
}

void MirConverter::SetVregOnValue(::llvm::Value* val, int s_reg) {
  // Set vreg for debugging
  art::llvm::IntrinsicHelper::IntrinsicId id = art::llvm::IntrinsicHelper::SetVReg;
  ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction(id);
  int v_reg = mir_graph_->SRegToVReg(s_reg);
  ::llvm::Value* table_slot = irb_->getInt32(v_reg);
  ::llvm::Value* args[] = { table_slot, val };
  irb_->CreateCall(func, args);
}

// Replace the placeholder value with the real definition
void MirConverter::DefineValueOnly(::llvm::Value* val, int s_reg) {
  ::llvm::Value* placeholder = GetLLVMValue(s_reg);
  if (placeholder == NULL) {
    // This can happen on instruction rewrite on verification failure
    LOG(WARNING) << "Null placeholder";
    return;
  }
  placeholder->replaceAllUsesWith(val);
  val->takeName(placeholder);
  llvm_values_.Put(s_reg, val);
  ::llvm::Instruction* inst = ::llvm::dyn_cast< ::llvm::Instruction>(placeholder);
  DCHECK(inst != NULL);
  inst->eraseFromParent();
}

void MirConverter::DefineValue(::llvm::Value* val, int s_reg) {
  DefineValueOnly(val, s_reg);
  SetVregOnValue(val, s_reg);
}

::llvm::Type* MirConverter::LlvmTypeFromLocRec(RegLocation loc) {
  ::llvm::Type* res = NULL;
  if (loc.wide) {
    if (loc.fp)
        res = irb_->getDoubleTy();
    else
        res = irb_->getInt64Ty();
  } else {
    if (loc.fp) {
      res = irb_->getFloatTy();
    } else {
      if (loc.ref)
        res = irb_->getJObjectTy();
      else
        res = irb_->getInt32Ty();
    }
  }
  return res;
}

void MirConverter::InitIR() {
  if (llvm_info_ == NULL) {
    CompilerTls* tls = cu_->compiler_driver->GetTls();
    CHECK(tls != NULL);
    llvm_info_ = static_cast<LLVMInfo*>(tls->GetLLVMInfo());
    if (llvm_info_ == NULL) {
      llvm_info_ = new LLVMInfo();
      tls->SetLLVMInfo(llvm_info_);
    }
  }
  context_ = llvm_info_->GetLLVMContext();
  module_ = llvm_info_->GetLLVMModule();
  intrinsic_helper_ = llvm_info_->GetIntrinsicHelper();
  irb_ = llvm_info_->GetIRBuilder();
}

::llvm::BasicBlock* MirConverter::FindCaseTarget(uint32_t vaddr) {
  BasicBlock* bb = mir_graph_->FindBlock(vaddr);
  DCHECK(bb != NULL);
  return GetLLVMBlock(bb->id);
}

void MirConverter::ConvertPackedSwitch(BasicBlock* bb,
                                int32_t table_offset, RegLocation rl_src) {
  const Instruction::PackedSwitchPayload* payload =
      reinterpret_cast<const Instruction::PackedSwitchPayload*>(
      cu_->insns + current_dalvik_offset_ + table_offset);

  ::llvm::Value* value = GetLLVMValue(rl_src.orig_sreg);

  ::llvm::SwitchInst* sw =
    irb_->CreateSwitch(value, GetLLVMBlock(bb->fall_through->id),
                             payload->case_count);

  for (uint16_t i = 0; i < payload->case_count; ++i) {
    ::llvm::BasicBlock* llvm_bb =
        FindCaseTarget(current_dalvik_offset_ + payload->targets[i]);
    sw->addCase(irb_->getInt32(payload->first_key + i), llvm_bb);
  }
  ::llvm::MDNode* switch_node =
      ::llvm::MDNode::get(*context_, irb_->getInt32(table_offset));
  sw->setMetadata("SwitchTable", switch_node);
  bb->taken = NULL;
  bb->fall_through = NULL;
}

void MirConverter::ConvertSparseSwitch(BasicBlock* bb,
                                int32_t table_offset, RegLocation rl_src) {
  const Instruction::SparseSwitchPayload* payload =
      reinterpret_cast<const Instruction::SparseSwitchPayload*>(
      cu_->insns + current_dalvik_offset_ + table_offset);

  const int32_t* keys = payload->GetKeys();
  const int32_t* targets = payload->GetTargets();

  ::llvm::Value* value = GetLLVMValue(rl_src.orig_sreg);

  ::llvm::SwitchInst* sw =
    irb_->CreateSwitch(value, GetLLVMBlock(bb->fall_through->id),
                             payload->case_count);

  for (size_t i = 0; i < payload->case_count; ++i) {
    ::llvm::BasicBlock* llvm_bb =
        FindCaseTarget(current_dalvik_offset_ + targets[i]);
    sw->addCase(irb_->getInt32(keys[i]), llvm_bb);
  }
  ::llvm::MDNode* switch_node =
      ::llvm::MDNode::get(*context_, irb_->getInt32(table_offset));
  sw->setMetadata("SwitchTable", switch_node);
  bb->taken = NULL;
  bb->fall_through = NULL;
}

void MirConverter::ConvertSget(int32_t field_index,
                        art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_dest) {
  ::llvm::Constant* field_idx = irb_->getInt32(field_index);
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  ::llvm::Value* res = irb_->CreateCall(intr, field_idx);
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertSput(int32_t field_index,
                        art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_src) {
  ::llvm::SmallVector< ::llvm::Value*, 2> args;
  args.push_back(irb_->getInt32(field_index));
  args.push_back(GetLLVMValue(rl_src.orig_sreg));
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  irb_->CreateCall(intr, args);
}

void MirConverter::ConvertFillArrayData(int32_t offset, RegLocation rl_array) {
  art::llvm::IntrinsicHelper::IntrinsicId id;
  id = art::llvm::IntrinsicHelper::HLFillArrayData;
  ::llvm::SmallVector< ::llvm::Value*, 2> args;
  args.push_back(irb_->getInt32(offset));
  args.push_back(GetLLVMValue(rl_array.orig_sreg));
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  irb_->CreateCall(intr, args);
}

::llvm::Value* MirConverter::EmitConst(::llvm::ArrayRef< ::llvm::Value*> src,
                              RegLocation loc) {
  art::llvm::IntrinsicHelper::IntrinsicId id;
  if (loc.wide) {
    if (loc.fp) {
      id = art::llvm::IntrinsicHelper::ConstDouble;
    } else {
      id = art::llvm::IntrinsicHelper::ConstLong;
    }
  } else {
    if (loc.fp) {
      id = art::llvm::IntrinsicHelper::ConstFloat;
    } else if (loc.ref) {
      id = art::llvm::IntrinsicHelper::ConstObj;
    } else {
      id = art::llvm::IntrinsicHelper::ConstInt;
    }
  }
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  return irb_->CreateCall(intr, src);
}

void MirConverter::EmitPopShadowFrame() {
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(
      art::llvm::IntrinsicHelper::PopShadowFrame);
  irb_->CreateCall(intr);
}

::llvm::Value* MirConverter::EmitCopy(::llvm::ArrayRef< ::llvm::Value*> src,
                             RegLocation loc) {
  art::llvm::IntrinsicHelper::IntrinsicId id;
  if (loc.wide) {
    if (loc.fp) {
      id = art::llvm::IntrinsicHelper::CopyDouble;
    } else {
      id = art::llvm::IntrinsicHelper::CopyLong;
    }
  } else {
    if (loc.fp) {
      id = art::llvm::IntrinsicHelper::CopyFloat;
    } else if (loc.ref) {
      id = art::llvm::IntrinsicHelper::CopyObj;
    } else {
      id = art::llvm::IntrinsicHelper::CopyInt;
    }
  }
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  return irb_->CreateCall(intr, src);
}

void MirConverter::ConvertMoveException(RegLocation rl_dest) {
  ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction(
      art::llvm::IntrinsicHelper::GetException);
  ::llvm::Value* res = irb_->CreateCall(func);
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertThrow(RegLocation rl_src) {
  ::llvm::Value* src = GetLLVMValue(rl_src.orig_sreg);
  ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction(
      art::llvm::IntrinsicHelper::HLThrowException);
  irb_->CreateCall(func, src);
}

void MirConverter::ConvertMonitorEnterExit(int opt_flags,
                                    art::llvm::IntrinsicHelper::IntrinsicId id,
                                    RegLocation rl_src) {
  ::llvm::SmallVector< ::llvm::Value*, 2> args;
  args.push_back(irb_->getInt32(opt_flags));
  args.push_back(GetLLVMValue(rl_src.orig_sreg));
  ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction(id);
  irb_->CreateCall(func, args);
}

void MirConverter::ConvertArrayLength(int opt_flags,
                               RegLocation rl_dest, RegLocation rl_src) {
  ::llvm::SmallVector< ::llvm::Value*, 2> args;
  args.push_back(irb_->getInt32(opt_flags));
  args.push_back(GetLLVMValue(rl_src.orig_sreg));
  ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction(
      art::llvm::IntrinsicHelper::OptArrayLength);
  ::llvm::Value* res = irb_->CreateCall(func, args);
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::EmitSuspendCheck() {
  art::llvm::IntrinsicHelper::IntrinsicId id =
      art::llvm::IntrinsicHelper::CheckSuspend;
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  irb_->CreateCall(intr);
}

::llvm::Value* MirConverter::ConvertCompare(ConditionCode cc,
                                   ::llvm::Value* src1, ::llvm::Value* src2) {
  ::llvm::Value* res = NULL;
  DCHECK_EQ(src1->getType(), src2->getType());
  switch (cc) {
    case kCondEq: res = irb_->CreateICmpEQ(src1, src2); break;
    case kCondNe: res = irb_->CreateICmpNE(src1, src2); break;
    case kCondLt: res = irb_->CreateICmpSLT(src1, src2); break;
    case kCondGe: res = irb_->CreateICmpSGE(src1, src2); break;
    case kCondGt: res = irb_->CreateICmpSGT(src1, src2); break;
    case kCondLe: res = irb_->CreateICmpSLE(src1, src2); break;
    default: LOG(FATAL) << "Unexpected cc value " << cc;
  }
  return res;
}

void MirConverter::ConvertCompareAndBranch(BasicBlock* bb, MIR* mir,
                                    ConditionCode cc, RegLocation rl_src1, RegLocation rl_src2) {
  if (bb->taken->start_offset <= mir->offset) {
    EmitSuspendCheck();
  }
  ::llvm::Value* src1 = GetLLVMValue(rl_src1.orig_sreg);
  ::llvm::Value* src2 = GetLLVMValue(rl_src2.orig_sreg);
  ::llvm::Value* cond_value = ConvertCompare(cc, src1, src2);
  cond_value->setName(StringPrintf("t%d", temp_name_++));
  irb_->CreateCondBr(cond_value, GetLLVMBlock(bb->taken->id),
                           GetLLVMBlock(bb->fall_through->id));
  // Don't redo the fallthrough branch in the BB driver
  bb->fall_through = NULL;
}

void MirConverter::ConvertCompareZeroAndBranch(BasicBlock* bb,
                                        MIR* mir, ConditionCode cc, RegLocation rl_src1) {
  if (bb->taken->start_offset <= mir->offset) {
    EmitSuspendCheck();
  }
  ::llvm::Value* src1 = GetLLVMValue(rl_src1.orig_sreg);
  ::llvm::Value* src2;
  if (rl_src1.ref) {
    src2 = irb_->getJNull();
  } else {
    src2 = irb_->getInt32(0);
  }
  ::llvm::Value* cond_value = ConvertCompare(cc, src1, src2);
  irb_->CreateCondBr(cond_value, GetLLVMBlock(bb->taken->id),
                           GetLLVMBlock(bb->fall_through->id));
  // Don't redo the fallthrough branch in the BB driver
  bb->fall_through = NULL;
}

::llvm::Value* MirConverter::GenDivModOp(bool is_div, bool is_long,
                                ::llvm::Value* src1, ::llvm::Value* src2) {
  art::llvm::IntrinsicHelper::IntrinsicId id;
  if (is_long) {
    if (is_div) {
      id = art::llvm::IntrinsicHelper::DivLong;
    } else {
      id = art::llvm::IntrinsicHelper::RemLong;
    }
  } else {
    if (is_div) {
      id = art::llvm::IntrinsicHelper::DivInt;
    } else {
      id = art::llvm::IntrinsicHelper::RemInt;
    }
  }
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  ::llvm::SmallVector< ::llvm::Value*, 2>args;
  args.push_back(src1);
  args.push_back(src2);
  return irb_->CreateCall(intr, args);
}

::llvm::Value* MirConverter::GenArithOp(OpKind op, bool is_long,
                               ::llvm::Value* src1, ::llvm::Value* src2) {
  ::llvm::Value* res = NULL;
  switch (op) {
    case kOpAdd: res = irb_->CreateAdd(src1, src2); break;
    case kOpSub: res = irb_->CreateSub(src1, src2); break;
    case kOpRsub: res = irb_->CreateSub(src2, src1); break;
    case kOpMul: res = irb_->CreateMul(src1, src2); break;
    case kOpOr: res = irb_->CreateOr(src1, src2); break;
    case kOpAnd: res = irb_->CreateAnd(src1, src2); break;
    case kOpXor: res = irb_->CreateXor(src1, src2); break;
    case kOpDiv: res = GenDivModOp(true, is_long, src1, src2); break;
    case kOpRem: res = GenDivModOp(false, is_long, src1, src2); break;
    case kOpLsl: res = irb_->CreateShl(src1, src2); break;
    case kOpLsr: res = irb_->CreateLShr(src1, src2); break;
    case kOpAsr: res = irb_->CreateAShr(src1, src2); break;
    default:
      LOG(FATAL) << "Invalid op " << op;
  }
  return res;
}

void MirConverter::ConvertFPArithOp(OpKind op, RegLocation rl_dest,
                             RegLocation rl_src1, RegLocation rl_src2) {
  ::llvm::Value* src1 = GetLLVMValue(rl_src1.orig_sreg);
  ::llvm::Value* src2 = GetLLVMValue(rl_src2.orig_sreg);
  ::llvm::Value* res = NULL;
  switch (op) {
    case kOpAdd: res = irb_->CreateFAdd(src1, src2); break;
    case kOpSub: res = irb_->CreateFSub(src1, src2); break;
    case kOpMul: res = irb_->CreateFMul(src1, src2); break;
    case kOpDiv: res = irb_->CreateFDiv(src1, src2); break;
    case kOpRem: res = irb_->CreateFRem(src1, src2); break;
    default:
      LOG(FATAL) << "Invalid op " << op;
  }
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertShift(art::llvm::IntrinsicHelper::IntrinsicId id,
                         RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  ::llvm::SmallVector< ::llvm::Value*, 2>args;
  args.push_back(GetLLVMValue(rl_src1.orig_sreg));
  args.push_back(GetLLVMValue(rl_src2.orig_sreg));
  ::llvm::Value* res = irb_->CreateCall(intr, args);
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertShiftLit(art::llvm::IntrinsicHelper::IntrinsicId id,
                            RegLocation rl_dest, RegLocation rl_src, int shift_amount) {
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  ::llvm::SmallVector< ::llvm::Value*, 2>args;
  args.push_back(GetLLVMValue(rl_src.orig_sreg));
  args.push_back(irb_->getInt32(shift_amount));
  ::llvm::Value* res = irb_->CreateCall(intr, args);
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertArithOp(OpKind op, RegLocation rl_dest,
                           RegLocation rl_src1, RegLocation rl_src2) {
  ::llvm::Value* src1 = GetLLVMValue(rl_src1.orig_sreg);
  ::llvm::Value* src2 = GetLLVMValue(rl_src2.orig_sreg);
  DCHECK_EQ(src1->getType(), src2->getType());
  ::llvm::Value* res = GenArithOp(op, rl_dest.wide, src1, src2);
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertArithOpLit(OpKind op, RegLocation rl_dest,
                              RegLocation rl_src1, int32_t imm) {
  ::llvm::Value* src1 = GetLLVMValue(rl_src1.orig_sreg);
  ::llvm::Value* src2 = irb_->getInt32(imm);
  ::llvm::Value* res = GenArithOp(op, rl_dest.wide, src1, src2);
  DefineValue(res, rl_dest.orig_sreg);
}

/*
 * Process arguments for invoke.  Note: this code is also used to
 * collect and process arguments for NEW_FILLED_ARRAY and NEW_FILLED_ARRAY_RANGE.
 * The requirements are similar.
 */
void MirConverter::ConvertInvoke(BasicBlock* bb, MIR* mir,
                          InvokeType invoke_type, bool is_range, bool is_filled_new_array) {
  CallInfo* info = mir_graph_->NewMemCallInfo(bb, mir, invoke_type, is_range);
  ::llvm::SmallVector< ::llvm::Value*, 10> args;
  // Insert the invoke_type
  args.push_back(irb_->getInt32(static_cast<int>(invoke_type)));
  // Insert the method_idx
  args.push_back(irb_->getInt32(info->index));
  // Insert the optimization flags
  args.push_back(irb_->getInt32(info->opt_flags));
  // Now, insert the actual arguments
  for (int i = 0; i < info->num_arg_words;) {
    ::llvm::Value* val = GetLLVMValue(info->args[i].orig_sreg);
    args.push_back(val);
    i += info->args[i].wide ? 2 : 1;
  }
  /*
   * Choose the invoke return type based on actual usage.  Note: may
   * be different than shorty.  For example, if a function return value
   * is not used, we'll treat this as a void invoke.
   */
  art::llvm::IntrinsicHelper::IntrinsicId id;
  if (is_filled_new_array) {
    id = art::llvm::IntrinsicHelper::HLFilledNewArray;
  } else if (info->result.location == kLocInvalid) {
    id = art::llvm::IntrinsicHelper::HLInvokeVoid;
  } else {
    if (info->result.wide) {
      if (info->result.fp) {
        id = art::llvm::IntrinsicHelper::HLInvokeDouble;
      } else {
        id = art::llvm::IntrinsicHelper::HLInvokeLong;
      }
    } else if (info->result.ref) {
        id = art::llvm::IntrinsicHelper::HLInvokeObj;
    } else if (info->result.fp) {
        id = art::llvm::IntrinsicHelper::HLInvokeFloat;
    } else {
        id = art::llvm::IntrinsicHelper::HLInvokeInt;
    }
  }
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  ::llvm::Value* res = irb_->CreateCall(intr, args);
  if (info->result.location != kLocInvalid) {
    DefineValue(res, info->result.orig_sreg);
  }
}

void MirConverter::ConvertConstObject(uint32_t idx,
                               art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_dest) {
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  ::llvm::Value* index = irb_->getInt32(idx);
  ::llvm::Value* res = irb_->CreateCall(intr, index);
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertCheckCast(uint32_t type_idx, RegLocation rl_src) {
  art::llvm::IntrinsicHelper::IntrinsicId id;
  id = art::llvm::IntrinsicHelper::HLCheckCast;
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  ::llvm::SmallVector< ::llvm::Value*, 2> args;
  args.push_back(irb_->getInt32(type_idx));
  args.push_back(GetLLVMValue(rl_src.orig_sreg));
  irb_->CreateCall(intr, args);
}

void MirConverter::ConvertNewInstance(uint32_t type_idx, RegLocation rl_dest) {
  art::llvm::IntrinsicHelper::IntrinsicId id;
  id = art::llvm::IntrinsicHelper::NewInstance;
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  ::llvm::Value* index = irb_->getInt32(type_idx);
  ::llvm::Value* res = irb_->CreateCall(intr, index);
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertNewArray(uint32_t type_idx,
                            RegLocation rl_dest, RegLocation rl_src) {
  art::llvm::IntrinsicHelper::IntrinsicId id;
  id = art::llvm::IntrinsicHelper::NewArray;
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  ::llvm::SmallVector< ::llvm::Value*, 2> args;
  args.push_back(irb_->getInt32(type_idx));
  args.push_back(GetLLVMValue(rl_src.orig_sreg));
  ::llvm::Value* res = irb_->CreateCall(intr, args);
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertAget(int opt_flags,
                        art::llvm::IntrinsicHelper::IntrinsicId id,
                        RegLocation rl_dest, RegLocation rl_array, RegLocation rl_index) {
  ::llvm::SmallVector< ::llvm::Value*, 3> args;
  args.push_back(irb_->getInt32(opt_flags));
  args.push_back(GetLLVMValue(rl_array.orig_sreg));
  args.push_back(GetLLVMValue(rl_index.orig_sreg));
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  ::llvm::Value* res = irb_->CreateCall(intr, args);
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertAput(int opt_flags,
                        art::llvm::IntrinsicHelper::IntrinsicId id,
                        RegLocation rl_src, RegLocation rl_array, RegLocation rl_index) {
  ::llvm::SmallVector< ::llvm::Value*, 4> args;
  args.push_back(irb_->getInt32(opt_flags));
  args.push_back(GetLLVMValue(rl_src.orig_sreg));
  args.push_back(GetLLVMValue(rl_array.orig_sreg));
  args.push_back(GetLLVMValue(rl_index.orig_sreg));
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  irb_->CreateCall(intr, args);
}

void MirConverter::ConvertIget(int opt_flags,
                        art::llvm::IntrinsicHelper::IntrinsicId id,
                        RegLocation rl_dest, RegLocation rl_obj, int field_index) {
  ::llvm::SmallVector< ::llvm::Value*, 3> args;
  args.push_back(irb_->getInt32(opt_flags));
  args.push_back(GetLLVMValue(rl_obj.orig_sreg));
  args.push_back(irb_->getInt32(field_index));
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  ::llvm::Value* res = irb_->CreateCall(intr, args);
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertIput(int opt_flags,
                        art::llvm::IntrinsicHelper::IntrinsicId id,
                        RegLocation rl_src, RegLocation rl_obj, int field_index) {
  ::llvm::SmallVector< ::llvm::Value*, 4> args;
  args.push_back(irb_->getInt32(opt_flags));
  args.push_back(GetLLVMValue(rl_src.orig_sreg));
  args.push_back(GetLLVMValue(rl_obj.orig_sreg));
  args.push_back(irb_->getInt32(field_index));
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  irb_->CreateCall(intr, args);
}

void MirConverter::ConvertInstanceOf(uint32_t type_idx,
                              RegLocation rl_dest, RegLocation rl_src) {
  art::llvm::IntrinsicHelper::IntrinsicId id;
  id = art::llvm::IntrinsicHelper::InstanceOf;
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  ::llvm::SmallVector< ::llvm::Value*, 2> args;
  args.push_back(irb_->getInt32(type_idx));
  args.push_back(GetLLVMValue(rl_src.orig_sreg));
  ::llvm::Value* res = irb_->CreateCall(intr, args);
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertIntToLong(RegLocation rl_dest, RegLocation rl_src) {
  ::llvm::Value* res = irb_->CreateSExt(GetLLVMValue(rl_src.orig_sreg),
                                            irb_->getInt64Ty());
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertLongToInt(RegLocation rl_dest, RegLocation rl_src) {
  ::llvm::Value* src = GetLLVMValue(rl_src.orig_sreg);
  ::llvm::Value* res = irb_->CreateTrunc(src, irb_->getInt32Ty());
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertFloatToDouble(RegLocation rl_dest, RegLocation rl_src) {
  ::llvm::Value* src = GetLLVMValue(rl_src.orig_sreg);
  ::llvm::Value* res = irb_->CreateFPExt(src, irb_->getDoubleTy());
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertDoubleToFloat(RegLocation rl_dest, RegLocation rl_src) {
  ::llvm::Value* src = GetLLVMValue(rl_src.orig_sreg);
  ::llvm::Value* res = irb_->CreateFPTrunc(src, irb_->getFloatTy());
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertWideComparison(art::llvm::IntrinsicHelper::IntrinsicId id,
                                         RegLocation rl_dest, RegLocation rl_src1,
                                         RegLocation rl_src2) {
  DCHECK_EQ(rl_src1.fp, rl_src2.fp);
  DCHECK_EQ(rl_src1.wide, rl_src2.wide);
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  ::llvm::SmallVector< ::llvm::Value*, 2> args;
  args.push_back(GetLLVMValue(rl_src1.orig_sreg));
  args.push_back(GetLLVMValue(rl_src2.orig_sreg));
  ::llvm::Value* res = irb_->CreateCall(intr, args);
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertIntNarrowing(RegLocation rl_dest, RegLocation rl_src,
                                art::llvm::IntrinsicHelper::IntrinsicId id) {
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  ::llvm::Value* res =
      irb_->CreateCall(intr, GetLLVMValue(rl_src.orig_sreg));
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertNeg(RegLocation rl_dest, RegLocation rl_src) {
  ::llvm::Value* res = irb_->CreateNeg(GetLLVMValue(rl_src.orig_sreg));
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertIntToFP(::llvm::Type* ty, RegLocation rl_dest,
                           RegLocation rl_src) {
  ::llvm::Value* res =
      irb_->CreateSIToFP(GetLLVMValue(rl_src.orig_sreg), ty);
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertFPToInt(art::llvm::IntrinsicHelper::IntrinsicId id,
                           RegLocation rl_dest,
                    RegLocation rl_src) {
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  ::llvm::Value* res = irb_->CreateCall(intr, GetLLVMValue(rl_src.orig_sreg));
  DefineValue(res, rl_dest.orig_sreg);
}


void MirConverter::ConvertNegFP(RegLocation rl_dest, RegLocation rl_src) {
  ::llvm::Value* res =
      irb_->CreateFNeg(GetLLVMValue(rl_src.orig_sreg));
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::ConvertNot(RegLocation rl_dest, RegLocation rl_src) {
  ::llvm::Value* src = GetLLVMValue(rl_src.orig_sreg);
  ::llvm::Value* res = irb_->CreateXor(src, static_cast<uint64_t>(-1));
  DefineValue(res, rl_dest.orig_sreg);
}

void MirConverter::EmitConstructorBarrier() {
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(
      art::llvm::IntrinsicHelper::ConstructorBarrier);
  irb_->CreateCall(intr);
}

/*
 * Target-independent code generation.  Use only high-level
 * load/store utilities here, or target-dependent genXX() handlers
 * when necessary.
 */
bool MirConverter::ConvertMIRNode(MIR* mir, BasicBlock* bb,
                           ::llvm::BasicBlock* llvm_bb) {
  bool res = false;   // Assume success
  RegLocation rl_src[3];
  RegLocation rl_dest = mir_graph_->GetBadLoc();
  Instruction::Code opcode = mir->dalvikInsn.opcode;
  int op_val = opcode;
  uint32_t vB = mir->dalvikInsn.vB;
  uint32_t vC = mir->dalvikInsn.vC;
  int opt_flags = mir->optimization_flags;

  if (cu_->verbose) {
    if (op_val < kMirOpFirst) {
      LOG(INFO) << ".. " << Instruction::Name(opcode) << " 0x" << std::hex << op_val;
    } else {
      LOG(INFO) << mir_graph_->extended_mir_op_names_[op_val - kMirOpFirst] << " 0x" << std::hex << op_val;
    }
  }

  /* Prep Src and Dest locations */
  int next_sreg = 0;
  int next_loc = 0;
  int attrs = mir_graph_->oat_data_flow_attributes_[opcode];
  rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc();
  if (attrs & DF_UA) {
    if (attrs & DF_A_WIDE) {
      rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg);
      next_sreg+= 2;
    } else {
      rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg);
      next_sreg++;
    }
  }
  if (attrs & DF_UB) {
    if (attrs & DF_B_WIDE) {
      rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg);
      next_sreg+= 2;
    } else {
      rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg);
      next_sreg++;
    }
  }
  if (attrs & DF_UC) {
    if (attrs & DF_C_WIDE) {
      rl_src[next_loc++] = mir_graph_->GetSrcWide(mir, next_sreg);
    } else {
      rl_src[next_loc++] = mir_graph_->GetSrc(mir, next_sreg);
    }
  }
  if (attrs & DF_DA) {
    if (attrs & DF_A_WIDE) {
      rl_dest = mir_graph_->GetDestWide(mir);
    } else {
      rl_dest = mir_graph_->GetDest(mir);
    }
  }

  switch (opcode) {
    case Instruction::NOP:
      break;

    case Instruction::MOVE:
    case Instruction::MOVE_OBJECT:
    case Instruction::MOVE_16:
    case Instruction::MOVE_OBJECT_16:
    case Instruction::MOVE_OBJECT_FROM16:
    case Instruction::MOVE_FROM16:
    case Instruction::MOVE_WIDE:
    case Instruction::MOVE_WIDE_16:
    case Instruction::MOVE_WIDE_FROM16: {
        /*
         * Moves/copies are meaningless in pure SSA register form,
         * but we need to preserve them for the conversion back into
         * MIR (at least until we stop using the Dalvik register maps).
         * Insert a dummy intrinsic copy call, which will be recognized
         * by the quick path and removed by the portable path.
         */
        ::llvm::Value* src = GetLLVMValue(rl_src[0].orig_sreg);
        ::llvm::Value* res = EmitCopy(src, rl_dest);
        DefineValue(res, rl_dest.orig_sreg);
      }
      break;

    case Instruction::CONST:
    case Instruction::CONST_4:
    case Instruction::CONST_16: {
        ::llvm::Constant* imm_value = irb_->getJInt(vB);
        ::llvm::Value* res = EmitConst(imm_value, rl_dest);
        DefineValue(res, rl_dest.orig_sreg);
      }
      break;

    case Instruction::CONST_WIDE_16:
    case Instruction::CONST_WIDE_32: {
        // Sign extend to 64 bits
        int64_t imm = static_cast<int32_t>(vB);
        ::llvm::Constant* imm_value = irb_->getJLong(imm);
        ::llvm::Value* res = EmitConst(imm_value, rl_dest);
        DefineValue(res, rl_dest.orig_sreg);
      }
      break;

    case Instruction::CONST_HIGH16: {
        ::llvm::Constant* imm_value = irb_->getJInt(vB << 16);
        ::llvm::Value* res = EmitConst(imm_value, rl_dest);
        DefineValue(res, rl_dest.orig_sreg);
      }
      break;

    case Instruction::CONST_WIDE: {
        ::llvm::Constant* imm_value =
            irb_->getJLong(mir->dalvikInsn.vB_wide);
        ::llvm::Value* res = EmitConst(imm_value, rl_dest);
        DefineValue(res, rl_dest.orig_sreg);
      }
      break;
    case Instruction::CONST_WIDE_HIGH16: {
        int64_t imm = static_cast<int64_t>(vB) << 48;
        ::llvm::Constant* imm_value = irb_->getJLong(imm);
        ::llvm::Value* res = EmitConst(imm_value, rl_dest);
        DefineValue(res, rl_dest.orig_sreg);
      }
      break;

    case Instruction::SPUT_OBJECT:
      ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputObject,
                  rl_src[0]);
      break;
    case Instruction::SPUT:
      if (rl_src[0].fp) {
        ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputFloat,
                    rl_src[0]);
      } else {
        ConvertSput(vB, art::llvm::IntrinsicHelper::HLSput, rl_src[0]);
      }
      break;
    case Instruction::SPUT_BOOLEAN:
      ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputBoolean,
                  rl_src[0]);
      break;
    case Instruction::SPUT_BYTE:
      ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputByte, rl_src[0]);
      break;
    case Instruction::SPUT_CHAR:
      ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputChar, rl_src[0]);
      break;
    case Instruction::SPUT_SHORT:
      ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputShort, rl_src[0]);
      break;
    case Instruction::SPUT_WIDE:
      if (rl_src[0].fp) {
        ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputDouble,
                    rl_src[0]);
      } else {
        ConvertSput(vB, art::llvm::IntrinsicHelper::HLSputWide,
                    rl_src[0]);
      }
      break;

    case Instruction::SGET_OBJECT:
      ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetObject, rl_dest);
      break;
    case Instruction::SGET:
      if (rl_dest.fp) {
        ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetFloat, rl_dest);
      } else {
        ConvertSget(vB, art::llvm::IntrinsicHelper::HLSget, rl_dest);
      }
      break;
    case Instruction::SGET_BOOLEAN:
      ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetBoolean, rl_dest);
      break;
    case Instruction::SGET_BYTE:
      ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetByte, rl_dest);
      break;
    case Instruction::SGET_CHAR:
      ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetChar, rl_dest);
      break;
    case Instruction::SGET_SHORT:
      ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetShort, rl_dest);
      break;
    case Instruction::SGET_WIDE:
      if (rl_dest.fp) {
        ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetDouble,
                    rl_dest);
      } else {
        ConvertSget(vB, art::llvm::IntrinsicHelper::HLSgetWide, rl_dest);
      }
      break;

    case Instruction::RETURN_WIDE:
    case Instruction::RETURN:
    case Instruction::RETURN_OBJECT: {
        if (!mir_graph_->MethodIsLeaf()) {
          EmitSuspendCheck();
        }
        EmitPopShadowFrame();
        irb_->CreateRet(GetLLVMValue(rl_src[0].orig_sreg));
        DCHECK(bb->terminated_by_return);
      }
      break;

    case Instruction::RETURN_VOID: {
        if (((cu_->access_flags & kAccConstructor) != 0) &&
            cu_->compiler_driver->RequiresConstructorBarrier(Thread::Current(),
                                                            cu_->dex_file,
                                                            cu_->class_def_idx)) {
          EmitConstructorBarrier();
        }
        if (!mir_graph_->MethodIsLeaf()) {
          EmitSuspendCheck();
        }
        EmitPopShadowFrame();
        irb_->CreateRetVoid();
        DCHECK(bb->terminated_by_return);
      }
      break;

    case Instruction::IF_EQ:
      ConvertCompareAndBranch(bb, mir, kCondEq, rl_src[0], rl_src[1]);
      break;
    case Instruction::IF_NE:
      ConvertCompareAndBranch(bb, mir, kCondNe, rl_src[0], rl_src[1]);
      break;
    case Instruction::IF_LT:
      ConvertCompareAndBranch(bb, mir, kCondLt, rl_src[0], rl_src[1]);
      break;
    case Instruction::IF_GE:
      ConvertCompareAndBranch(bb, mir, kCondGe, rl_src[0], rl_src[1]);
      break;
    case Instruction::IF_GT:
      ConvertCompareAndBranch(bb, mir, kCondGt, rl_src[0], rl_src[1]);
      break;
    case Instruction::IF_LE:
      ConvertCompareAndBranch(bb, mir, kCondLe, rl_src[0], rl_src[1]);
      break;
    case Instruction::IF_EQZ:
      ConvertCompareZeroAndBranch(bb, mir, kCondEq, rl_src[0]);
      break;
    case Instruction::IF_NEZ:
      ConvertCompareZeroAndBranch(bb, mir, kCondNe, rl_src[0]);
      break;
    case Instruction::IF_LTZ:
      ConvertCompareZeroAndBranch(bb, mir, kCondLt, rl_src[0]);
      break;
    case Instruction::IF_GEZ:
      ConvertCompareZeroAndBranch(bb, mir, kCondGe, rl_src[0]);
      break;
    case Instruction::IF_GTZ:
      ConvertCompareZeroAndBranch(bb, mir, kCondGt, rl_src[0]);
      break;
    case Instruction::IF_LEZ:
      ConvertCompareZeroAndBranch(bb, mir, kCondLe, rl_src[0]);
      break;

    case Instruction::GOTO:
    case Instruction::GOTO_16:
    case Instruction::GOTO_32: {
        if (bb->taken->start_offset <= bb->start_offset) {
          EmitSuspendCheck();
        }
        irb_->CreateBr(GetLLVMBlock(bb->taken->id));
      }
      break;

    case Instruction::ADD_LONG:
    case Instruction::ADD_LONG_2ADDR:
    case Instruction::ADD_INT:
    case Instruction::ADD_INT_2ADDR:
      ConvertArithOp(kOpAdd, rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::SUB_LONG:
    case Instruction::SUB_LONG_2ADDR:
    case Instruction::SUB_INT:
    case Instruction::SUB_INT_2ADDR:
      ConvertArithOp(kOpSub, rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::MUL_LONG:
    case Instruction::MUL_LONG_2ADDR:
    case Instruction::MUL_INT:
    case Instruction::MUL_INT_2ADDR:
      ConvertArithOp(kOpMul, rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::DIV_LONG:
    case Instruction::DIV_LONG_2ADDR:
    case Instruction::DIV_INT:
    case Instruction::DIV_INT_2ADDR:
      ConvertArithOp(kOpDiv, rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::REM_LONG:
    case Instruction::REM_LONG_2ADDR:
    case Instruction::REM_INT:
    case Instruction::REM_INT_2ADDR:
      ConvertArithOp(kOpRem, rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::AND_LONG:
    case Instruction::AND_LONG_2ADDR:
    case Instruction::AND_INT:
    case Instruction::AND_INT_2ADDR:
      ConvertArithOp(kOpAnd, rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::OR_LONG:
    case Instruction::OR_LONG_2ADDR:
    case Instruction::OR_INT:
    case Instruction::OR_INT_2ADDR:
      ConvertArithOp(kOpOr, rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::XOR_LONG:
    case Instruction::XOR_LONG_2ADDR:
    case Instruction::XOR_INT:
    case Instruction::XOR_INT_2ADDR:
      ConvertArithOp(kOpXor, rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::SHL_LONG:
    case Instruction::SHL_LONG_2ADDR:
      ConvertShift(art::llvm::IntrinsicHelper::SHLLong,
                    rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::SHL_INT:
    case Instruction::SHL_INT_2ADDR:
      ConvertShift(art::llvm::IntrinsicHelper::SHLInt,
                   rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::SHR_LONG:
    case Instruction::SHR_LONG_2ADDR:
      ConvertShift(art::llvm::IntrinsicHelper::SHRLong,
                   rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::SHR_INT:
    case Instruction::SHR_INT_2ADDR:
      ConvertShift(art::llvm::IntrinsicHelper::SHRInt,
                   rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::USHR_LONG:
    case Instruction::USHR_LONG_2ADDR:
      ConvertShift(art::llvm::IntrinsicHelper::USHRLong,
                   rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::USHR_INT:
    case Instruction::USHR_INT_2ADDR:
      ConvertShift(art::llvm::IntrinsicHelper::USHRInt,
                   rl_dest, rl_src[0], rl_src[1]);
      break;

    case Instruction::ADD_INT_LIT16:
    case Instruction::ADD_INT_LIT8:
      ConvertArithOpLit(kOpAdd, rl_dest, rl_src[0], vC);
      break;
    case Instruction::RSUB_INT:
    case Instruction::RSUB_INT_LIT8:
      ConvertArithOpLit(kOpRsub, rl_dest, rl_src[0], vC);
      break;
    case Instruction::MUL_INT_LIT16:
    case Instruction::MUL_INT_LIT8:
      ConvertArithOpLit(kOpMul, rl_dest, rl_src[0], vC);
      break;
    case Instruction::DIV_INT_LIT16:
    case Instruction::DIV_INT_LIT8:
      ConvertArithOpLit(kOpDiv, rl_dest, rl_src[0], vC);
      break;
    case Instruction::REM_INT_LIT16:
    case Instruction::REM_INT_LIT8:
      ConvertArithOpLit(kOpRem, rl_dest, rl_src[0], vC);
      break;
    case Instruction::AND_INT_LIT16:
    case Instruction::AND_INT_LIT8:
      ConvertArithOpLit(kOpAnd, rl_dest, rl_src[0], vC);
      break;
    case Instruction::OR_INT_LIT16:
    case Instruction::OR_INT_LIT8:
      ConvertArithOpLit(kOpOr, rl_dest, rl_src[0], vC);
      break;
    case Instruction::XOR_INT_LIT16:
    case Instruction::XOR_INT_LIT8:
      ConvertArithOpLit(kOpXor, rl_dest, rl_src[0], vC);
      break;
    case Instruction::SHL_INT_LIT8:
      ConvertShiftLit(art::llvm::IntrinsicHelper::SHLInt,
                      rl_dest, rl_src[0], vC & 0x1f);
      break;
    case Instruction::SHR_INT_LIT8:
      ConvertShiftLit(art::llvm::IntrinsicHelper::SHRInt,
                      rl_dest, rl_src[0], vC & 0x1f);
      break;
    case Instruction::USHR_INT_LIT8:
      ConvertShiftLit(art::llvm::IntrinsicHelper::USHRInt,
                      rl_dest, rl_src[0], vC & 0x1f);
      break;

    case Instruction::ADD_FLOAT:
    case Instruction::ADD_FLOAT_2ADDR:
    case Instruction::ADD_DOUBLE:
    case Instruction::ADD_DOUBLE_2ADDR:
      ConvertFPArithOp(kOpAdd, rl_dest, rl_src[0], rl_src[1]);
      break;

    case Instruction::SUB_FLOAT:
    case Instruction::SUB_FLOAT_2ADDR:
    case Instruction::SUB_DOUBLE:
    case Instruction::SUB_DOUBLE_2ADDR:
      ConvertFPArithOp(kOpSub, rl_dest, rl_src[0], rl_src[1]);
      break;

    case Instruction::MUL_FLOAT:
    case Instruction::MUL_FLOAT_2ADDR:
    case Instruction::MUL_DOUBLE:
    case Instruction::MUL_DOUBLE_2ADDR:
      ConvertFPArithOp(kOpMul, rl_dest, rl_src[0], rl_src[1]);
      break;

    case Instruction::DIV_FLOAT:
    case Instruction::DIV_FLOAT_2ADDR:
    case Instruction::DIV_DOUBLE:
    case Instruction::DIV_DOUBLE_2ADDR:
      ConvertFPArithOp(kOpDiv, rl_dest, rl_src[0], rl_src[1]);
      break;

    case Instruction::REM_FLOAT:
    case Instruction::REM_FLOAT_2ADDR:
    case Instruction::REM_DOUBLE:
    case Instruction::REM_DOUBLE_2ADDR:
      ConvertFPArithOp(kOpRem, rl_dest, rl_src[0], rl_src[1]);
      break;

    case Instruction::INVOKE_STATIC:
      ConvertInvoke(bb, mir, kStatic, false /*range*/,
                    false /* NewFilledArray */);
      break;
    case Instruction::INVOKE_STATIC_RANGE:
      ConvertInvoke(bb, mir, kStatic, true /*range*/,
                    false /* NewFilledArray */);
      break;

    case Instruction::INVOKE_DIRECT:
      ConvertInvoke(bb,  mir, kDirect, false /*range*/,
                    false /* NewFilledArray */);
      break;
    case Instruction::INVOKE_DIRECT_RANGE:
      ConvertInvoke(bb, mir, kDirect, true /*range*/,
                    false /* NewFilledArray */);
      break;

    case Instruction::INVOKE_VIRTUAL:
      ConvertInvoke(bb, mir, kVirtual, false /*range*/,
                    false /* NewFilledArray */);
      break;
    case Instruction::INVOKE_VIRTUAL_RANGE:
      ConvertInvoke(bb, mir, kVirtual, true /*range*/,
                    false /* NewFilledArray */);
      break;

    case Instruction::INVOKE_SUPER:
      ConvertInvoke(bb, mir, kSuper, false /*range*/,
                    false /* NewFilledArray */);
      break;
    case Instruction::INVOKE_SUPER_RANGE:
      ConvertInvoke(bb, mir, kSuper, true /*range*/,
                    false /* NewFilledArray */);
      break;

    case Instruction::INVOKE_INTERFACE:
      ConvertInvoke(bb, mir, kInterface, false /*range*/,
                    false /* NewFilledArray */);
      break;
    case Instruction::INVOKE_INTERFACE_RANGE:
      ConvertInvoke(bb, mir, kInterface, true /*range*/,
                    false /* NewFilledArray */);
      break;
    case Instruction::FILLED_NEW_ARRAY:
      ConvertInvoke(bb, mir, kInterface, false /*range*/,
                    true /* NewFilledArray */);
      break;
    case Instruction::FILLED_NEW_ARRAY_RANGE:
      ConvertInvoke(bb, mir, kInterface, true /*range*/,
                    true /* NewFilledArray */);
      break;

    case Instruction::CONST_STRING:
    case Instruction::CONST_STRING_JUMBO:
      ConvertConstObject(vB, art::llvm::IntrinsicHelper::ConstString,
                         rl_dest);
      break;

    case Instruction::CONST_CLASS:
      ConvertConstObject(vB, art::llvm::IntrinsicHelper::ConstClass,
                         rl_dest);
      break;

    case Instruction::CHECK_CAST:
      ConvertCheckCast(vB, rl_src[0]);
      break;

    case Instruction::NEW_INSTANCE:
      ConvertNewInstance(vB, rl_dest);
      break;

    case Instruction::MOVE_EXCEPTION:
      ConvertMoveException(rl_dest);
      break;

    case Instruction::THROW:
      ConvertThrow(rl_src[0]);
      /*
       * If this throw is standalone, terminate.
       * If it might rethrow, force termination
       * of the following block.
       */
      if (bb->fall_through == NULL) {
        irb_->CreateUnreachable();
      } else {
        bb->fall_through->fall_through = NULL;
        bb->fall_through->taken = NULL;
      }
      break;

    case Instruction::MOVE_RESULT_WIDE:
    case Instruction::MOVE_RESULT:
    case Instruction::MOVE_RESULT_OBJECT:
      /*
       * All move_results should have been folded into the preceeding invoke.
       */
      LOG(FATAL) << "Unexpected move_result";
      break;

    case Instruction::MONITOR_ENTER:
      ConvertMonitorEnterExit(opt_flags,
                              art::llvm::IntrinsicHelper::MonitorEnter,
                              rl_src[0]);
      break;

    case Instruction::MONITOR_EXIT:
      ConvertMonitorEnterExit(opt_flags,
                              art::llvm::IntrinsicHelper::MonitorExit,
                              rl_src[0]);
      break;

    case Instruction::ARRAY_LENGTH:
      ConvertArrayLength(opt_flags, rl_dest, rl_src[0]);
      break;

    case Instruction::NEW_ARRAY:
      ConvertNewArray(vC, rl_dest, rl_src[0]);
      break;

    case Instruction::INSTANCE_OF:
      ConvertInstanceOf(vC, rl_dest, rl_src[0]);
      break;

    case Instruction::AGET:
      if (rl_dest.fp) {
        ConvertAget(opt_flags,
                    art::llvm::IntrinsicHelper::HLArrayGetFloat,
                    rl_dest, rl_src[0], rl_src[1]);
      } else {
        ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGet,
                    rl_dest, rl_src[0], rl_src[1]);
      }
      break;
    case Instruction::AGET_OBJECT:
      ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGetObject,
                  rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::AGET_BOOLEAN:
      ConvertAget(opt_flags,
                  art::llvm::IntrinsicHelper::HLArrayGetBoolean,
                  rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::AGET_BYTE:
      ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGetByte,
                  rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::AGET_CHAR:
      ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGetChar,
                  rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::AGET_SHORT:
      ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGetShort,
                  rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::AGET_WIDE:
      if (rl_dest.fp) {
        ConvertAget(opt_flags,
                    art::llvm::IntrinsicHelper::HLArrayGetDouble,
                    rl_dest, rl_src[0], rl_src[1]);
      } else {
        ConvertAget(opt_flags, art::llvm::IntrinsicHelper::HLArrayGetWide,
                    rl_dest, rl_src[0], rl_src[1]);
      }
      break;

    case Instruction::APUT:
      if (rl_src[0].fp) {
        ConvertAput(opt_flags,
                    art::llvm::IntrinsicHelper::HLArrayPutFloat,
                    rl_src[0], rl_src[1], rl_src[2]);
      } else {
        ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPut,
                    rl_src[0], rl_src[1], rl_src[2]);
      }
      break;
    case Instruction::APUT_OBJECT:
      ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPutObject,
                    rl_src[0], rl_src[1], rl_src[2]);
      break;
    case Instruction::APUT_BOOLEAN:
      ConvertAput(opt_flags,
                  art::llvm::IntrinsicHelper::HLArrayPutBoolean,
                    rl_src[0], rl_src[1], rl_src[2]);
      break;
    case Instruction::APUT_BYTE:
      ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPutByte,
                    rl_src[0], rl_src[1], rl_src[2]);
      break;
    case Instruction::APUT_CHAR:
      ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPutChar,
                    rl_src[0], rl_src[1], rl_src[2]);
      break;
    case Instruction::APUT_SHORT:
      ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPutShort,
                    rl_src[0], rl_src[1], rl_src[2]);
      break;
    case Instruction::APUT_WIDE:
      if (rl_src[0].fp) {
        ConvertAput(opt_flags,
                    art::llvm::IntrinsicHelper::HLArrayPutDouble,
                    rl_src[0], rl_src[1], rl_src[2]);
      } else {
        ConvertAput(opt_flags, art::llvm::IntrinsicHelper::HLArrayPutWide,
                    rl_src[0], rl_src[1], rl_src[2]);
      }
      break;

    case Instruction::IGET:
      if (rl_dest.fp) {
        ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetFloat,
                    rl_dest, rl_src[0], vC);
      } else {
        ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGet,
                    rl_dest, rl_src[0], vC);
      }
      break;
    case Instruction::IGET_OBJECT:
      ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetObject,
                  rl_dest, rl_src[0], vC);
      break;
    case Instruction::IGET_BOOLEAN:
      ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetBoolean,
                  rl_dest, rl_src[0], vC);
      break;
    case Instruction::IGET_BYTE:
      ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetByte,
                  rl_dest, rl_src[0], vC);
      break;
    case Instruction::IGET_CHAR:
      ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetChar,
                  rl_dest, rl_src[0], vC);
      break;
    case Instruction::IGET_SHORT:
      ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetShort,
                  rl_dest, rl_src[0], vC);
      break;
    case Instruction::IGET_WIDE:
      if (rl_dest.fp) {
        ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetDouble,
                    rl_dest, rl_src[0], vC);
      } else {
        ConvertIget(opt_flags, art::llvm::IntrinsicHelper::HLIGetWide,
                    rl_dest, rl_src[0], vC);
      }
      break;
    case Instruction::IPUT:
      if (rl_src[0].fp) {
        ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutFloat,
                    rl_src[0], rl_src[1], vC);
      } else {
        ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPut,
                    rl_src[0], rl_src[1], vC);
      }
      break;
    case Instruction::IPUT_OBJECT:
      ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutObject,
                  rl_src[0], rl_src[1], vC);
      break;
    case Instruction::IPUT_BOOLEAN:
      ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutBoolean,
                  rl_src[0], rl_src[1], vC);
      break;
    case Instruction::IPUT_BYTE:
      ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutByte,
                  rl_src[0], rl_src[1], vC);
      break;
    case Instruction::IPUT_CHAR:
      ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutChar,
                  rl_src[0], rl_src[1], vC);
      break;
    case Instruction::IPUT_SHORT:
      ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutShort,
                  rl_src[0], rl_src[1], vC);
      break;
    case Instruction::IPUT_WIDE:
      if (rl_src[0].fp) {
        ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutDouble,
                    rl_src[0], rl_src[1], vC);
      } else {
        ConvertIput(opt_flags, art::llvm::IntrinsicHelper::HLIPutWide,
                    rl_src[0], rl_src[1], vC);
      }
      break;

    case Instruction::FILL_ARRAY_DATA:
      ConvertFillArrayData(vB, rl_src[0]);
      break;

    case Instruction::LONG_TO_INT:
      ConvertLongToInt(rl_dest, rl_src[0]);
      break;

    case Instruction::INT_TO_LONG:
      ConvertIntToLong(rl_dest, rl_src[0]);
      break;

    case Instruction::INT_TO_CHAR:
      ConvertIntNarrowing(rl_dest, rl_src[0],
                          art::llvm::IntrinsicHelper::IntToChar);
      break;
    case Instruction::INT_TO_BYTE:
      ConvertIntNarrowing(rl_dest, rl_src[0],
                          art::llvm::IntrinsicHelper::IntToByte);
      break;
    case Instruction::INT_TO_SHORT:
      ConvertIntNarrowing(rl_dest, rl_src[0],
                          art::llvm::IntrinsicHelper::IntToShort);
      break;

    case Instruction::INT_TO_FLOAT:
    case Instruction::LONG_TO_FLOAT:
      ConvertIntToFP(irb_->getFloatTy(), rl_dest, rl_src[0]);
      break;

    case Instruction::INT_TO_DOUBLE:
    case Instruction::LONG_TO_DOUBLE:
      ConvertIntToFP(irb_->getDoubleTy(), rl_dest, rl_src[0]);
      break;

    case Instruction::FLOAT_TO_DOUBLE:
      ConvertFloatToDouble(rl_dest, rl_src[0]);
      break;

    case Instruction::DOUBLE_TO_FLOAT:
      ConvertDoubleToFloat(rl_dest, rl_src[0]);
      break;

    case Instruction::NEG_LONG:
    case Instruction::NEG_INT:
      ConvertNeg(rl_dest, rl_src[0]);
      break;

    case Instruction::NEG_FLOAT:
    case Instruction::NEG_DOUBLE:
      ConvertNegFP(rl_dest, rl_src[0]);
      break;

    case Instruction::NOT_LONG:
    case Instruction::NOT_INT:
      ConvertNot(rl_dest, rl_src[0]);
      break;

    case Instruction::FLOAT_TO_INT:
      ConvertFPToInt(art::llvm::IntrinsicHelper::F2I, rl_dest, rl_src[0]);
      break;

    case Instruction::DOUBLE_TO_INT:
      ConvertFPToInt(art::llvm::IntrinsicHelper::D2I, rl_dest, rl_src[0]);
      break;

    case Instruction::FLOAT_TO_LONG:
      ConvertFPToInt(art::llvm::IntrinsicHelper::F2L, rl_dest, rl_src[0]);
      break;

    case Instruction::DOUBLE_TO_LONG:
      ConvertFPToInt(art::llvm::IntrinsicHelper::D2L, rl_dest, rl_src[0]);
      break;

    case Instruction::CMPL_FLOAT:
      ConvertWideComparison(art::llvm::IntrinsicHelper::CmplFloat,
                            rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::CMPG_FLOAT:
      ConvertWideComparison(art::llvm::IntrinsicHelper::CmpgFloat,
                            rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::CMPL_DOUBLE:
      ConvertWideComparison(art::llvm::IntrinsicHelper::CmplDouble,
                            rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::CMPG_DOUBLE:
      ConvertWideComparison(art::llvm::IntrinsicHelper::CmpgDouble,
                            rl_dest, rl_src[0], rl_src[1]);
      break;
    case Instruction::CMP_LONG:
      ConvertWideComparison(art::llvm::IntrinsicHelper::CmpLong,
                            rl_dest, rl_src[0], rl_src[1]);
      break;

    case Instruction::PACKED_SWITCH:
      ConvertPackedSwitch(bb, vB, rl_src[0]);
      break;

    case Instruction::SPARSE_SWITCH:
      ConvertSparseSwitch(bb, vB, rl_src[0]);
      break;

    default:
      UNIMPLEMENTED(FATAL) << "Unsupported Dex opcode 0x" << std::hex << opcode;
      res = true;
  }
  return res;
}  // NOLINT(readability/fn_size)

void MirConverter::SetDexOffset(int32_t offset) {
  current_dalvik_offset_ = offset;
  ::llvm::SmallVector< ::llvm::Value*, 1> array_ref;
  array_ref.push_back(irb_->getInt32(offset));
  ::llvm::MDNode* node = ::llvm::MDNode::get(*context_, array_ref);
  irb_->SetDexOffset(node);
}

// Attach method info as metadata to special intrinsic
void MirConverter::SetMethodInfo() {
  // We don't want dex offset on this
  irb_->SetDexOffset(NULL);
  art::llvm::IntrinsicHelper::IntrinsicId id;
  id = art::llvm::IntrinsicHelper::MethodInfo;
  ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(id);
  ::llvm::Instruction* inst = irb_->CreateCall(intr);
  ::llvm::SmallVector< ::llvm::Value*, 2> reg_info;
  reg_info.push_back(irb_->getInt32(cu_->num_ins));
  reg_info.push_back(irb_->getInt32(cu_->num_regs));
  reg_info.push_back(irb_->getInt32(cu_->num_outs));
  reg_info.push_back(irb_->getInt32(cu_->num_compiler_temps));
  reg_info.push_back(irb_->getInt32(mir_graph_->GetNumSSARegs()));
  ::llvm::MDNode* reg_info_node = ::llvm::MDNode::get(*context_, reg_info);
  inst->setMetadata("RegInfo", reg_info_node);
  SetDexOffset(current_dalvik_offset_);
}

void MirConverter::HandlePhiNodes(BasicBlock* bb, ::llvm::BasicBlock* llvm_bb) {
  SetDexOffset(bb->start_offset);
  for (MIR* mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
    int opcode = mir->dalvikInsn.opcode;
    if (opcode < kMirOpFirst) {
      // Stop after first non-pseudo MIR op.
      continue;
    }
    if (opcode != kMirOpPhi) {
      // Skip other mir Pseudos.
      continue;
    }
    RegLocation rl_dest = mir_graph_->reg_location_[mir->ssa_rep->defs[0]];
    /*
     * The Art compiler's Phi nodes only handle 32-bit operands,
     * representing wide values using a matched set of Phi nodes
     * for the lower and upper halves.  In the llvm world, we only
     * want a single Phi for wides.  Here we will simply discard
     * the Phi node representing the high word.
     */
    if (rl_dest.high_word) {
      continue;  // No Phi node - handled via low word
    }
    int* incoming = reinterpret_cast<int*>(mir->dalvikInsn.vB);
    ::llvm::Type* phi_type =
        LlvmTypeFromLocRec(rl_dest);
    ::llvm::PHINode* phi = irb_->CreatePHI(phi_type, mir->ssa_rep->num_uses);
    for (int i = 0; i < mir->ssa_rep->num_uses; i++) {
      RegLocation loc;
      // Don't check width here.
      loc = mir_graph_->GetRawSrc(mir, i);
      DCHECK_EQ(rl_dest.wide, loc.wide);
      DCHECK_EQ(rl_dest.wide & rl_dest.high_word, loc.wide & loc.high_word);
      DCHECK_EQ(rl_dest.fp, loc.fp);
      DCHECK_EQ(rl_dest.core, loc.core);
      DCHECK_EQ(rl_dest.ref, loc.ref);
      SafeMap<unsigned int, unsigned int>::iterator it;
      it = mir_graph_->block_id_map_.find(incoming[i]);
      DCHECK(it != mir_graph_->block_id_map_.end());
      DCHECK(GetLLVMValue(loc.orig_sreg) != NULL);
      DCHECK(GetLLVMBlock(it->second) != NULL);
      phi->addIncoming(GetLLVMValue(loc.orig_sreg),
                       GetLLVMBlock(it->second));
    }
    DefineValueOnly(phi, rl_dest.orig_sreg);
  }
}

/* Extended MIR instructions like PHI */
void MirConverter::ConvertExtendedMIR(BasicBlock* bb, MIR* mir,
                                      ::llvm::BasicBlock* llvm_bb) {
  switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) {
    case kMirOpPhi: {
      // The llvm Phi node already emitted - just DefineValue() here.
      RegLocation rl_dest = mir_graph_->reg_location_[mir->ssa_rep->defs[0]];
      if (!rl_dest.high_word) {
        // Only consider low word of pairs.
        DCHECK(GetLLVMValue(rl_dest.orig_sreg) != NULL);
        ::llvm::Value* phi = GetLLVMValue(rl_dest.orig_sreg);
        if (1) SetVregOnValue(phi, rl_dest.orig_sreg);
      }
      break;
    }
    case kMirOpCopy: {
      UNIMPLEMENTED(WARNING) << "unimp kMirOpPhi";
      break;
    }
    case kMirOpNop:
      if ((mir == bb->last_mir_insn) && (bb->taken == NULL) &&
          (bb->fall_through == NULL)) {
        irb_->CreateUnreachable();
      }
      break;

    // TODO: need GBC intrinsic to take advantage of fused operations
    case kMirOpFusedCmplFloat:
      UNIMPLEMENTED(FATAL) << "kMirOpFusedCmpFloat unsupported";
      break;
    case kMirOpFusedCmpgFloat:
      UNIMPLEMENTED(FATAL) << "kMirOpFusedCmgFloat unsupported";
      break;
    case kMirOpFusedCmplDouble:
      UNIMPLEMENTED(FATAL) << "kMirOpFusedCmplDouble unsupported";
      break;
    case kMirOpFusedCmpgDouble:
      UNIMPLEMENTED(FATAL) << "kMirOpFusedCmpgDouble unsupported";
      break;
    case kMirOpFusedCmpLong:
      UNIMPLEMENTED(FATAL) << "kMirOpLongCmpBranch unsupported";
      break;
    default:
      break;
  }
}

/* Handle the content in each basic block */
bool MirConverter::BlockBitcodeConversion(BasicBlock* bb) {
  if (bb->block_type == kDead) return false;
  ::llvm::BasicBlock* llvm_bb = GetLLVMBlock(bb->id);
  if (llvm_bb == NULL) {
    CHECK(bb->block_type == kExitBlock);
  } else {
    irb_->SetInsertPoint(llvm_bb);
    SetDexOffset(bb->start_offset);
  }

  if (cu_->verbose) {
    LOG(INFO) << "................................";
    LOG(INFO) << "Block id " << bb->id;
    if (llvm_bb != NULL) {
      LOG(INFO) << "label " << llvm_bb->getName().str().c_str();
    } else {
      LOG(INFO) << "llvm_bb is NULL";
    }
  }

  if (bb->block_type == kEntryBlock) {
    SetMethodInfo();

    { // Allocate shadowframe.
      art::llvm::IntrinsicHelper::IntrinsicId id =
              art::llvm::IntrinsicHelper::AllocaShadowFrame;
      ::llvm::Function* func = intrinsic_helper_->GetIntrinsicFunction(id);
      ::llvm::Value* entries = irb_->getInt32(cu_->num_dalvik_registers);
      irb_->CreateCall(func, entries);
    }

    { // Store arguments to vregs.
      uint16_t arg_reg = cu_->num_regs;

      ::llvm::Function::arg_iterator arg_iter(func_->arg_begin());
      ::llvm::Function::arg_iterator arg_end(func_->arg_end());

      const char* shorty = cu_->shorty;
      uint32_t shorty_size = strlen(shorty);
      CHECK_GE(shorty_size, 1u);

      ++arg_iter; // skip method object

      if ((cu_->access_flags & kAccStatic) == 0) {
        SetVregOnValue(arg_iter, arg_reg);
        ++arg_iter;
        ++arg_reg;
      }

      for (uint32_t i = 1; i < shorty_size; ++i, ++arg_iter) {
        SetVregOnValue(arg_iter, arg_reg);

        ++arg_reg;
        if (shorty[i] == 'J' || shorty[i] == 'D') {
          // Wide types, such as long and double, are using a pair of registers
          // to store the value, so we have to increase arg_reg again.
          ++arg_reg;
        }
      }
    }
  } else if (bb->block_type == kExitBlock) {
    /*
     * Because of the differences between how MIR/LIR and llvm handle exit
     * blocks, we won't explicitly covert them.  On the llvm-to-lir
     * path, it will need to be regenereated.
     */
    return false;
  } else if (bb->block_type == kExceptionHandling) {
    /*
     * Because we're deferring null checking, delete the associated empty
     * exception block.
     */
    llvm_bb->eraseFromParent();
    return false;
  }

  HandlePhiNodes(bb, llvm_bb);

  for (MIR* mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
    SetDexOffset(mir->offset);

    int opcode = mir->dalvikInsn.opcode;
    Instruction::Format dalvik_format =
        Instruction::FormatOf(mir->dalvikInsn.opcode);

    if (opcode == kMirOpCheck) {
      // Combine check and work halves of throwing instruction.
      MIR* work_half = mir->meta.throw_insn;
      mir->dalvikInsn.opcode = work_half->dalvikInsn.opcode;
      opcode = mir->dalvikInsn.opcode;
      SSARepresentation* ssa_rep = work_half->ssa_rep;
      work_half->ssa_rep = mir->ssa_rep;
      mir->ssa_rep = ssa_rep;
      work_half->meta.original_opcode = work_half->dalvikInsn.opcode;
      work_half->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
      if (bb->successor_block_list.block_list_type == kCatch) {
        ::llvm::Function* intr = intrinsic_helper_->GetIntrinsicFunction(
            art::llvm::IntrinsicHelper::CatchTargets);
        ::llvm::Value* switch_key =
            irb_->CreateCall(intr, irb_->getInt32(mir->offset));
        GrowableArray<SuccessorBlockInfo*>::Iterator iter(bb->successor_block_list.blocks);
        // New basic block to use for work half
        ::llvm::BasicBlock* work_bb =
            ::llvm::BasicBlock::Create(*context_, "", func_);
        ::llvm::SwitchInst* sw =
            irb_->CreateSwitch(switch_key, work_bb,
                                     bb->successor_block_list.blocks->Size());
        while (true) {
          SuccessorBlockInfo *successor_block_info = iter.Next();
          if (successor_block_info == NULL) break;
          ::llvm::BasicBlock *target =
              GetLLVMBlock(successor_block_info->block->id);
          int type_index = successor_block_info->key;
          sw->addCase(irb_->getInt32(type_index), target);
        }
        llvm_bb = work_bb;
        irb_->SetInsertPoint(llvm_bb);
      }
    }

    if (opcode >= kMirOpFirst) {
      ConvertExtendedMIR(bb, mir, llvm_bb);
      continue;
    }

    bool not_handled = ConvertMIRNode(mir, bb, llvm_bb);
    if (not_handled) {
      Instruction::Code dalvik_opcode = static_cast<Instruction::Code>(opcode);
      LOG(WARNING) << StringPrintf("%#06x: Op %#x (%s) / Fmt %d not handled",
                                   mir->offset, opcode,
                                   Instruction::Name(dalvik_opcode),
                                   dalvik_format);
    }
  }

  if (bb->block_type == kEntryBlock) {
    entry_target_bb_ = GetLLVMBlock(bb->fall_through->id);
  } else if ((bb->fall_through != NULL) && !bb->terminated_by_return) {
    irb_->CreateBr(GetLLVMBlock(bb->fall_through->id));
  }

  return false;
}

char RemapShorty(char shorty_type) {
  /*
   * TODO: might want to revisit this.  Dalvik registers are 32-bits wide,
   * and longs/doubles are represented as a pair of registers.  When sub-word
   * arguments (and method results) are passed, they are extended to Dalvik
   * virtual register containers.  Because llvm is picky about type consistency,
   * we must either cast the "real" type to 32-bit container multiple Dalvik
   * register types, or always use the expanded values.
   * Here, we're doing the latter.  We map the shorty signature to container
   * types (which is valid so long as we always do a real expansion of passed
   * arguments and field loads).
   */
  switch (shorty_type) {
    case 'Z' : shorty_type = 'I'; break;
    case 'B' : shorty_type = 'I'; break;
    case 'S' : shorty_type = 'I'; break;
    case 'C' : shorty_type = 'I'; break;
    default: break;
  }
  return shorty_type;
}

::llvm::FunctionType* MirConverter::GetFunctionType() {
  // Get return type
  ::llvm::Type* ret_type = irb_->getJType(RemapShorty(cu_->shorty[0]));

  // Get argument type
  std::vector< ::llvm::Type*> args_type;

  // method object
  args_type.push_back(irb_->getJMethodTy());

  // Do we have  a "this"?
  if ((cu_->access_flags & kAccStatic) == 0) {
    args_type.push_back(irb_->getJObjectTy());
  }

  for (uint32_t i = 1; i < strlen(cu_->shorty); ++i) {
    args_type.push_back(irb_->getJType(RemapShorty(cu_->shorty[i])));
  }

  return ::llvm::FunctionType::get(ret_type, args_type, false);
}

bool MirConverter::CreateFunction() {
  ::llvm::FunctionType* func_type = GetFunctionType();
  if (func_type == NULL) {
    return false;
  }

  func_ = ::llvm::Function::Create(func_type,
                                      ::llvm::Function::InternalLinkage,
                                      symbol_, module_);

  ::llvm::Function::arg_iterator arg_iter(func_->arg_begin());
  ::llvm::Function::arg_iterator arg_end(func_->arg_end());

  arg_iter->setName("method");
  ++arg_iter;

  int start_sreg = cu_->num_regs;

  for (unsigned i = 0; arg_iter != arg_end; ++i, ++arg_iter) {
    arg_iter->setName(StringPrintf("v%i_0", start_sreg));
    start_sreg += mir_graph_->reg_location_[start_sreg].wide ? 2 : 1;
  }

  return true;
}

bool MirConverter::CreateLLVMBasicBlock(BasicBlock* bb) {
  // Skip the exit block
  if ((bb->block_type == kDead) ||(bb->block_type == kExitBlock)) {
    id_to_block_map_.Put(bb->id, NULL);
  } else {
    int offset = bb->start_offset;
    bool entry_block = (bb->block_type == kEntryBlock);
    ::llvm::BasicBlock* llvm_bb =
        ::llvm::BasicBlock::Create(*context_, entry_block ? "entry" :
                                 StringPrintf(kLabelFormat, bb->catch_entry ? kCatchBlock :
                                              kNormalBlock, offset, bb->id), func_);
    if (entry_block) {
        entry_bb_ = llvm_bb;
        placeholder_bb_ =
            ::llvm::BasicBlock::Create(*context_, "placeholder",
                                     func_);
    }
    id_to_block_map_.Put(bb->id, llvm_bb);
  }
  return false;
}


/*
 * Convert MIR to LLVM_IR
 *  o For each ssa name, create LLVM named value.  Type these
 *    appropriately, and ignore high half of wide and double operands.
 *  o For each MIR basic block, create an LLVM basic block.
 *  o Iterate through the MIR a basic block at a time, setting arguments
 *    to recovered ssa name.
 */
void MirConverter::MethodMIR2Bitcode() {
  InitIR();

  // Create the function
  CreateFunction();

  // Create an LLVM basic block for each MIR block in dfs preorder
  PreOrderDfsIterator iter(mir_graph_, false /* not iterative */);
  for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
    CreateLLVMBasicBlock(bb);
  }

  /*
   * Create an llvm named value for each MIR SSA name.  Note: we'll use
   * placeholders for all non-argument values (because we haven't seen
   * the definition yet).
   */
  irb_->SetInsertPoint(placeholder_bb_);
  ::llvm::Function::arg_iterator arg_iter(func_->arg_begin());
  arg_iter++;  /* Skip path method */
  for (int i = 0; i < mir_graph_->GetNumSSARegs(); i++) {
    ::llvm::Value* val;
    RegLocation rl_temp = mir_graph_->reg_location_[i];
    if ((mir_graph_->SRegToVReg(i) < 0) || rl_temp.high_word) {
      llvm_values_.Insert(0);
    } else if ((i < cu_->num_regs) ||
               (i >= (cu_->num_regs + cu_->num_ins))) {
      ::llvm::Constant* imm_value = mir_graph_->reg_location_[i].wide ?
         irb_->getJLong(0) : irb_->getJInt(0);
      val = EmitConst(imm_value, mir_graph_->reg_location_[i]);
      val->setName(mir_graph_->GetSSAName(i));
      llvm_values_.Insert(val);
    } else {
      // Recover previously-created argument values
      ::llvm::Value* arg_val = arg_iter++;
      llvm_values_.Insert(arg_val);
    }
  }

  PreOrderDfsIterator iter2(mir_graph_, false /* not iterative */);
  for (BasicBlock* bb = iter2.Next(); bb != NULL; bb = iter2.Next()) {
    BlockBitcodeConversion(bb);
  }

  /*
   * In a few rare cases of verification failure, the verifier will
   * replace one or more Dalvik opcodes with the special
   * throw-verification-failure opcode.  This can leave the SSA graph
   * in an invalid state, as definitions may be lost, while uses retained.
   * To work around this problem, we insert placeholder definitions for
   * all Dalvik SSA regs in the "placeholder" block.  Here, after
   * bitcode conversion is complete, we examine those placeholder definitions
   * and delete any with no references (which normally is all of them).
   *
   * If any definitions remain, we link the placeholder block into the
   * CFG.  Otherwise, it is deleted.
   */
  for (::llvm::BasicBlock::iterator it = placeholder_bb_->begin(),
       it_end = placeholder_bb_->end(); it != it_end;) {
    ::llvm::Instruction* inst = ::llvm::dyn_cast< ::llvm::Instruction>(it++);
    DCHECK(inst != NULL);
    ::llvm::Value* val = ::llvm::dyn_cast< ::llvm::Value>(inst);
    DCHECK(val != NULL);
    if (val->getNumUses() == 0) {
      inst->eraseFromParent();
    }
  }
  SetDexOffset(0);
  if (placeholder_bb_->empty()) {
    placeholder_bb_->eraseFromParent();
  } else {
    irb_->SetInsertPoint(placeholder_bb_);
    irb_->CreateBr(entry_target_bb_);
    entry_target_bb_ = placeholder_bb_;
  }
  irb_->SetInsertPoint(entry_bb_);
  irb_->CreateBr(entry_target_bb_);

  if (cu_->enable_debug & (1 << kDebugVerifyBitcode)) {
     if (::llvm::verifyFunction(*func_, ::llvm::PrintMessageAction)) {
       LOG(INFO) << "Bitcode verification FAILED for "
                 << PrettyMethod(cu_->method_idx, *cu_->dex_file)
                 << " of size " << cu_->code_item->insns_size_in_code_units_;
       cu_->enable_debug |= (1 << kDebugDumpBitcodeFile);
     }
  }

  if (cu_->enable_debug & (1 << kDebugDumpBitcodeFile)) {
    // Write bitcode to file
    std::string errmsg;
    std::string fname(PrettyMethod(cu_->method_idx, *cu_->dex_file));
    mir_graph_->ReplaceSpecialChars(fname);
    // TODO: make configurable change naming mechanism to avoid fname length issues.
    fname = StringPrintf("/sdcard/Bitcode/%s.bc", fname.c_str());

    if (fname.size() > 240) {
      LOG(INFO) << "Warning: bitcode filename too long. Truncated.";
      fname.resize(240);
    }

    ::llvm::OwningPtr< ::llvm::tool_output_file> out_file(
        new ::llvm::tool_output_file(fname.c_str(), errmsg,
                                   ::llvm::raw_fd_ostream::F_Binary));

    if (!errmsg.empty()) {
      LOG(ERROR) << "Failed to create bitcode output file: " << errmsg;
    }

    ::llvm::WriteBitcodeToFile(module_, out_file->os());
    out_file->keep();
  }
}

Backend* PortableCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
                               ArenaAllocator* const arena,
                               llvm::LlvmCompilationUnit* const llvm_compilation_unit) {
  return new MirConverter(cu, mir_graph, arena, llvm_compilation_unit);
}

}  // namespace art
