/*
 * 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.
 */

namespace art {

void setMemRefType(LIR* lir, bool isLoad, int memType)
{
  u8 *maskPtr;
  u8 mask = ENCODE_MEM;;
  DCHECK(EncodingMap[lir->opcode].flags & (IS_LOAD | IS_STORE));
  if (isLoad) {
    maskPtr = &lir->useMask;
  } else {
    maskPtr = &lir->defMask;
  }
  /* Clear out the memref flags */
  *maskPtr &= ~mask;
  /* ..and then add back the one we need */
  switch (memType) {
    case kLiteral:
      DCHECK(isLoad);
      *maskPtr |= ENCODE_LITERAL;
      break;
    case kDalvikReg:
      *maskPtr |= ENCODE_DALVIK_REG;
      break;
    case kHeapRef:
      *maskPtr |= ENCODE_HEAP_REF;
      break;
    case kMustNotAlias:
      /* Currently only loads can be marked as kMustNotAlias */
      DCHECK(!(EncodingMap[lir->opcode].flags & IS_STORE));
      *maskPtr |= ENCODE_MUST_NOT_ALIAS;
      break;
    default:
      LOG(FATAL) << "Oat: invalid memref kind - " << memType;
  }
}

/*
 * Mark load/store instructions that access Dalvik registers through the stack.
 */
void annotateDalvikRegAccess(LIR* lir, int regId, bool isLoad, bool is64bit)
{
  setMemRefType(lir, isLoad, kDalvikReg);

  /*
   * Store the Dalvik register id in aliasInfo. Mark the MSB if it is a 64-bit
   * access.
   */
  lir->aliasInfo = regId;
  if (is64bit) {
    lir->aliasInfo |= 0x80000000;
  }
}

/*
 * Decode the register id.
 */
inline u8 getRegMaskCommon(int reg)
{
  u8 seed;
  int shift;

#if defined(TARGET_X86)
  int regId = reg & 0xf;
  /*
   * Double registers in x86 are just a single FP register
   */
  seed = 1;
#else
  int regId = reg & 0x1f;
  /*
   * Each double register is equal to a pair of single-precision FP registers
   */
  seed = DOUBLEREG(reg) ? 3 : 1;
#endif
  /* FP register starts at bit position 16 */
  shift = FPREG(reg) ? kFPReg0 : 0;
  /* Expand the double register id into single offset */
  shift += regId;
  return (seed << shift);
}

/*
 * Mark the corresponding bit(s).
 */
inline void setupRegMask(u8* mask, int reg)
{
  *mask |= getRegMaskCommon(reg);
}

/*
 * Set up the proper fields in the resource mask
 */
void setupResourceMasks(LIR* lir)
{
  int opcode = lir->opcode;
  int flags;

  if (opcode <= 0) {
    lir->useMask = lir->defMask = 0;
    return;
  }

  flags = EncodingMap[lir->opcode].flags;

  if (flags & NEEDS_FIXUP) {
    lir->flags.pcRelFixup = true;
  }

  /* Get the starting size of the instruction's template */
  lir->flags.size = oatGetInsnSize(lir);

  /* Set up the mask for resources that are updated */
  if (flags & (IS_LOAD | IS_STORE)) {
    /* Default to heap - will catch specialized classes later */
    setMemRefType(lir, flags & IS_LOAD, kHeapRef);
  }

  /*
   * Conservatively assume the branch here will call out a function that in
   * turn will trash everything.
   */
  if (flags & IS_BRANCH) {
    lir->defMask = lir->useMask = ENCODE_ALL;
    return;
  }

  if (flags & REG_DEF0) {
    setupRegMask(&lir->defMask, lir->operands[0]);
  }

  if (flags & REG_DEF1) {
    setupRegMask(&lir->defMask, lir->operands[1]);
  }

#if defined(TARGET_X86)
  if (flags & REG_DEFA) {
    setupRegMask(&lir->defMask, rAX);
  }

  if (flags & REG_DEFD) {
    setupRegMask(&lir->defMask, rDX);
  }
#endif

  if (flags & REG_DEF_SP) {
    lir->defMask |= ENCODE_REG_SP;
  }

#if !defined(TARGET_X86)
  if (flags & REG_DEF_LR) {
    lir->defMask |= ENCODE_REG_LR;
  }
#endif

#if defined(TARGET_ARM)
  if (flags & REG_DEF_LIST0) {
    lir->defMask |= ENCODE_REG_LIST(lir->operands[0]);
  }

  if (flags & REG_DEF_LIST1) {
    lir->defMask |= ENCODE_REG_LIST(lir->operands[1]);
  }

  if (flags & REG_DEF_FPCS_LIST0) {
    lir->defMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
  }

  if (flags & REG_DEF_FPCS_LIST2) {
    for (int i = 0; i < lir->operands[2]; i++) {
      setupRegMask(&lir->defMask, lir->operands[1] + i);
    }
  }
#endif

  if (flags & SETS_CCODES) {
    lir->defMask |= ENCODE_CCODE;
  }

#if defined(TARGET_ARM)
  /* Conservatively treat the IT block */
  if (flags & IS_IT) {
    lir->defMask = ENCODE_ALL;
  }
#endif

  if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
    int i;

    for (i = 0; i < 4; i++) {
      if (flags & (1 << (kRegUse0 + i))) {
        setupRegMask(&lir->useMask, lir->operands[i]);
      }
    }
  }

#if defined(TARGET_X86)
  if (flags & REG_USEA) {
    setupRegMask(&lir->useMask, rAX);
  }

