/*
 * 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 "compiler.h"
#include "compiler_internals.h"
#include "dataflow.h"
#include "ssa_transformation.h"
#include "leb128.h"
#include "mirror/object.h"
#include "runtime.h"
#include "codegen/codegen_util.h"
#include "codegen/mir_to_gbc.h"
#include "codegen/mir_to_lir.h"

#include <llvm/Support/Threading.h>

namespace {
#if !defined(ART_USE_LLVM_COMPILER)
  pthread_once_t llvm_multi_init = PTHREAD_ONCE_INIT;
#endif
  void InitializeLLVMForQuick() {
    llvm::llvm_start_multithreaded();
  }
}

namespace art {

LLVMInfo::LLVMInfo() {
#if !defined(ART_USE_LLVM_COMPILER)
  pthread_once(&llvm_multi_init, InitializeLLVMForQuick);
#endif
  // Create context, module, intrinsic helper & ir builder
  llvm_context_.reset(new llvm::LLVMContext());
  llvm_module_ = new llvm::Module("art", *llvm_context_);
  llvm::StructType::create(*llvm_context_, "JavaObject");
  intrinsic_helper_.reset( new greenland::IntrinsicHelper(*llvm_context_, *llvm_module_));
  ir_builder_.reset(new greenland::IRBuilder(*llvm_context_, *llvm_module_, *intrinsic_helper_));
}

LLVMInfo::~LLVMInfo() {
}

extern "C" void ArtInitQuickCompilerContext(art::Compiler& compiler) {
  CHECK(compiler.GetCompilerContext() == NULL);
  LLVMInfo* llvm_info = new LLVMInfo();
  compiler.SetCompilerContext(llvm_info);
}

extern "C" void ArtUnInitQuickCompilerContext(art::Compiler& compiler) {
  delete reinterpret_cast<LLVMInfo*>(compiler.GetCompilerContext());
  compiler.SetCompilerContext(NULL);
}

/* Default optimizer/debug setting for the compiler. */
static uint32_t kCompilerOptimizerDisableFlags = 0 | // Disable specific optimizations
  //(1 << kLoadStoreElimination) |
  //(1 << kLoadHoisting) |
  //(1 << kSuppressLoads) |
  //(1 << kNullCheckElimination) |
  //(1 << kPromoteRegs) |
  //(1 << kTrackLiveTemps) |
  //(1 << kSkipLargeMethodOptimization) |
  //(1 << kSafeOptimizations) |
  //(1 << kBBOpt) |
  //(1 << kMatch) |
  //(1 << kPromoteCompilerTemps) |
  0;

static uint32_t kCompilerDebugFlags = 0 |     // Enable debug/testing modes
  //(1 << kDebugDisplayMissingTargets) |
  //(1 << kDebugVerbose) |
  //(1 << kDebugDumpCFG) |
  //(1 << kDebugSlowFieldPath) |
  //(1 << kDebugSlowInvokePath) |
  //(1 << kDebugSlowStringPath) |
  //(1 << kDebugSlowestFieldPath) |
  //(1 << kDebugSlowestStringPath) |
  //(1 << kDebugExerciseResolveMethod) |
  //(1 << kDebugVerifyDataflow) |
  //(1 << kDebugShowMemoryUsage) |
  //(1 << kDebugShowNops) |
  //(1 << kDebugCountOpcodes) |
  //(1 << kDebugDumpCheckStats) |
  //(1 << kDebugDumpBitcodeFile) |
  //(1 << kDebugVerifyBitcode) |
  0;

static bool ContentIsInsn(const uint16_t* code_ptr) {
  uint16_t instr = *code_ptr;
  Instruction::Code opcode = static_cast<Instruction::Code>(instr & 0xff);

  /*
   * Since the low 8-bit in metadata may look like NOP, we need to check
   * both the low and whole sub-word to determine whether it is code or data.
   */
  return (opcode != Instruction::NOP || instr == 0);
}

/*
 * Parse an instruction, return the length of the instruction
 */
static int ParseInsn(CompilationUnit* cu, const uint16_t* code_ptr,
                     DecodedInstruction* decoded_instruction)
{
  // Don't parse instruction data
  if (!ContentIsInsn(code_ptr)) {
    return 0;
  }

  const Instruction* instruction = Instruction::At(code_ptr);
  *decoded_instruction = DecodedInstruction(instruction);

  return instruction->SizeInCodeUnits();
}

#define UNKNOWN_TARGET 0xffffffff

/* Split an existing block from the specified code offset into two */
static BasicBlock *SplitBlock(CompilationUnit* cu, unsigned int code_offset,
                              BasicBlock* orig_block, BasicBlock** immed_pred_block_p)
{
  MIR* insn = orig_block->first_mir_insn;
  while (insn) {
    if (insn->offset == code_offset) break;
    insn = insn->next;
  }
  if (insn == NULL) {
    LOG(FATAL) << "Break split failed";
  }
  BasicBlock *bottom_block = NewMemBB(cu, kDalvikByteCode,
                                     cu->num_blocks++);
  InsertGrowableList(cu, &cu->block_list, reinterpret_cast<uintptr_t>(bottom_block));

  bottom_block->start_offset = code_offset;
  bottom_block->first_mir_insn = insn;
  bottom_block->last_mir_insn = orig_block->last_mir_insn;

  /* Add it to the quick lookup cache */
  cu->block_map.Put(bottom_block->start_offset, bottom_block);

  /* Handle the taken path */
  bottom_block->taken = orig_block->taken;
  if (bottom_block->taken) {
    orig_block->taken = NULL;
    DeleteGrowableList(bottom_block->taken->predecessors, reinterpret_cast<uintptr_t>(orig_block));
    InsertGrowableList(cu, bottom_block->taken->predecessors,
                          reinterpret_cast<uintptr_t>(bottom_block));
  }

  /* Handle the fallthrough path */
  bottom_block->fall_through = orig_block->fall_through;
  orig_block->fall_through = bottom_block;
  InsertGrowableList(cu, bottom_block->predecessors,
                        reinterpret_cast<uintptr_t>(orig_block));
  if (bottom_block->fall_through) {
    DeleteGrowableList(bottom_block->fall_through->predecessors,
                          reinterpret_cast<uintptr_t>(orig_block));
    InsertGrowableList(cu, bottom_block->fall_through->predecessors,
                          reinterpret_cast<uintptr_t>(bottom_block));
  }

  /* Handle the successor list */
  if (orig_block->successor_block_list.block_list_type != kNotUsed) {
    bottom_block->successor_block_list = orig_block->successor_block_list;
    orig_block->successor_block_list.block_list_type = kNotUsed;
    GrowableListIterator iterator;

    GrowableListIteratorInit(&bottom_block->successor_block_list.blocks,
                                &iterator);
    while (true) {
      SuccessorBlockInfo *successor_block_info =
          reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iterator));
      if (successor_block_info == NULL) break;
      BasicBlock *bb = successor_block_info->block;
      DeleteGrowableList(bb->predecessors, reinterpret_cast<uintptr_t>(orig_block));
      InsertGrowableList(cu, bb->predecessors, reinterpret_cast<uintptr_t>(bottom_block));
    }
  }

  orig_block->last_mir_insn = insn->prev;

  insn->prev->next = NULL;
  insn->prev = NULL;
  /*
   * Update the immediate predecessor block pointer so that outgoing edges
   * can be applied to the proper block.
   */
  if (immed_pred_block_p) {
    DCHECK_EQ(*immed_pred_block_p, orig_block);
    *immed_pred_block_p = bottom_block;
  }
  return bottom_block;
}

