/*
 * 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 "codegen_util.h"
#include "compiler/compiler_ir.h"
#include "ralloc_util.h"

namespace art {

/* This file contains target-independent codegen and support. */

/*
 * Load an immediate value into a fixed or temp register.  Target
 * register is clobbered, and marked in_use.
 */
LIR* Codegen::LoadConstant(CompilationUnit* cu, int r_dest, int value)
{
  if (IsTemp(cu, r_dest)) {
    Clobber(cu, r_dest);
    MarkInUse(cu, r_dest);
  }
  return LoadConstantNoClobber(cu, r_dest, value);
}

/*
 * Temporary workaround for Issue 7250540.  If we're loading a constant zero into a
 * promoted floating point register, also copy a zero into the int/ref identity of
 * that sreg.
 */
void Codegen::Workaround7250540(CompilationUnit* cu, RegLocation rl_dest, int zero_reg)
{
  if (rl_dest.fp) {
    int pmap_index = SRegToPMap(cu, rl_dest.s_reg_low);
    if (cu->promotion_map[pmap_index].fp_location == kLocPhysReg) {
      // Now, determine if this vreg is ever used as a reference.  If not, we're done.
      if (!cu->gen_bitcode) {
        // TUNING: We no longer have this info for QuickGBC - assume the worst
        bool used_as_reference = false;
        int base_vreg = SRegToVReg(cu, rl_dest.s_reg_low);
        for (int i = 0; !used_as_reference && (i < cu->num_ssa_regs); i++) {
          if (SRegToVReg(cu, cu->reg_location[i].s_reg_low) == base_vreg) {
            used_as_reference |= cu->reg_location[i].ref;
          }
        }
        if (!used_as_reference) {
          return;
        }
      }
      int temp_reg = zero_reg;
      if (temp_reg == INVALID_REG) {
        temp_reg = AllocTemp(cu);
        cu->cg->LoadConstant(cu, temp_reg, 0);
      }
      if (cu->promotion_map[pmap_index].core_location == kLocPhysReg) {
        // Promoted - just copy in a zero
        OpRegCopy(cu, cu->promotion_map[pmap_index].core_reg, temp_reg);
      } else {
        // Lives in the frame, need to store.
        StoreBaseDisp(cu, TargetReg(kSp), SRegOffset(cu, rl_dest.s_reg_low), temp_reg, kWord);
      }
      if (zero_reg == INVALID_REG) {
        FreeTemp(cu, temp_reg);
      }
    }
  }
}

/* Load a word at base + displacement.  Displacement must be word multiple */
LIR* Codegen::LoadWordDisp(CompilationUnit* cu, int rBase, int displacement, int r_dest)
{
  return LoadBaseDisp(cu, rBase, displacement, r_dest, kWord,
                      INVALID_SREG);
}

LIR* Codegen::StoreWordDisp(CompilationUnit* cu, int rBase, int displacement, int r_src)
{
  return StoreBaseDisp(cu, rBase, displacement, r_src, kWord);
}

/*
 * Load a Dalvik register into a physical register.  Take care when
 * using this routine, as it doesn't perform any bookkeeping regarding
 * register liveness.  That is the responsibility of the caller.
 */
void Codegen::LoadValueDirect(CompilationUnit* cu, RegLocation rl_src, int r_dest)
{
  rl_src = UpdateLoc(cu, rl_src);
  if (rl_src.location == kLocPhysReg) {
    OpRegCopy(cu, r_dest, rl_src.low_reg);
  } else if (IsInexpensiveConstant(cu, rl_src)) {
    LoadConstantNoClobber(cu, r_dest, ConstantValue(cu, rl_src));
  } else {
    DCHECK((rl_src.location == kLocDalvikFrame) ||
           (rl_src.location == kLocCompilerTemp));
    LoadWordDisp(cu, TargetReg(kSp), SRegOffset(cu, rl_src.s_reg_low), r_dest);
  }
}

/*
 * Similar to LoadValueDirect, but clobbers and allocates the target
 * register.  Should be used when loading to a fixed register (for example,
 * loading arguments to an out of line call.
 */
void Codegen::LoadValueDirectFixed(CompilationUnit* cu, RegLocation rl_src, int r_dest)
{
  Clobber(cu, r_dest);
  MarkInUse(cu, r_dest);
  LoadValueDirect(cu, rl_src, r_dest);
}