  if (flags & REG_USEC) {
    setupRegMask(&lir->useMask, rCX);
  }

  if (flags & REG_USED) {
    setupRegMask(&lir->useMask, rDX);
  }
#endif

#if defined(TARGET_ARM)
  if (flags & REG_USE_PC) {
    lir->useMask |= ENCODE_REG_PC;
  }
#endif

  if (flags & REG_USE_SP) {
    lir->useMask |= ENCODE_REG_SP;
  }

#if defined(TARGET_ARM)
  if (flags & REG_USE_LIST0) {
    lir->useMask |= ENCODE_REG_LIST(lir->operands[0]);
  }

  if (flags & REG_USE_LIST1) {
    lir->useMask |= ENCODE_REG_LIST(lir->operands[1]);
  }

  if (flags & REG_USE_FPCS_LIST0) {
    lir->useMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
  }

  if (flags & REG_USE_FPCS_LIST2) {
    for (int i = 0; i < lir->operands[2]; i++) {
      setupRegMask(&lir->useMask, lir->operands[1] + i);
    }
  }
#endif

  if (flags & USES_CCODES) {
    lir->useMask |= ENCODE_CCODE;
  }

#if defined(TARGET_ARM)
  /* Fixup for kThumbPush/lr and kThumbPop/pc */
  if (opcode == kThumbPush || opcode == kThumbPop) {
    u8 r8Mask = getRegMaskCommon(r8);
    if ((opcode == kThumbPush) && (lir->useMask & r8Mask)) {
      lir->useMask &= ~r8Mask;
      lir->useMask |= ENCODE_REG_LR;
    } else if ((opcode == kThumbPop) && (lir->defMask & r8Mask)) {
      lir->defMask &= ~r8Mask;
      lir->defMask |= ENCODE_REG_PC;
    }
  }
#endif
}

/*
 * Debugging macros
 */
#define DUMP_RESOURCE_MASK(X)
#define DUMP_SSA_REP(X)