/*
 * Given a code offset, find out the block that starts with it. If the offset
 * is in the middle of an existing block, split it into two.  If immed_pred_block_p
 * is not non-null and is the block being split, update *immed_pred_block_p to
 * point to the bottom block so that outgoing edges can be set up properly
 * (by the caller)
 * Utilizes a map for fast lookup of the typical cases.
 */
BasicBlock *FindBlock(CompilationUnit* cu, unsigned int code_offset,
                      bool split, bool create, BasicBlock** immed_pred_block_p)
{
  GrowableList* block_list = &cu->block_list;
  BasicBlock* bb;
  unsigned int i;
  SafeMap<unsigned int, BasicBlock*>::iterator it;

  it = cu->block_map.find(code_offset);
  if (it != cu->block_map.end()) {
    return it->second;
  } else if (!create) {
    return NULL;
  }

  if (split) {
    for (i = 0; i < block_list->num_used; i++) {
      bb = reinterpret_cast<BasicBlock*>(block_list->elem_list[i]);
      if (bb->block_type != kDalvikByteCode) continue;
      /* Check if a branch jumps into the middle of an existing block */
      if ((code_offset > bb->start_offset) && (bb->last_mir_insn != NULL) &&
          (code_offset <= bb->last_mir_insn->offset)) {
        BasicBlock *new_bb = SplitBlock(cu, code_offset, bb,
                                       bb == *immed_pred_block_p ?
                                       immed_pred_block_p : NULL);
        return new_bb;
      }
    }
  }

  /* Create a new one */
  bb = NewMemBB(cu, kDalvikByteCode, cu->num_blocks++);
  InsertGrowableList(cu, &cu->block_list, reinterpret_cast<uintptr_t>(bb));
  bb->start_offset = code_offset;
  cu->block_map.Put(bb->start_offset, bb);
  return bb;
}

/* Find existing block */
BasicBlock* FindBlock(CompilationUnit* cu, unsigned int code_offset)
{
  return FindBlock(cu, code_offset, false, false, NULL);
}

/* Turn method name into a legal Linux file name */
void ReplaceSpecialChars(std::string& str)
{
  static const struct { const char before; const char after; } match[] =
      {{'/','-'}, {';','#'}, {' ','#'}, {'$','+'},
       {'(','@'}, {')','@'}, {'<','='}, {'>','='}};
  for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) {
    std::replace(str.begin(), str.end(), match[i].before, match[i].after);
  }
}