/*
 * Load a Dalvik register pair into a physical register[s].  Take care when
 * using this routine, as it doesn't perform any bookkeeping regarding
 * register liveness.  That is the responsibility of the caller.
 */
void Codegen::LoadValueDirectWide(CompilationUnit* cu, RegLocation rl_src, int reg_lo,
             int reg_hi)
{
  rl_src = UpdateLocWide(cu, rl_src);
  if (rl_src.location == kLocPhysReg) {
    OpRegCopyWide(cu, reg_lo, reg_hi, rl_src.low_reg, rl_src.high_reg);
  } else if (IsInexpensiveConstant(cu, rl_src)) {
    LoadConstantWide(cu, reg_lo, reg_hi, ConstantValueWide(cu, rl_src));
  } else {
    DCHECK((rl_src.location == kLocDalvikFrame) ||
           (rl_src.location == kLocCompilerTemp));
    LoadBaseDispWide(cu, TargetReg(kSp), SRegOffset(cu, rl_src.s_reg_low),
                     reg_lo, reg_hi, INVALID_SREG);
  }
}

/*
 * Similar to LoadValueDirect, but clobbers and allocates the target
 * registers.  Should be used when loading to a fixed registers (for example,
 * loading arguments to an out of line call.
 */
void Codegen::LoadValueDirectWideFixed(CompilationUnit* cu, RegLocation rl_src, int reg_lo,
                                       int reg_hi)
{
  Clobber(cu, reg_lo);
  Clobber(cu, reg_hi);
  MarkInUse(cu, reg_lo);
  MarkInUse(cu, reg_hi);
  LoadValueDirectWide(cu, rl_src, reg_lo, reg_hi);
}

RegLocation Codegen::LoadValue(CompilationUnit* cu, RegLocation rl_src, RegisterClass op_kind)
{
  rl_src = EvalLoc(cu, rl_src, op_kind, false);
  if (IsInexpensiveConstant(cu, rl_src) || rl_src.location != kLocPhysReg) {
    LoadValueDirect(cu, rl_src, rl_src.low_reg);
    rl_src.location = kLocPhysReg;
    MarkLive(cu, rl_src.low_reg, rl_src.s_reg_low);
  }
  return rl_src;
}

void Codegen::StoreValue(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src)
{
#ifndef NDEBUG
  /*
   * Sanity checking - should never try to store to the same
   * ssa name during the compilation of a single instruction
   * without an intervening ClobberSReg().
   */
  DCHECK((cu->live_sreg == INVALID_SREG) ||
         (rl_dest.s_reg_low != cu->live_sreg));
  cu->live_sreg = rl_dest.s_reg_low;
#endif
  LIR* def_start;
  LIR* def_end;
  DCHECK(!rl_dest.wide);
  DCHECK(!rl_src.wide);
  rl_src = UpdateLoc(cu, rl_src);
  rl_dest = UpdateLoc(cu, rl_dest);
  if (rl_src.location == kLocPhysReg) {
    if (IsLive(cu, rl_src.low_reg) ||
      IsPromoted(cu, rl_src.low_reg) ||
      (rl_dest.location == kLocPhysReg)) {
      // Src is live/promoted or Dest has assigned reg.
      rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false);
      OpRegCopy(cu, rl_dest.low_reg, rl_src.low_reg);
    } else {
      // Just re-assign the registers.  Dest gets Src's regs
      rl_dest.low_reg = rl_src.low_reg;
      Clobber(cu, rl_src.low_reg);
    }
  } else {
    // Load Src either into promoted Dest or temps allocated for Dest
    rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false);
    LoadValueDirect(cu, rl_src, rl_dest.low_reg);
  }

  // Dest is now live and dirty (until/if we flush it to home location)
  MarkLive(cu, rl_dest.low_reg, rl_dest.s_reg_low);
  MarkDirty(cu, rl_dest);


  ResetDefLoc(cu, rl_dest);
  if (IsDirty(cu, rl_dest.low_reg) &&
      oat_live_out(cu, rl_dest.s_reg_low)) {
    def_start = cu->last_lir_insn;
    StoreBaseDisp(cu, TargetReg(kSp), SRegOffset(cu, rl_dest.s_reg_low),
                  rl_dest.low_reg, kWord);
    MarkClean(cu, rl_dest);
    def_end = cu->last_lir_insn;
    if (!rl_dest.ref) {
      // Exclude references from store elimination
      MarkDef(cu, rl_dest, def_start, def_end);
    }
  }
}