/* Pretty-print a LIR instruction */
void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr)
{
  LIR* lir = (LIR*) arg;
  int offset = lir->offset;
  int dest = lir->operands[0];
  const bool dumpNop = (cUnit->enableDebug & (1 << kDebugShowNops));

  /* Handle pseudo-ops individually, and all regular insns as a group */
  switch (lir->opcode) {
    case kPseudoMethodEntry:
      LOG(INFO) << "-------- method entry "
                << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
      break;
    case kPseudoMethodExit:
      LOG(INFO) << "-------- Method_Exit";
      break;
    case kPseudoBarrier:
      LOG(INFO) << "-------- BARRIER";
      break;
    case kPseudoExtended:
      LOG(INFO) << "-------- " << (char* ) dest;
      break;
    case kPseudoSSARep:
      DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " <<  (char* ) dest);
      break;
    case kPseudoEntryBlock:
      LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
      break;
    case kPseudoDalvikByteCodeBoundary:
      LOG(INFO) << "-------- dalvik offset: 0x" << std::hex
                << lir->dalvikOffset << " @ " << (char* )lir->operands[0];
      break;
    case kPseudoExitBlock:
      LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
      break;
    case kPseudoPseudoAlign4:
      LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex
                << offset << "): .align4";
      break;
    case kPseudoEHBlockLabel:
      LOG(INFO) << "Exception_Handling:";
      break;
    case kPseudoTargetLabel:
    case kPseudoNormalBlockLabel:
      LOG(INFO) << "L" << (void*)lir << ":";
      break;
    case kPseudoThrowTarget:
      LOG(INFO) << "LT" << (void*)lir << ":";
      break;
    case kPseudoIntrinsicRetry:
      LOG(INFO) << "IR" << (void*)lir << ":";
      break;
    case kPseudoSuspendTarget:
      LOG(INFO) << "LS" << (void*)lir << ":";
      break;
    case kPseudoCaseLabel:
      LOG(INFO) << "LC" << (void*)lir << ": Case target 0x"
                << std::hex << lir->operands[0] << "|" << std::dec <<
        lir->operands[0];
      break;
    default:
      if (lir->flags.isNop && !dumpNop) {
        break;
      } else {
        std::string op_name(buildInsnString(EncodingMap[lir->opcode].name,
                                            lir, baseAddr));
        std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt
                                              , lir, baseAddr));
        LOG(INFO) << StringPrintf("%05x: %-9s%s%s",
                                  (unsigned int)(baseAddr + offset),
                                  op_name.c_str(), op_operands.c_str(),
                                  lir->flags.isNop ? "(nop)" : "");
      }
      break;
  }

  if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
    DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->useMask, "use"));
  }
  if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
    DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, lir->defMask, "def"));
  }
}

void oatDumpPromotionMap(CompilationUnit *cUnit)
{
  int numRegs = cUnit->numDalvikRegisters + cUnit->numCompilerTemps + 1;
  for (int i = 0; i < numRegs; i++) {
    PromotionMap vRegMap = cUnit->promotionMap[i];
    std::string buf;
    if (vRegMap.fpLocation == kLocPhysReg) {
      StringAppendF(&buf, " : s%d", vRegMap.fpReg & FP_REG_MASK);
    }

    std::string buf3;
    if (i < cUnit->numDalvikRegisters) {
      StringAppendF(&buf3, "%02d", i);
    } else if (i == cUnit->methodSReg) {
      buf3 = "Method*";
    } else {
      StringAppendF(&buf3, "ct%d", i - cUnit->numDalvikRegisters);
    }

    LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(),
                              vRegMap.coreLocation == kLocPhysReg ?
                              "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
                              vRegMap.coreReg : oatSRegOffset(cUnit, i),
                              buf.c_str());
  }
}