/* Dump the CFG into a DOT graph */
void DumpCFG(CompilationUnit* cu, const char* dir_prefix, bool all_blocks)
{
  FILE* file;
  std::string fname(PrettyMethod(cu->method_idx, *cu->dex_file));
  ReplaceSpecialChars(fname);
  fname = StringPrintf("%s%s%x.dot", dir_prefix, fname.c_str(),
                      cu->entry_block->fall_through->start_offset);
  file = fopen(fname.c_str(), "w");
  if (file == NULL) {
    return;
  }
  fprintf(file, "digraph G {\n");

  fprintf(file, "  rankdir=TB\n");

  int num_blocks = all_blocks ? cu->num_blocks : cu->num_reachable_blocks;
  int idx;
  const GrowableList *block_list = &cu->block_list;

  for (idx = 0; idx < num_blocks; idx++) {
    int block_idx = all_blocks ? idx : cu->dfs_order.elem_list[idx];
    BasicBlock *bb = reinterpret_cast<BasicBlock*>(GrowableListGetElement(block_list, block_idx));
    if (bb == NULL) break;
    if (bb->block_type == kDead) continue;
    if (bb->block_type == kEntryBlock) {
      fprintf(file, "  entry_%d [shape=Mdiamond];\n", bb->id);
    } else if (bb->block_type == kExitBlock) {
      fprintf(file, "  exit_%d [shape=Mdiamond];\n", bb->id);
    } else if (bb->block_type == kDalvikByteCode) {
      fprintf(file, "  block%04x_%d [shape=record,label = \"{ \\\n",
              bb->start_offset, bb->id);
      const MIR *mir;
        fprintf(file, "    {block id %d\\l}%s\\\n", bb->id,
                bb->first_mir_insn ? " | " : " ");
        for (mir = bb->first_mir_insn; mir; mir = mir->next) {
            int opcode = mir->dalvikInsn.opcode;
            fprintf(file, "    {%04x %s %s %s\\l}%s\\\n", mir->offset,
                    mir->ssa_rep ? GetDalvikDisassembly(cu, mir) :
                    (opcode < kMirOpFirst) ?  Instruction::Name(mir->dalvikInsn.opcode) :
                    extended_mir_op_names[opcode - kMirOpFirst],
                    (mir->optimization_flags & MIR_IGNORE_RANGE_CHECK) != 0 ? " no_rangecheck" : " ",
                    (mir->optimization_flags & MIR_IGNORE_NULL_CHECK) != 0 ? " no_nullcheck" : " ",
                    mir->next ? " | " : " ");
        }
        fprintf(file, "  }\"];\n\n");
    } else if (bb->block_type == kExceptionHandling) {
      char block_name[BLOCK_NAME_LEN];

      GetBlockName(bb, block_name);
      fprintf(file, "  %s [shape=invhouse];\n", block_name);
    }

    char block_name1[BLOCK_NAME_LEN], block_name2[BLOCK_NAME_LEN];

    if (bb->taken) {
      GetBlockName(bb, block_name1);
      GetBlockName(bb->taken, block_name2);
      fprintf(file, "  %s:s -> %s:n [style=dotted]\n",
              block_name1, block_name2);
    }
    if (bb->fall_through) {
      GetBlockName(bb, block_name1);
      GetBlockName(bb->fall_through, block_name2);
      fprintf(file, "  %s:s -> %s:n\n", block_name1, block_name2);
    }

    if (bb->successor_block_list.block_list_type != kNotUsed) {
      fprintf(file, "  succ%04x_%d [shape=%s,label = \"{ \\\n",
              bb->start_offset, bb->id,
              (bb->successor_block_list.block_list_type == kCatch) ?
               "Mrecord" : "record");
      GrowableListIterator iterator;
      GrowableListIteratorInit(&bb->successor_block_list.blocks,
                                  &iterator);
      SuccessorBlockInfo *successor_block_info =
          reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iterator));

      int succ_id = 0;
      while (true) {
        if (successor_block_info == NULL) break;

        BasicBlock *dest_block = successor_block_info->block;
        SuccessorBlockInfo *next_successor_block_info =
            reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iterator));

        fprintf(file, "    {<f%d> %04x: %04x\\l}%s\\\n",
                succ_id++,
                successor_block_info->key,
                dest_block->start_offset,
                (next_successor_block_info != NULL) ? " | " : " ");

        successor_block_info = next_successor_block_info;
      }
      fprintf(file, "  }\"];\n\n");

      GetBlockName(bb, block_name1);
      fprintf(file, "  %s:s -> succ%04x_%d:n [style=dashed]\n",
              block_name1, bb->start_offset, bb->id);

      if (bb->successor_block_list.block_list_type == kPackedSwitch ||
          bb->successor_block_list.block_list_type == kSparseSwitch) {

        GrowableListIteratorInit(&bb->successor_block_list.blocks,
                                    &iterator);

        succ_id = 0;
        while (true) {
          SuccessorBlockInfo *successor_block_info =
              reinterpret_cast<SuccessorBlockInfo*>( GrowableListIteratorNext(&iterator));
          if (successor_block_info == NULL) break;

          BasicBlock *dest_block = successor_block_info->block;

          GetBlockName(dest_block, block_name2);
          fprintf(file, "  succ%04x_%d:f%d:e -> %s:n\n", bb->start_offset,
                  bb->id, succ_id++, block_name2);
        }
      }
    }
    fprintf(file, "\n");

    if (cu->verbose) {
      /* Display the dominator tree */
      GetBlockName(bb, block_name1);
      fprintf(file, "  cfg%s [label=\"%s\", shape=none];\n",
              block_name1, block_name1);
      if (bb->i_dom) {
        GetBlockName(bb->i_dom, block_name2);
        fprintf(file, "  cfg%s:s -> cfg%s:n\n\n", block_name2, block_name1);
      }
    }
  }
  fprintf(file, "}\n");
  fclose(file);
}

/* Verify if all the successor is connected with all the claimed predecessors */
static bool VerifyPredInfo(CompilationUnit* cu, BasicBlock* bb)
{
  GrowableListIterator iter;

  GrowableListIteratorInit(bb->predecessors, &iter);
  while (true) {
    BasicBlock *pred_bb = reinterpret_cast<BasicBlock*>(GrowableListIteratorNext(&iter));
    if (!pred_bb) break;
    bool found = false;
    if (pred_bb->taken == bb) {
        found = true;
    } else if (pred_bb->fall_through == bb) {
        found = true;
    } else if (pred_bb->successor_block_list.block_list_type != kNotUsed) {
      GrowableListIterator iterator;
      GrowableListIteratorInit(&pred_bb->successor_block_list.blocks,
                                  &iterator);
      while (true) {
        SuccessorBlockInfo *successor_block_info =
            reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iterator));
        if (successor_block_info == NULL) break;
        BasicBlock *succ_bb = successor_block_info->block;
        if (succ_bb == bb) {
            found = true;
            break;
        }
      }
    }
    if (found == false) {
      char block_name1[BLOCK_NAME_LEN], block_name2[BLOCK_NAME_LEN];
      GetBlockName(bb, block_name1);
      GetBlockName(pred_bb, block_name2);
      DumpCFG(cu, "/sdcard/cfg/", false);
      LOG(FATAL) << "Successor " << block_name1 << "not found from "
                 << block_name2;
    }
  }
  return true;
}

/* Identify code range in try blocks and set up the empty catch blocks */
static void ProcessTryCatchBlocks(CompilationUnit* cu)
{
  const DexFile::CodeItem* code_item = cu->code_item;
  int tries_size = code_item->tries_size_;
  int offset;

  if (tries_size == 0) {
    return;
  }

  ArenaBitVector* try_block_addr = cu->try_block_addr;

  for (int i = 0; i < tries_size; i++) {
    const DexFile::TryItem* pTry =
        DexFile::GetTryItems(*code_item, i);
    int start_offset = pTry->start_addr_;
    int end_offset = start_offset + pTry->insn_count_;
    for (offset = start_offset; offset < end_offset; offset++) {
      SetBit(cu, try_block_addr, offset);
    }
  }

  // Iterate over each of the handlers to enqueue the empty Catch blocks
  const byte* handlers_ptr = DexFile::GetCatchHandlerData(*code_item, 0);
  uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
  for (uint32_t idx = 0; idx < handlers_size; idx++) {
    CatchHandlerIterator iterator(handlers_ptr);
    for (; iterator.HasNext(); iterator.Next()) {
      uint32_t address = iterator.GetHandlerAddress();
      FindBlock(cu, address, false /* split */, true /*create*/,
                /* immed_pred_block_p */ NULL);
    }
    handlers_ptr = iterator.EndDataPointer();
  }
}