RegLocation Codegen::LoadValueWide(CompilationUnit* cu, RegLocation rl_src, RegisterClass op_kind)
{
  DCHECK(rl_src.wide);
  rl_src = EvalLoc(cu, rl_src, op_kind, false);
  if (IsInexpensiveConstant(cu, rl_src) || rl_src.location != kLocPhysReg) {
    LoadValueDirectWide(cu, rl_src, rl_src.low_reg, rl_src.high_reg);
    rl_src.location = kLocPhysReg;
    MarkLive(cu, rl_src.low_reg, rl_src.s_reg_low);
    MarkLive(cu, rl_src.high_reg, GetSRegHi(rl_src.s_reg_low));
  }
  return rl_src;
}

void Codegen::StoreValueWide(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src)
{
#ifndef NDEBUG
  /*
   * Sanity checking - should never try to store to the same
   * ssa name during the compilation of a single instruction
   * without an intervening ClobberSReg().
   */
  DCHECK((cu->live_sreg == INVALID_SREG) ||
      (rl_dest.s_reg_low != cu->live_sreg));
  cu->live_sreg = rl_dest.s_reg_low;
#endif
  LIR* def_start;
  LIR* def_end;
  DCHECK_EQ(IsFpReg(rl_src.low_reg), IsFpReg(rl_src.high_reg));
  DCHECK(rl_dest.wide);
  DCHECK(rl_src.wide);
  if (rl_src.location == kLocPhysReg) {
    if (IsLive(cu, rl_src.low_reg) ||
        IsLive(cu, rl_src.high_reg) ||
        IsPromoted(cu, rl_src.low_reg) ||
        IsPromoted(cu, rl_src.high_reg) ||
        (rl_dest.location == kLocPhysReg)) {
      // Src is live or promoted or Dest has assigned reg.
      rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false);
      OpRegCopyWide(cu, rl_dest.low_reg, rl_dest.high_reg,
                    rl_src.low_reg, rl_src.high_reg);
    } else {
      // Just re-assign the registers.  Dest gets Src's regs
      rl_dest.low_reg = rl_src.low_reg;
      rl_dest.high_reg = rl_src.high_reg;
      Clobber(cu, rl_src.low_reg);
      Clobber(cu, rl_src.high_reg);
    }
  } else {
    // Load Src either into promoted Dest or temps allocated for Dest
    rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false);
    LoadValueDirectWide(cu, rl_src, rl_dest.low_reg, rl_dest.high_reg);
  }

  // Dest is now live and dirty (until/if we flush it to home location)
  MarkLive(cu, rl_dest.low_reg, rl_dest.s_reg_low);
  MarkLive(cu, rl_dest.high_reg, GetSRegHi(rl_dest.s_reg_low));
  MarkDirty(cu, rl_dest);
  MarkPair(cu, rl_dest.low_reg, rl_dest.high_reg);


  ResetDefLocWide(cu, rl_dest);
  if ((IsDirty(cu, rl_dest.low_reg) ||
      IsDirty(cu, rl_dest.high_reg)) &&
      (oat_live_out(cu, rl_dest.s_reg_low) ||
      oat_live_out(cu, GetSRegHi(rl_dest.s_reg_low)))) {
    def_start = cu->last_lir_insn;
    DCHECK_EQ((SRegToVReg(cu, rl_dest.s_reg_low)+1),
              SRegToVReg(cu, GetSRegHi(rl_dest.s_reg_low)));
    StoreBaseDispWide(cu, TargetReg(kSp), SRegOffset(cu, rl_dest.s_reg_low),
                      rl_dest.low_reg, rl_dest.high_reg);
    MarkClean(cu, rl_dest);
    def_end = cu->last_lir_insn;
    MarkDefWide(cu, rl_dest, def_start, def_end);
  }
}

/* Utilities to load the current Method* */
void Codegen::LoadCurrMethodDirect(CompilationUnit *cu, int r_tgt)
{
  LoadValueDirectFixed(cu, cu->method_loc, r_tgt);
}

RegLocation Codegen::LoadCurrMethod(CompilationUnit *cu)
{
  return LoadValue(cu, cu->method_loc, kCoreReg);
}

}  // namespace art