/* Dump instructions and constant pool contents */
void oatCodegenDump(CompilationUnit* cUnit)
{
  LOG(INFO) << "Dumping LIR insns for "
            << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
  LIR* lirInsn;
  LIR* thisLIR;
  int insnsSize = cUnit->insnsSize;

  LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
  LOG(INFO) << "Ins          : " << cUnit->numIns;
  LOG(INFO) << "Outs         : " << cUnit->numOuts;
  LOG(INFO) << "CoreSpills       : " << cUnit->numCoreSpills;
  LOG(INFO) << "FPSpills       : " << cUnit->numFPSpills;
  LOG(INFO) << "CompilerTemps    : " << cUnit->numCompilerTemps;
  LOG(INFO) << "Frame size       : " << cUnit->frameSize;
  LOG(INFO) << "code size is " << cUnit->totalSize <<
    " bytes, Dalvik size is " << insnsSize * 2;
  LOG(INFO) << "expansion factor: "
            << (float)cUnit->totalSize / (float)(insnsSize * 2);
  oatDumpPromotionMap(cUnit);
  for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
    oatDumpLIRInsn(cUnit, lirInsn, 0);
  }
  for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) {
    thisLIR = (LIR*) lirInsn;
    LOG(INFO) << StringPrintf("%x (%04x): .class (%s)",
                              thisLIR->offset, thisLIR->offset,
                              ((CallsiteInfo *)
                              thisLIR->operands[0])->classDescriptor);
  }
  for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
    thisLIR = (LIR*) lirInsn;
    LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)",
                              thisLIR->offset, thisLIR->offset,
                              thisLIR->operands[0]);
  }

  const DexFile::MethodId& method_id =
      cUnit->dex_file->GetMethodId(cUnit->method_idx);
  std::string signature(cUnit->dex_file->GetMethodSignature(method_id));
  std::string name(cUnit->dex_file->GetMethodName(method_id));
  std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));

  // Dump mapping table
  if (cUnit->mappingTable.size() > 0) {
    std::string
        line(StringPrintf("\n  MappingTable %s%s_%s_mappingTable[%zu] = {",
                          descriptor.c_str(), name.c_str(), signature.c_str(),
                          cUnit->mappingTable.size()));
    std::replace(line.begin(), line.end(), ';', '_');
    LOG(INFO) << line;
    for (uint32_t i = 0; i < cUnit->mappingTable.size(); i+=2) {
      line = StringPrintf("    {0x%05x, 0x%04x},",
                          cUnit->mappingTable[i], cUnit->mappingTable[i+1]);
      LOG(INFO) << line;
    }
    LOG(INFO) <<"  };\n\n";
  }
}


LIR* rawLIR(CompilationUnit* cUnit, int dalvikOffset, int opcode, int op0,
      int op1, int op2, int op3, int op4, LIR* target)
{
  LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
  insn->dalvikOffset = dalvikOffset;
  insn->opcode = opcode;
  insn->operands[0] = op0;
  insn->operands[1] = op1;
  insn->operands[2] = op2;
  insn->operands[3] = op3;
  insn->operands[4] = op4;
  insn->target = target;
  oatSetupResourceMasks(insn);
  if (opcode == kPseudoTargetLabel) {
    // Always make labels scheduling barriers
    insn->defMask = ENCODE_ALL;
  }
  return insn;
}

/*
 * The following are building blocks to construct low-level IRs with 0 - 4
 * operands.
 */
LIR* newLIR0(CompilationUnit* cUnit, int opcode)
{
  DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND))
      << EncodingMap[opcode].name << " " << (int)opcode << " "
      << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
      << cUnit->currentDalvikOffset;
  LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode);
  oatAppendLIR(cUnit, (LIR*) insn);
  return insn;
}

LIR* newLIR1(CompilationUnit* cUnit, int opcode,
               int dest)
{
  DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP))
      << EncodingMap[opcode].name << " " << (int)opcode << " "
      << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
      << cUnit->currentDalvikOffset;
  LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest);
  oatAppendLIR(cUnit, (LIR*) insn);
  return insn;
}

LIR* newLIR2(CompilationUnit* cUnit, int opcode,
               int dest, int src1)
{
  DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_BINARY_OP))
      << EncodingMap[opcode].name << " " << (int)opcode << " "
      << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
      << cUnit->currentDalvikOffset;
  LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1);
  oatAppendLIR(cUnit, (LIR*) insn);
  return insn;
}