/* Process instructions with the kBranch flag */
static BasicBlock* ProcessCanBranch(CompilationUnit* cu, BasicBlock* cur_block,
                                    MIR* insn, int cur_offset, int width, int flags,
                                    const uint16_t* code_ptr, const uint16_t* code_end)
{
  int target = cur_offset;
  switch (insn->dalvikInsn.opcode) {
    case Instruction::GOTO:
    case Instruction::GOTO_16:
    case Instruction::GOTO_32:
      target += insn->dalvikInsn.vA;
      break;
    case Instruction::IF_EQ:
    case Instruction::IF_NE:
    case Instruction::IF_LT:
    case Instruction::IF_GE:
    case Instruction::IF_GT:
    case Instruction::IF_LE:
      cur_block->conditional_branch = true;
      target += insn->dalvikInsn.vC;
      break;
    case Instruction::IF_EQZ:
    case Instruction::IF_NEZ:
    case Instruction::IF_LTZ:
    case Instruction::IF_GEZ:
    case Instruction::IF_GTZ:
    case Instruction::IF_LEZ:
      cur_block->conditional_branch = true;
      target += insn->dalvikInsn.vB;
      break;
    default:
      LOG(FATAL) << "Unexpected opcode(" << insn->dalvikInsn.opcode << ") with kBranch set";
  }
  BasicBlock *taken_block = FindBlock(cu, target,
                                     /* split */
                                     true,
                                     /* create */
                                     true,
                                     /* immed_pred_block_p */
                                     &cur_block);
  cur_block->taken = taken_block;
  InsertGrowableList(cu, taken_block->predecessors, reinterpret_cast<uintptr_t>(cur_block));

  /* Always terminate the current block for conditional branches */
  if (flags & Instruction::kContinue) {
    BasicBlock *fallthrough_block = FindBlock(cu,
                                             cur_offset +  width,
                                             /*
                                              * If the method is processed
                                              * in sequential order from the
                                              * beginning, we don't need to
                                              * specify split for continue
                                              * blocks. However, this
                                              * routine can be called by
                                              * compileLoop, which starts
                                              * parsing the method from an
                                              * arbitrary address in the
                                              * method body.
                                              */
                                             true,
                                             /* create */
                                             true,
                                             /* immed_pred_block_p */
                                             &cur_block);
    cur_block->fall_through = fallthrough_block;
    InsertGrowableList(cu, fallthrough_block->predecessors,
                          reinterpret_cast<uintptr_t>(cur_block));
  } else if (code_ptr < code_end) {
    /* Create a fallthrough block for real instructions (incl. NOP) */
    if (ContentIsInsn(code_ptr)) {
      FindBlock(cu, cur_offset + width,
                /* split */
                false,
                /* create */
                true,
                /* immed_pred_block_p */
                NULL);
    }
  }
  return cur_block;
}