LIR* newLIR3(CompilationUnit* cUnit, int opcode,
               int dest, int src1, int src2)
{
  DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_TERTIARY_OP))
      << EncodingMap[opcode].name << " " << (int)opcode << " "
      << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
      << cUnit->currentDalvikOffset;
  LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
                     src2);
  oatAppendLIR(cUnit, (LIR*) insn);
  return insn;
}

LIR* newLIR4(CompilationUnit* cUnit, int opcode,
      int dest, int src1, int src2, int info)
{
  DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUAD_OP))
      << EncodingMap[opcode].name << " " << (int)opcode << " "
      << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
      << cUnit->currentDalvikOffset;
  LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
                     src2, info);
  oatAppendLIR(cUnit, (LIR*) insn);
  return insn;
}

LIR* newLIR5(CompilationUnit* cUnit, int opcode,
       int dest, int src1, int src2, int info1, int info2)
{
  DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUIN_OP))
      << EncodingMap[opcode].name << " " << (int)opcode << " "
      << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
      << cUnit->currentDalvikOffset;
  LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
                     src2, info1, info2);
  oatAppendLIR(cUnit, (LIR*) insn);
  return insn;
}

/*
 * Search the existing constants in the literal pool for an exact or close match
 * within specified delta (greater or equal to 0).
 */
LIR* scanLiteralPool(LIR* dataTarget, int value, unsigned int delta)
{
  while (dataTarget) {
    if (((unsigned) (value - ((LIR* ) dataTarget)->operands[0])) <= delta)
      return (LIR* ) dataTarget;
    dataTarget = dataTarget->next;
  }
  return NULL;
}

/* Search the existing constants in the literal pool for an exact wide match */
LIR* scanLiteralPoolWide(LIR* dataTarget, int valLo, int valHi)
{
  bool loMatch = false;
  LIR* loTarget = NULL;
  while (dataTarget) {
    if (loMatch && (((LIR*)dataTarget)->operands[0] == valHi)) {
      return (LIR*)loTarget;
    }
    loMatch = false;
    if (((LIR*)dataTarget)->operands[0] == valLo) {
      loMatch = true;
      loTarget = dataTarget;
    }
    dataTarget = dataTarget->next;
  }
  return NULL;
}

/*
 * The following are building blocks to insert constants into the pool or
 * instruction streams.
 */

/* Add a 32-bit constant either in the constant pool */
LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP, int value)
{
  /* Add the constant to the literal pool */
  if (constantListP) {
    LIR* newValue = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocData);
    newValue->operands[0] = value;
    newValue->next = *constantListP;
    *constantListP = (LIR*) newValue;
    return newValue;
  }
  return NULL;
}

/* Add a 64-bit constant to the constant pool or mixed with code */
LIR* addWideData(CompilationUnit* cUnit, LIR* *constantListP,
               int valLo, int valHi)
{
  //FIXME: hard-coded little endian, need BE variant
  // Insert high word into list first
  addWordData(cUnit, constantListP, valHi);
  return addWordData(cUnit, constantListP, valLo);
}

void pushWord(std::vector<uint8_t>&buf, int data) {
  buf.push_back( data & 0xff);
  buf.push_back( (data >> 8) & 0xff);
  buf.push_back( (data >> 16) & 0xff);
  buf.push_back( (data >> 24) & 0xff);
}

void alignBuffer(std::vector<uint8_t>&buf, size_t offset) {
  while (buf.size() < offset) {
    buf.push_back(0);
  }
}

bool IsDirect(int invokeType) {
  InvokeType type = static_cast<InvokeType>(invokeType);
  return type == kStatic || type == kDirect;
}