/* Process instructions with the kSwitch flag */
static void ProcessCanSwitch(CompilationUnit* cu, BasicBlock* cur_block,
                             MIR* insn, int cur_offset, int width, int flags)
{
  const uint16_t* switch_data =
      reinterpret_cast<const uint16_t*>(cu->insns + cur_offset + insn->dalvikInsn.vB);
  int size;
  const int* keyTable;
  const int* target_table;
  int i;
  int first_key;

  /*
   * Packed switch data format:
   *  ushort ident = 0x0100   magic value
   *  ushort size             number of entries in the table
   *  int first_key           first (and lowest) switch case value
   *  int targets[size]       branch targets, relative to switch opcode
   *
   * Total size is (4+size*2) 16-bit code units.
   */
  if (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) {
    DCHECK_EQ(static_cast<int>(switch_data[0]),
              static_cast<int>(Instruction::kPackedSwitchSignature));
    size = switch_data[1];
    first_key = switch_data[2] | (switch_data[3] << 16);
    target_table = reinterpret_cast<const int*>(&switch_data[4]);
    keyTable = NULL;        // Make the compiler happy
  /*
   * Sparse switch data format:
   *  ushort ident = 0x0200   magic value
   *  ushort size             number of entries in the table; > 0
   *  int keys[size]          keys, sorted low-to-high; 32-bit aligned
   *  int targets[size]       branch targets, relative to switch opcode
   *
   * Total size is (2+size*4) 16-bit code units.
   */
  } else {
    DCHECK_EQ(static_cast<int>(switch_data[0]),
              static_cast<int>(Instruction::kSparseSwitchSignature));
    size = switch_data[1];
    keyTable = reinterpret_cast<const int*>(&switch_data[2]);
    target_table = reinterpret_cast<const int*>(&switch_data[2 + size*2]);
    first_key = 0;   // To make the compiler happy
  }

  if (cur_block->successor_block_list.block_list_type != kNotUsed) {
    LOG(FATAL) << "Successor block list already in use: "
               << static_cast<int>(cur_block->successor_block_list.block_list_type);
  }
  cur_block->successor_block_list.block_list_type =
      (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
      kPackedSwitch : kSparseSwitch;
  CompilerInitGrowableList(cu, &cur_block->successor_block_list.blocks, size,
                      kListSuccessorBlocks);

  for (i = 0; i < size; i++) {
    BasicBlock *case_block = FindBlock(cu, cur_offset + target_table[i],
                                      /* split */
                                      true,
                                      /* create */
                                      true,
                                      /* immed_pred_block_p */
                                      &cur_block);
    SuccessorBlockInfo *successor_block_info =
        static_cast<SuccessorBlockInfo*>(NewMem(cu, sizeof(SuccessorBlockInfo),
                                         false, kAllocSuccessor));
    successor_block_info->block = case_block;
    successor_block_info->key =
        (insn->dalvikInsn.opcode == Instruction::PACKED_SWITCH) ?
        first_key + i : keyTable[i];
    InsertGrowableList(cu, &cur_block->successor_block_list.blocks,
                          reinterpret_cast<uintptr_t>(successor_block_info));
    InsertGrowableList(cu, case_block->predecessors,
                          reinterpret_cast<uintptr_t>(cur_block));
  }

  /* Fall-through case */
  BasicBlock* fallthrough_block = FindBlock(cu,
                                           cur_offset +  width,
                                           /* split */
                                           false,
                                           /* create */
                                           true,
                                           /* immed_pred_block_p */
                                           NULL);
  cur_block->fall_through = fallthrough_block;
  InsertGrowableList(cu, fallthrough_block->predecessors,
                        reinterpret_cast<uintptr_t>(cur_block));
}

/* Process instructions with the kThrow flag */
static BasicBlock* ProcessCanThrow(CompilationUnit* cu, BasicBlock* cur_block,
                                   MIR* insn, int cur_offset, int width, int flags,
                                   ArenaBitVector* try_block_addr, const uint16_t* code_ptr,
                                   const uint16_t* code_end)
{
  const DexFile::CodeItem* code_item = cu->code_item;
  bool in_try_block = IsBitSet(try_block_addr, cur_offset);

  /* In try block */
  if (in_try_block) {
    CatchHandlerIterator iterator(*code_item, cur_offset);

    if (cur_block->successor_block_list.block_list_type != kNotUsed) {
      LOG(INFO) << PrettyMethod(cu->method_idx, *cu->dex_file);
      LOG(FATAL) << "Successor block list already in use: "
                 << static_cast<int>(cur_block->successor_block_list.block_list_type);
    }

    cur_block->successor_block_list.block_list_type = kCatch;
    CompilerInitGrowableList(cu, &cur_block->successor_block_list.blocks, 2,
                        kListSuccessorBlocks);

    for (;iterator.HasNext(); iterator.Next()) {
      BasicBlock *catch_block = FindBlock(cu, iterator.GetHandlerAddress(),
                                         false /* split*/,
                                         false /* creat */,
                                         NULL  /* immed_pred_block_p */);
      catch_block->catch_entry = true;
      cu->catches.insert(catch_block->start_offset);
      SuccessorBlockInfo *successor_block_info = reinterpret_cast<SuccessorBlockInfo*>
          (NewMem(cu, sizeof(SuccessorBlockInfo), false, kAllocSuccessor));
      successor_block_info->block = catch_block;
      successor_block_info->key = iterator.GetHandlerTypeIndex();
      InsertGrowableList(cu, &cur_block->successor_block_list.blocks,
                            reinterpret_cast<uintptr_t>(successor_block_info));
      InsertGrowableList(cu, catch_block->predecessors,
                            reinterpret_cast<uintptr_t>(cur_block));
    }
  } else {
    BasicBlock *eh_block = NewMemBB(cu, kExceptionHandling,
                                   cu->num_blocks++);
    cur_block->taken = eh_block;
    InsertGrowableList(cu, &cu->block_list, reinterpret_cast<uintptr_t>(eh_block));
    eh_block->start_offset = cur_offset;
    InsertGrowableList(cu, eh_block->predecessors, reinterpret_cast<uintptr_t>(cur_block));
  }

  if (insn->dalvikInsn.opcode == Instruction::THROW){
    cur_block->explicit_throw = true;
    if ((code_ptr < code_end) && ContentIsInsn(code_ptr)) {
      // Force creation of new block following THROW via side-effect
      FindBlock(cu, cur_offset + width, /* split */ false,
                /* create */ true, /* immed_pred_block_p */ NULL);
    }
    if (!in_try_block) {
       // Don't split a THROW that can't rethrow - we're done.
      return cur_block;
    }
  }

  /*
   * Split the potentially-throwing instruction into two parts.
   * The first half will be a pseudo-op that captures the exception
   * edges and terminates the basic block.  It always falls through.
   * Then, create a new basic block that begins with the throwing instruction
   * (minus exceptions).  Note: this new basic block must NOT be entered into
   * the block_map.  If the potentially-throwing instruction is the target of a
   * future branch, we need to find the check psuedo half.  The new
   * basic block containing the work portion of the instruction should
   * only be entered via fallthrough from the block containing the
   * pseudo exception edge MIR.  Note also that this new block is
   * not automatically terminated after the work portion, and may
   * contain following instructions.
   */
  BasicBlock *new_block = NewMemBB(cu, kDalvikByteCode, cu->num_blocks++);
  InsertGrowableList(cu, &cu->block_list, reinterpret_cast<uintptr_t>(new_block));
  new_block->start_offset = insn->offset;
  cur_block->fall_through = new_block;
  InsertGrowableList(cu, new_block->predecessors, reinterpret_cast<uintptr_t>(cur_block));
  MIR* new_insn = static_cast<MIR*>(NewMem(cu, sizeof(MIR), true, kAllocMIR));
  *new_insn = *insn;
  insn->dalvikInsn.opcode =
      static_cast<Instruction::Code>(kMirOpCheck);
  // Associate the two halves
  insn->meta.throw_insn = new_insn;
  new_insn->meta.throw_insn = insn;
  AppendMIR(new_block, new_insn);
  return new_block;
}

void CompilerInit(CompilationUnit* cu, const Compiler& compiler) {
  bool success = false;
  switch (compiler.GetInstructionSet()) {
    case kThumb2:
      success = InitArmCodegen(cu);
      break;
    case kMips:
      success = InitMipsCodegen(cu);
      break;
    case kX86:
      success = InitX86Codegen(cu);
      break;
    default:;
  }
  if (!success) {
    LOG(FATAL) << "Failed to initialize codegen for " << compiler.GetInstructionSet();
  }
  if (!HeapInit(cu)) {
    LOG(FATAL) << "Failed to initialize oat heap";
  }
}

static CompiledMethod* CompileMethod(Compiler& compiler,
                                     const CompilerBackend compiler_backend,
                                     const DexFile::CodeItem* code_item,
                                     uint32_t access_flags, InvokeType invoke_type,
                                     uint32_t class_def_idx, uint32_t method_idx,
                                     jobject class_loader, const DexFile& dex_file,
                                     LLVMInfo* llvm_info)
{
  VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";

  const uint16_t* code_ptr = code_item->insns_;
  const uint16_t* code_end = code_item->insns_ + code_item->insns_size_in_code_units_;
  int num_blocks = 0;
  unsigned int cur_offset = 0;

  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
  UniquePtr<CompilationUnit> cu(new CompilationUnit);

  CompilerInit(cu.get(), compiler);

  cu->compiler = &compiler;
  cu->class_linker = class_linker;
  cu->dex_file = &dex_file;
  cu->class_def_idx = class_def_idx;
  cu->method_idx = method_idx;
  cu->code_item = code_item;
  cu->access_flags = access_flags;
  cu->invoke_type = invoke_type;
  cu->shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
  cu->instruction_set = compiler.GetInstructionSet();
  cu->insns = code_item->insns_;
  cu->insns_size = code_item->insns_size_in_code_units_;
  cu->num_ins = code_item->ins_size_;
  cu->num_regs = code_item->registers_size_ - cu->num_ins;
  cu->num_outs = code_item->outs_size_;
  DCHECK((cu->instruction_set == kThumb2) ||
         (cu->instruction_set == kX86) ||
         (cu->instruction_set == kMips));
  if ((compiler_backend == kQuickGBC) || (compiler_backend == kPortable)) {
    cu->gen_bitcode = true;
  }
  DCHECK_NE(compiler_backend, kIceland);  // TODO: remove when Portable/Iceland merge complete
  cu->llvm_info = llvm_info;
  /* Adjust this value accordingly once inlining is performed */
  cu->num_dalvik_registers = code_item->registers_size_;
  // TODO: set this from command line
  cu->compiler_flip_match = false;
  bool use_match = !cu->compiler_method_match.empty();
  bool match = use_match && (cu->compiler_flip_match ^
      (PrettyMethod(method_idx, dex_file).find(cu->compiler_method_match) !=
       std::string::npos));
  if (!use_match || match) {
    cu->disable_opt = kCompilerOptimizerDisableFlags;
    cu->enable_debug = kCompilerDebugFlags;
    cu->verbose = VLOG_IS_ON(compiler) ||
        (cu->enable_debug & (1 << kDebugVerbose));
  }
#ifndef NDEBUG
  if (cu->gen_bitcode) {
    cu->enable_debug |= (1 << kDebugVerifyBitcode);
  }
#endif

  if (cu->instruction_set == kMips) {
    // Disable some optimizations for mips for now
    cu->disable_opt |= (
        (1 << kLoadStoreElimination) |
        (1 << kLoadHoisting) |
        (1 << kSuppressLoads) |
        (1 << kNullCheckElimination) |
        (1 << kPromoteRegs) |
        (1 << kTrackLiveTemps) |
        (1 << kSkipLargeMethodOptimization) |
        (1 << kSafeOptimizations) |
        (1 << kBBOpt) |
        (1 << kMatch) |
        (1 << kPromoteCompilerTemps));
  }

  /* Gathering opcode stats? */
  if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
    cu->opcode_count =
        static_cast<int*>(NewMem(cu.get(), kNumPackedOpcodes * sizeof(int), true, kAllocMisc));
  }

  /* Assume non-throwing leaf */
  cu->attrs = (METHOD_IS_LEAF | METHOD_IS_THROW_FREE);

  /* Initialize the block list, estimate size based on insns_size */
  CompilerInitGrowableList(cu.get(), &cu->block_list, cu->insns_size,
                      kListBlockList);

  /* Initialize the switch_tables list */
  CompilerInitGrowableList(cu.get(), &cu->switch_tables, 4,
                      kListSwitchTables);

  /* Intialize the fill_array_data list */
  CompilerInitGrowableList(cu.get(), &cu->fill_array_data, 4,
                      kListFillArrayData);

  /* Intialize the throw_launchpads list, estimate size based on insns_size */
  CompilerInitGrowableList(cu.get(), &cu->throw_launchpads, cu->insns_size,
                      kListThrowLaunchPads);

  /* Intialize the instrinsic_launchpads list */
  CompilerInitGrowableList(cu.get(), &cu->intrinsic_launchpads, 4,
                      kListMisc);


  /* Intialize the suspend_launchpads list */
  CompilerInitGrowableList(cu.get(), &cu->suspend_launchpads, 2048,
                      kListSuspendLaunchPads);

  /* Allocate the bit-vector to track the beginning of basic blocks */
  ArenaBitVector *try_block_addr = AllocBitVector(cu.get(),
                                                   cu->insns_size,
                                                   true /* expandable */);
  cu->try_block_addr = try_block_addr;

  /* Create the default entry and exit blocks and enter them to the list */
  BasicBlock *entry_block = NewMemBB(cu.get(), kEntryBlock, num_blocks++);
  BasicBlock *exit_block = NewMemBB(cu.get(), kExitBlock, num_blocks++);

  cu->entry_block = entry_block;
  cu->exit_block = exit_block;

  InsertGrowableList(cu.get(), &cu->block_list, reinterpret_cast<uintptr_t>(entry_block));
  InsertGrowableList(cu.get(), &cu->block_list, reinterpret_cast<uintptr_t>(exit_block));

  /* Current block to record parsed instructions */
  BasicBlock *cur_block = NewMemBB(cu.get(), kDalvikByteCode, num_blocks++);
  cur_block->start_offset = 0;
  InsertGrowableList(cu.get(), &cu->block_list, reinterpret_cast<uintptr_t>(cur_block));
  /* Add first block to the fast lookup cache */
  cu->block_map.Put(cur_block->start_offset, cur_block);
  entry_block->fall_through = cur_block;
  InsertGrowableList(cu.get(), cur_block->predecessors,
                        reinterpret_cast<uintptr_t>(entry_block));

  /*
   * Store back the number of blocks since new blocks may be created of
   * accessing cu.
   */
  cu->num_blocks = num_blocks;

  /* Identify code range in try blocks and set up the empty catch blocks */
  ProcessTryCatchBlocks(cu.get());

  /* Set up for simple method detection */
  int num_patterns = sizeof(special_patterns)/sizeof(special_patterns[0]);
  bool live_pattern = (num_patterns > 0) && !(cu->disable_opt & (1 << kMatch));
  bool* dead_pattern =
      static_cast<bool*>(NewMem(cu.get(), sizeof(bool) * num_patterns, true, kAllocMisc));
  SpecialCaseHandler special_case = kNoHandler;
  int pattern_pos = 0;

  /* Parse all instructions and put them into containing basic blocks */
  while (code_ptr < code_end) {
    MIR *insn = static_cast<MIR *>(NewMem(cu.get(), sizeof(MIR), true, kAllocMIR));
    insn->offset = cur_offset;
    int width = ParseInsn(cu.get(), code_ptr, &insn->dalvikInsn);
    insn->width = width;
    Instruction::Code opcode = insn->dalvikInsn.opcode;
    if (cu->opcode_count != NULL) {
      cu->opcode_count[static_cast<int>(opcode)]++;
    }

    /* Terminate when the data section is seen */
    if (width == 0)
      break;

    /* Possible simple method? */
    if (live_pattern) {
      live_pattern = false;
      special_case = kNoHandler;
      for (int i = 0; i < num_patterns; i++) {
        if (!dead_pattern[i]) {
          if (special_patterns[i].opcodes[pattern_pos] == opcode) {
            live_pattern = true;
            special_case = special_patterns[i].handler_code;
          } else {
             dead_pattern[i] = true;
          }
        }
      }
    pattern_pos++;
    }

    AppendMIR(cur_block, insn);

    code_ptr += width;
    int flags = Instruction::FlagsOf(insn->dalvikInsn.opcode);

    int df_flags = oat_data_flow_attributes[insn->dalvikInsn.opcode];

    if (df_flags & DF_HAS_DEFS) {
      cu->def_count += (df_flags & DF_A_WIDE) ? 2 : 1;
    }

    if (flags & Instruction::kBranch) {
      cur_block = ProcessCanBranch(cu.get(), cur_block, insn, cur_offset,
                                  width, flags, code_ptr, code_end);
    } else if (flags & Instruction::kReturn) {
      cur_block->fall_through = exit_block;
      InsertGrowableList(cu.get(), exit_block->predecessors,
                            reinterpret_cast<uintptr_t>(cur_block));
      /*
       * Terminate the current block if there are instructions
       * afterwards.
       */
      if (code_ptr < code_end) {
        /*
         * Create a fallthrough block for real instructions
         * (incl. NOP).
         */
        if (ContentIsInsn(code_ptr)) {
            FindBlock(cu.get(), cur_offset + width,
                      /* split */
                      false,
                      /* create */
                      true,
                      /* immed_pred_block_p */
                      NULL);
        }
      }
    } else if (flags & Instruction::kThrow) {
      cur_block = ProcessCanThrow(cu.get(), cur_block, insn, cur_offset,
                                 width, flags, try_block_addr, code_ptr, code_end);
    } else if (flags & Instruction::kSwitch) {
      ProcessCanSwitch(cu.get(), cur_block, insn, cur_offset, width, flags);
    }
    cur_offset += width;
    BasicBlock *next_block = FindBlock(cu.get(), cur_offset,
                                      /* split */
                                      false,
                                      /* create */
                                      false,
                                      /* immed_pred_block_p */
                                      NULL);
    if (next_block) {
      /*
       * The next instruction could be the target of a previously parsed
       * forward branch so a block is already created. If the current
       * instruction is not an unconditional branch, connect them through
       * the fall-through link.
       */
      DCHECK(cur_block->fall_through == NULL ||
             cur_block->fall_through == next_block ||
             cur_block->fall_through == exit_block);

      if ((cur_block->fall_through == NULL) && (flags & Instruction::kContinue)) {
        cur_block->fall_through = next_block;
        InsertGrowableList(cu.get(), next_block->predecessors,
                              reinterpret_cast<uintptr_t>(cur_block));
      }
      cur_block = next_block;
    }
  }

  if (cu->enable_debug & (1 << kDebugDumpCFG)) {
    DumpCFG(cu.get(), "/sdcard/1_post_parse_cfg/", true);
  }

  if (!(cu->disable_opt & (1 << kSkipLargeMethodOptimization))) {
    if ((cu->num_blocks > MANY_BLOCKS) ||
        ((cu->num_blocks > MANY_BLOCKS_INITIALIZER) &&
      PrettyMethod(method_idx, dex_file, false).find("init>") !=
          std::string::npos)) {
        cu->qd_mode = true;
    }
  }

  if (cu->qd_mode) {
    // Bitcode generation requires full dataflow analysis
    cu->disable_dataflow = !cu->gen_bitcode;
    // Disable optimization which require dataflow/ssa
    cu->disable_opt |= (1 << kBBOpt) | (1 << kPromoteRegs) | (1 << kNullCheckElimination);
    if (cu->verbose) {
        LOG(INFO) << "QD mode enabled: "
                  << PrettyMethod(method_idx, dex_file)
                  << " num blocks: " << cu->num_blocks;
    }
  }

  if (cu->verbose) {
    DumpCompilationUnit(cu.get());
  }

  /* Do a code layout pass */
  CodeLayout(cu.get());

  if (cu->enable_debug & (1 << kDebugDumpCFG)) {
    DumpCFG(cu.get(), "/sdcard/2_post_layout_cfg/", true);
  }

  if (cu->enable_debug & (1 << kDebugVerifyDataflow)) {
    /* Verify if all blocks are connected as claimed */
    DataFlowAnalysisDispatcher(cu.get(), VerifyPredInfo, kAllNodes,
                                  false /* is_iterative */);
  }

  /* Perform SSA transformation for the whole method */
  SSATransformation(cu.get());

  if (cu->enable_debug & (1 << kDebugDumpCFG)) {
    DumpCFG(cu.get(), "/sdcard/3_post_ssa_cfg/", false);
  }

  /* Do constant propagation */
  // TODO: Probably need to make these expandable to support new ssa names
  // introducted during MIR optimization passes
  cu->is_constant_v = AllocBitVector(cu.get(), cu->num_ssa_regs,
                                         false  /* not expandable */);
  cu->constant_values =
      static_cast<int*>(NewMem(cu.get(), sizeof(int) * cu->num_ssa_regs, true, kAllocDFInfo));
  DataFlowAnalysisDispatcher(cu.get(), DoConstantPropogation,
                                kAllNodes,
                                false /* is_iterative */);

  /* Detect loops */
  LoopDetection(cu.get());

  /* Count uses */
  MethodUseCount(cu.get());

  /* Perform null check elimination */
  NullCheckElimination(cu.get());

  if (cu->enable_debug & (1 << kDebugDumpCFG)) {
    DumpCFG(cu.get(), "/sdcard/4_post_nce_cfg/", false);
  }

  /* Combine basic blocks where possible */
  BasicBlockCombine(cu.get());

  if (cu->enable_debug & (1 << kDebugDumpCFG)) {
    DumpCFG(cu.get(), "/sdcard/5_post_bbcombine_cfg/", false);
  }

  /* Do some basic block optimizations */
  BasicBlockOptimization(cu.get());

  // Debugging only
  if (cu->enable_debug & (1 << kDebugDumpCFG)) {
    DumpCFG(cu.get(), "/sdcard/6_post_bbo_cfg/", false);
  }

  if (cu->enable_debug & (1 << kDebugDumpCheckStats)) {
    DumpCheckStats(cu.get());
  }

  cu.get()->cg->CompilerInitializeRegAlloc(cu.get());  // Needs to happen after SSA naming

  /* Allocate Registers using simple local allocation scheme */
  SimpleRegAlloc(cu.get());

  if (cu->enable_debug & (1 << kDebugDumpCFG)) {
    DumpCFG(cu.get(), "/sdcard/7_post_ralloc_cfg/", true);
  }


  /* Go the LLVM path? */
  if (cu->gen_bitcode) {
    // MIR->Bitcode
    MethodMIR2Bitcode(cu.get());
    if (compiler_backend == kPortable) {
      // all done
      ArenaReset(cu.get());
      return NULL;
    }
    // Bitcode->LIR
    MethodBitcode2LIR(cu.get());
  } else {
    if (special_case != kNoHandler) {
      /*
       * Custom codegen for special cases.  If for any reason the
       * special codegen doesn't succeed, cu->first_lir_insn will
       * set to NULL;
       */
      SpecialMIR2LIR(cu.get(), special_case);
    }

    /* Convert MIR to LIR, etc. */
    if (cu->first_lir_insn == NULL) {
      MethodMIR2LIR(cu.get());
    }
  }

  /* Method is not empty */
  if (cu->first_lir_insn) {

    // mark the targets of switch statement case labels
    ProcessSwitchTables(cu.get());

    /* Convert LIR into machine code. */
    AssembleLIR(cu.get());

    if (cu->verbose) {
      CodegenDump(cu.get());
    }

    if (cu->opcode_count != NULL) {
      LOG(INFO) << "Opcode Count";
      for (int i = 0; i < kNumPackedOpcodes; i++) {
        if (cu->opcode_count[i] != 0) {
          LOG(INFO) << "-C- "
                    << Instruction::Name(static_cast<Instruction::Code>(i))
                    << " " << cu->opcode_count[i];
        }
      }
    }
  }

  // Combine vmap tables - core regs, then fp regs - into vmap_table
  std::vector<uint16_t> vmap_table;
  // Core regs may have been inserted out of order - sort first
  std::sort(cu->core_vmap_table.begin(), cu->core_vmap_table.end());
  for (size_t i = 0 ; i < cu->core_vmap_table.size(); i++) {
    // Copy, stripping out the phys register sort key
    vmap_table.push_back(~(-1 << VREG_NUM_WIDTH) & cu->core_vmap_table[i]);
  }
  // If we have a frame, push a marker to take place of lr
  if (cu->frame_size > 0) {
    vmap_table.push_back(INVALID_VREG);
  } else {
    DCHECK_EQ(__builtin_popcount(cu->core_spill_mask), 0);
    DCHECK_EQ(__builtin_popcount(cu->fp_spill_mask), 0);
  }
  // Combine vmap tables - core regs, then fp regs. fp regs already sorted
  for (uint32_t i = 0; i < cu->fp_vmap_table.size(); i++) {
    vmap_table.push_back(cu->fp_vmap_table[i]);
  }
  CompiledMethod* result =
      new CompiledMethod(cu->instruction_set, cu->code_buffer,
                         cu->frame_size, cu->core_spill_mask, cu->fp_spill_mask,
                         cu->combined_mapping_table, vmap_table, cu->native_gc_map);

  VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file)
     << " (" << (cu->code_buffer.size() * sizeof(cu->code_buffer[0]))
     << " bytes)";