/* Write the literal pool to the output stream */
void installLiteralPools(CompilationUnit* cUnit)
{
  alignBuffer(cUnit->codeBuffer, cUnit->dataOffset);
  LIR* dataLIR = cUnit->literalList;
  while (dataLIR != NULL) {
    pushWord(cUnit->codeBuffer, dataLIR->operands[0]);
    dataLIR = NEXT_LIR(dataLIR);
  }
  // Push code and method literals, record offsets for the compiler to patch.
  dataLIR = cUnit->codeLiteralList;
  if (dataLIR != NULL) {
    while (dataLIR != NULL) {
      uint32_t target = dataLIR->operands[0];
      cUnit->compiler->AddCodePatch(cUnit->dex_cache, cUnit->dex_file,
                                    cUnit->method_idx,
                                    cUnit->access_flags,
                                    target,
                                    IsDirect(dataLIR->operands[1]),
                                    cUnit->codeBuffer.size());
      const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
      // unique based on target to ensure code deduplication works
      uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
      pushWord(cUnit->codeBuffer, unique_patch_value);
      dataLIR = NEXT_LIR(dataLIR);
    }
    dataLIR = cUnit->methodLiteralList;
    while (dataLIR != NULL) {
      uint32_t target = dataLIR->operands[0];
      cUnit->compiler->AddMethodPatch(cUnit->dex_cache, cUnit->dex_file,
                                      cUnit->method_idx,
                                      cUnit->access_flags,
                                      target,
                                      IsDirect(dataLIR->operands[1]),
                                      cUnit->codeBuffer.size());
      const DexFile::MethodId& id = cUnit->dex_file->GetMethodId(target);
      // unique based on target to ensure code deduplication works
      uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
      pushWord(cUnit->codeBuffer, unique_patch_value);
      dataLIR = NEXT_LIR(dataLIR);
    }
  }

}

/* Write the switch tables to the output stream */
void installSwitchTables(CompilationUnit* cUnit)
{
  GrowableListIterator iterator;
  oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
  while (true) {
    SwitchTable* tabRec = (SwitchTable *) oatGrowableListIteratorNext(
       &iterator);
    if (tabRec == NULL) break;
    alignBuffer(cUnit->codeBuffer, tabRec->offset);
    /*
     * For Arm, our reference point is the address of the bx
     * instruction that does the launch, so we have to subtract
     * the auto pc-advance.  For other targets the reference point
     * is a label, so we can use the offset as-is.
     */
#if defined(TARGET_ARM)
    int bxOffset = tabRec->anchor->offset + 4;
#elif defined(TARGET_X86)
    int bxOffset = 0;
#else
    int bxOffset = tabRec->anchor->offset;
#endif
    if (cUnit->printMe) {
      LOG(INFO) << "Switch table for offset 0x" << std::hex << bxOffset;
    }
    if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
      int* keys = (int*)&(tabRec->table[2]);
      for (int elems = 0; elems < tabRec->table[1]; elems++) {
        int disp = tabRec->targets[elems]->offset - bxOffset;
        if (cUnit->printMe) {
          LOG(INFO) << "  Case[" << elems << "] key: 0x"
                    << std::hex << keys[elems] << ", disp: 0x"
                    << std::hex << disp;
        }
        pushWord(cUnit->codeBuffer, keys[elems]);
        pushWord(cUnit->codeBuffer,
          tabRec->targets[elems]->offset - bxOffset);
      }
    } else {
      DCHECK_EQ(static_cast<int>(tabRec->table[0]),
                static_cast<int>(Instruction::kPackedSwitchSignature));
      for (int elems = 0; elems < tabRec->table[1]; elems++) {
        int disp = tabRec->targets[elems]->offset - bxOffset;
        if (cUnit->printMe) {
          LOG(INFO) << "  Case[" << elems << "] disp: 0x"
                    << std::hex << disp;
        }
        pushWord(cUnit->codeBuffer, tabRec->targets[elems]->offset - bxOffset);
      }
    }
  }
}

/* Write the fill array dta to the output stream */
void installFillArrayData(CompilationUnit* cUnit)
{
  GrowableListIterator iterator;
  oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
  while (true) {
    FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
       &iterator);
    if (tabRec == NULL) break;
    alignBuffer(cUnit->codeBuffer, tabRec->offset);
    for (int i = 0; i < (tabRec->size + 1) / 2; i++) {
      cUnit->codeBuffer.push_back( tabRec->table[i] & 0xFF);
      cUnit->codeBuffer.push_back( (tabRec->table[i] >> 8) & 0xFF);
    }
  }
}

int assignLiteralOffsetCommon(LIR* lir, int offset)
{
  for (;lir != NULL; lir = lir->next) {
    lir->offset = offset;
    offset += 4;
  }
  return offset;
}

void createMappingTable(CompilationUnit* cUnit)
{
  LIR* tgtLIR;
  int currentDalvikOffset = -1;

  for (tgtLIR = (LIR *) cUnit->firstLIRInsn;
     tgtLIR;
     tgtLIR = NEXT_LIR(tgtLIR)) {
    if ((tgtLIR->opcode >= 0) && !tgtLIR->flags.isNop &&
      (currentDalvikOffset != tgtLIR->dalvikOffset)) {
      // Changed - need to emit a record
      cUnit->mappingTable.push_back(tgtLIR->offset);
      cUnit->mappingTable.push_back(tgtLIR->dalvikOffset);
      currentDalvikOffset = tgtLIR->dalvikOffset;
    }
  }
}

/* Determine the offset of each literal field */
int assignLiteralOffset(CompilationUnit* cUnit, int offset)
{
  offset = assignLiteralOffsetCommon(cUnit->literalList, offset);
  offset = assignLiteralOffsetCommon(cUnit->codeLiteralList, offset);
  offset = assignLiteralOffsetCommon(cUnit->methodLiteralList, offset);
  return offset;
}

int assignSwitchTablesOffset(CompilationUnit* cUnit, int offset)
{
  GrowableListIterator iterator;
  oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
  while (true) {
    SwitchTable *tabRec = (SwitchTable *) oatGrowableListIteratorNext(
       &iterator);
    if (tabRec == NULL) break;
    tabRec->offset = offset;
    if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
      offset += tabRec->table[1] * (sizeof(int) * 2);
    } else {
      DCHECK_EQ(static_cast<int>(tabRec->table[0]),
                static_cast<int>(Instruction::kPackedSwitchSignature));
      offset += tabRec->table[1] * sizeof(int);
    }
  }
  return offset;
}

int assignFillArrayDataOffset(CompilationUnit* cUnit, int offset)
{
  GrowableListIterator iterator;
  oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
  while (true) {
    FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
       &iterator);
    if (tabRec == NULL) break;
    tabRec->offset = offset;
    offset += tabRec->size;
    // word align
    offset = (offset + 3) & ~3;
    }
  return offset;
}

/*
 * Walk the compilation unit and assign offsets to instructions
 * and literals and compute the total size of the compiled unit.
 */
void oatAssignOffsets(CompilationUnit* cUnit)
{
  int offset = oatAssignInsnOffsets(cUnit);

  /* Const values have to be word aligned */
  offset = (offset + 3) & ~3;

  /* Set up offsets for literals */
  cUnit->dataOffset = offset;

  offset = assignLiteralOffset(cUnit, offset);

  offset = assignSwitchTablesOffset(cUnit, offset);

  offset = assignFillArrayDataOffset(cUnit, offset);

  cUnit->totalSize = offset;
}

/*
 * Go over each instruction in the list and calculate the offset from the top
 * before sending them off to the assembler. If out-of-range branch distance is
 * seen rearrange the instructions a bit to correct it.
 */