#ifdef WITH_MEMSTATS
  if (cu->enable_debug & (1 << kDebugShowMemoryUsage)) {
    DumpMemStats(cu.get());
  }
#endif

  ArenaReset(cu.get());

  return result;
}

CompiledMethod* CompileOneMethod(Compiler& compiler,
                                 const CompilerBackend backend,
                                 const DexFile::CodeItem* code_item,
                                 uint32_t access_flags, InvokeType invoke_type,
                                 uint32_t class_def_idx, uint32_t method_idx, jobject class_loader,
                                 const DexFile& dex_file,
                                 LLVMInfo* llvm_info)
{
  return CompileMethod(compiler, backend, code_item, access_flags, invoke_type, class_def_idx,
                       method_idx, class_loader, dex_file, llvm_info);
}

}  // namespace art

extern "C" art::CompiledMethod*
    ArtQuickCompileMethod(art::Compiler& compiler,
                          const art::DexFile::CodeItem* code_item,
                          uint32_t access_flags, art::InvokeType invoke_type,
                          uint32_t class_def_idx, uint32_t method_idx, jobject class_loader,
                          const art::DexFile& dex_file)
{
  // TODO: check method fingerprint here to determine appropriate backend type.  Until then, use build default
  art::CompilerBackend backend = compiler.GetCompilerBackend();
  return art::CompileOneMethod(compiler, backend, code_item, access_flags, invoke_type,
                               class_def_idx, method_idx, class_loader, dex_file,
                               NULL /* use thread llvm_info */);
}