void oatAssembleLIR(CompilationUnit* cUnit)
{
  oatAssignOffsets(cUnit);
  /*
   * Assemble here.  Note that we generate code with optimistic assumptions
   * and if found now to work, we'll have to redo the sequence and retry.
   */

  while (true) {
    AssemblerStatus res = oatAssembleInstructions(cUnit, 0);
    if (res == kSuccess) {
      break;
    } else {
      cUnit->assemblerRetries++;
      if (cUnit->assemblerRetries > MAX_ASSEMBLER_RETRIES) {
        oatCodegenDump(cUnit);
        LOG(FATAL) << "Assembler error - too many retries";
      }
      // Redo offsets and try again
      oatAssignOffsets(cUnit);
      cUnit->codeBuffer.clear();
    }
  }

  // Install literals
  installLiteralPools(cUnit);

  // Install switch tables
  installSwitchTables(cUnit);

  // Install fill array data
  installFillArrayData(cUnit);

  /*
   * Create the mapping table
   */
  createMappingTable(cUnit);
}

/*
 * Insert a kPseudoCaseLabel at the beginning of the Dalvik
 * offset vaddr.  This label will be used to fix up the case
 * branch table during the assembly phase.  Be sure to set
 * all resource flags on this to prevent code motion across
 * target boundaries.  KeyVal is just there for debugging.
 */
LIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal)
{
  SafeMap<unsigned int, LIR*>::iterator it;
  it = cUnit->boundaryMap.find(vaddr);
  if (it == cUnit->boundaryMap.end()) {
    LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
  }
  LIR* newLabel = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
  newLabel->dalvikOffset = vaddr;
  newLabel->opcode = kPseudoCaseLabel;
  newLabel->operands[0] = keyVal;
  oatInsertLIRAfter(it->second, (LIR*)newLabel);
  return newLabel;
}

void markPackedCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
{
  const u2* table = tabRec->table;
  int baseVaddr = tabRec->vaddr;
  int *targets = (int*)&table[4];
  int entries = table[1];
  int lowKey = s4FromSwitchData(&table[2]);
  for (int i = 0; i < entries; i++) {
    tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
                                         i + lowKey);
  }
}

void markSparseCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
{
  const u2* table = tabRec->table;
  int baseVaddr = tabRec->vaddr;
  int entries = table[1];
  int* keys = (int*)&table[2];
  int* targets = &keys[entries];
  for (int i = 0; i < entries; i++) {
    tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
                                         keys[i]);
  }
}

void oatProcessSwitchTables(CompilationUnit* cUnit)
{
  GrowableListIterator iterator;
  oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
  while (true) {
    SwitchTable *tabRec =
        (SwitchTable *) oatGrowableListIteratorNext(&iterator);
    if (tabRec == NULL) break;
    if (tabRec->table[0] == Instruction::kPackedSwitchSignature) {
      markPackedCaseLabels(cUnit, tabRec);
    } else if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
      markSparseCaseLabels(cUnit, tabRec);
    } else {
      LOG(FATAL) << "Invalid switch table";
    }
  }
}

//FIXME: Do we have endian issues here?

void dumpSparseSwitchTable(const u2* table)
  /*
   * 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.
   */
{
  u2 ident = table[0];
  int entries = table[1];
  int* keys = (int*)&table[2];
  int* targets = &keys[entries];
  LOG(INFO) <<  "Sparse switch table - ident:0x" << std::hex << ident
            << ", entries: " << std::dec << entries;
  for (int i = 0; i < entries; i++) {
    LOG(INFO) << "  Key[" << keys[i] << "] -> 0x" << std::hex << targets[i];
  }
}

void dumpPackedSwitchTable(const u2* table)
  /*
   * 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.
   */
{
  u2 ident = table[0];
  int* targets = (int*)&table[4];
  int entries = table[1];
  int lowKey = s4FromSwitchData(&table[2]);
  LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident
            << ", entries: " << std::dec << entries << ", lowKey: " << lowKey;
  for (int i = 0; i < entries; i++) {
    LOG(INFO) << "  Key[" << (i + lowKey) << "] -> 0x" << std::hex
              << targets[i];
  }
}


}  // namespace art
