/*
 * 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 "mir_to_lir-inl.h"

#include "dex/compiler_ir.h"
#include "dex/mir_graph.h"
#include "invoke_type.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* Mir2Lir::LoadConstant(RegStorage r_dest, int value) {
  if (IsTemp(r_dest)) {
    Clobber(r_dest);
    MarkInUse(r_dest);
  }
  return LoadConstantNoClobber(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 Mir2Lir::Workaround7250540(RegLocation rl_dest, RegStorage zero_reg) {
  if (rl_dest.fp) {
    int pmap_index = SRegToPMap(rl_dest.s_reg_low);
    if (promotion_map_[pmap_index].fp_location == kLocPhysReg) {
      // Now, determine if this vreg is ever used as a reference.  If not, we're done.
      bool used_as_reference = false;
      int base_vreg = mir_graph_->SRegToVReg(rl_dest.s_reg_low);
      for (int i = 0; !used_as_reference && (i < mir_graph_->GetNumSSARegs()); i++) {
        if (mir_graph_->SRegToVReg(mir_graph_->reg_location_[i].s_reg_low) == base_vreg) {
          used_as_reference |= mir_graph_->reg_location_[i].ref;
        }
      }
      if (!used_as_reference) {
        return;
      }
      RegStorage temp_reg = zero_reg;
      if (!temp_reg.Valid()) {
        temp_reg = AllocTemp();
        LoadConstant(temp_reg, 0);
      }
      if (promotion_map_[pmap_index].core_location == kLocPhysReg) {
        // Promoted - just copy in a zero
        OpRegCopy(RegStorage::Solo32(promotion_map_[pmap_index].core_reg), temp_reg);
      } else {
        // Lives in the frame, need to store.
        ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
        StoreBaseDisp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), temp_reg, k32, kNotVolatile);
      }
      if (!zero_reg.Valid()) {
        FreeTemp(temp_reg);
      }
    }
  }
}

/*
 * 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 Mir2Lir::LoadValueDirect(RegLocation rl_src, RegStorage r_dest) {
  rl_src = UpdateLoc(rl_src);
  if (rl_src.location == kLocPhysReg) {
    OpRegCopy(r_dest, rl_src.reg);
  } else if (IsInexpensiveConstant(rl_src)) {
    // On 64-bit targets, will sign extend.  Make sure constant reference is always NULL.
    DCHECK(!rl_src.ref || (mir_graph_->ConstantValue(rl_src) == 0));
    LoadConstantNoClobber(r_dest, mir_graph_->ConstantValue(rl_src));
  } else {
    DCHECK((rl_src.location == kLocDalvikFrame) ||
           (rl_src.location == kLocCompilerTemp));
    ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
    if (rl_src.ref) {
      LoadRefDisp(TargetPtrReg(kSp), SRegOffset(rl_src.s_reg_low), r_dest, kNotVolatile);
    } else {
      Load32Disp(TargetPtrReg(kSp), SRegOffset(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 Mir2Lir::LoadValueDirectFixed(RegLocation rl_src, RegStorage r_dest) {
  Clobber(r_dest);
  MarkInUse(r_dest);
  LoadValueDirect(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 Mir2Lir::LoadValueDirectWide(RegLocation rl_src, RegStorage r_dest) {
  rl_src = UpdateLocWide(rl_src);
  if (rl_src.location == kLocPhysReg) {
    OpRegCopyWide(r_dest, rl_src.reg);
  } else if (IsInexpensiveConstant(rl_src)) {
    LoadConstantWide(r_dest, mir_graph_->ConstantValueWide(rl_src));
  } else {
    DCHECK((rl_src.location == kLocDalvikFrame) ||
           (rl_src.location == kLocCompilerTemp));
    ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
    LoadBaseDisp(TargetPtrReg(kSp), SRegOffset(rl_src.s_reg_low), r_dest, k64, kNotVolatile);
  }
}

/*
 * 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 Mir2Lir::LoadValueDirectWideFixed(RegLocation rl_src, RegStorage r_dest) {
  Clobber(r_dest);
  MarkInUse(r_dest);
  LoadValueDirectWide(rl_src, r_dest);
}

RegLocation Mir2Lir::LoadValue(RegLocation rl_src, RegisterClass op_kind) {
  DCHECK(!rl_src.ref || op_kind == kRefReg);
  rl_src = UpdateLoc(rl_src);
  if (rl_src.location == kLocPhysReg) {
    if (!RegClassMatches(op_kind, rl_src.reg)) {
      // Wrong register class, realloc, copy and transfer ownership.
      RegStorage new_reg = AllocTypedTemp(rl_src.fp, op_kind);
      OpRegCopy(new_reg, rl_src.reg);
      // Clobber the old regs and free it.
      Clobber(rl_src.reg);
      FreeTemp(rl_src.reg);
      // ...and mark the new one live.
      rl_src.reg = new_reg;
      MarkLive(rl_src);
    }
    return rl_src;
  }

  DCHECK_NE(rl_src.s_reg_low, INVALID_SREG);
  rl_src.reg = AllocTypedTemp(rl_src.fp, op_kind);
  LoadValueDirect(rl_src, rl_src.reg);
  rl_src.location = kLocPhysReg;
  MarkLive(rl_src);
  return rl_src;
}

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

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


  ResetDefLoc(rl_dest);
  if (IsDirty(rl_dest.reg) && LiveOut(rl_dest.s_reg_low)) {
    def_start = last_lir_insn_;
    ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
    if (rl_dest.ref) {
      StoreRefDisp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg, kNotVolatile);
    } else {
      Store32Disp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg);
    }
    MarkClean(rl_dest);
    def_end = last_lir_insn_;
    if (!rl_dest.ref) {
      // Exclude references from store elimination
      MarkDef(rl_dest, def_start, def_end);
    }
  }
}

RegLocation Mir2Lir::LoadValueWide(RegLocation rl_src, RegisterClass op_kind) {
  DCHECK(rl_src.wide);
  rl_src = UpdateLocWide(rl_src);
  if (rl_src.location == kLocPhysReg) {
    if (!RegClassMatches(op_kind, rl_src.reg)) {
      // Wrong register class, realloc, copy and transfer ownership.
      RegStorage new_regs = AllocTypedTempWide(rl_src.fp, op_kind);
      OpRegCopyWide(new_regs, rl_src.reg);
      // Clobber the old regs and free it.
      Clobber(rl_src.reg);
      FreeTemp(rl_src.reg);
      // ...and mark the new ones live.
      rl_src.reg = new_regs;
      MarkLive(rl_src);
    }
    return rl_src;
  }

  DCHECK_NE(rl_src.s_reg_low, INVALID_SREG);
  DCHECK_NE(GetSRegHi(rl_src.s_reg_low), INVALID_SREG);
  rl_src.reg = AllocTypedTempWide(rl_src.fp, op_kind);
  LoadValueDirectWide(rl_src, rl_src.reg);
  rl_src.location = kLocPhysReg;
  MarkLive(rl_src);
  return rl_src;
}

void Mir2Lir::StoreValueWide(RegLocation rl_dest, RegLocation rl_src) {
  /*
   * Sanity checking - should never try to store to the same
   * ssa name during the compilation of a single instruction
   * without an intervening ClobberSReg().
   */
  if (kIsDebugBuild) {
    DCHECK((live_sreg_ == INVALID_SREG) ||
           (rl_dest.s_reg_low != live_sreg_));
    live_sreg_ = rl_dest.s_reg_low;
  }
  LIR* def_start;
  LIR* def_end;
  DCHECK(rl_dest.wide);
  DCHECK(rl_src.wide);
  rl_src = UpdateLocWide(rl_src);
  rl_dest = UpdateLocWide(rl_dest);
  if (rl_src.location == kLocPhysReg) {
    if (IsLive(rl_src.reg) ||
        IsPromoted(rl_src.reg) ||
        (rl_dest.location == kLocPhysReg)) {
      /*
       * If src reg[s] are tied to the original Dalvik vreg via liveness or promotion, we
       * can't repurpose them.  Similarly, if the dest reg[s] are tied to Dalvik vregs via
       * promotion, we can't just re-assign.  In these cases, we have to copy.
       */
      rl_dest = EvalLoc(rl_dest, kAnyReg, false);
      OpRegCopyWide(rl_dest.reg, rl_src.reg);
    } else {
      // Just re-assign the registers.  Dest gets Src's regs
      rl_dest.reg = rl_src.reg;
      Clobber(rl_src.reg);
    }
  } else {
    // Load Src either into promoted Dest or temps allocated for Dest
    rl_dest = EvalLoc(rl_dest, kAnyReg, false);
    LoadValueDirectWide(rl_src, rl_dest.reg);
  }

  // Dest is now live and dirty (until/if we flush it to home location)
  MarkLive(rl_dest);
  MarkWide(rl_dest.reg);
  MarkDirty(rl_dest);

  ResetDefLocWide(rl_dest);
  if (IsDirty(rl_dest.reg) && (LiveOut(rl_dest.s_reg_low) ||
      LiveOut(GetSRegHi(rl_dest.s_reg_low)))) {
    def_start = last_lir_insn_;
    DCHECK_EQ((mir_graph_->SRegToVReg(rl_dest.s_reg_low)+1),
              mir_graph_->SRegToVReg(GetSRegHi(rl_dest.s_reg_low)));
    ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
    StoreBaseDisp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg, k64, kNotVolatile);
    MarkClean(rl_dest);
    def_end = last_lir_insn_;
    MarkDefWide(rl_dest, def_start, def_end);
  }
}

void Mir2Lir::StoreFinalValue(RegLocation rl_dest, RegLocation rl_src) {
  DCHECK_EQ(rl_src.location, kLocPhysReg);

  if (rl_dest.location == kLocPhysReg) {
    OpRegCopy(rl_dest.reg, rl_src.reg);
  } else {
    // Just re-assign the register.  Dest gets Src's reg.
    rl_dest.location = kLocPhysReg;
    rl_dest.reg = rl_src.reg;
    Clobber(rl_src.reg);
  }

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


  ResetDefLoc(rl_dest);
  if (IsDirty(rl_dest.reg) && LiveOut(rl_dest.s_reg_low)) {
    LIR *def_start = last_lir_insn_;
    ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
    Store32Disp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg);
    MarkClean(rl_dest);
    LIR *def_end = last_lir_insn_;
    if (!rl_dest.ref) {
      // Exclude references from store elimination
      MarkDef(rl_dest, def_start, def_end);
    }
  }
}

void Mir2Lir::StoreFinalValueWide(RegLocation rl_dest, RegLocation rl_src) {
  DCHECK(rl_dest.wide);
  DCHECK(rl_src.wide);
  DCHECK_EQ(rl_src.location, kLocPhysReg);

  if (rl_dest.location == kLocPhysReg) {
    OpRegCopyWide(rl_dest.reg, rl_src.reg);
  } else {
    // Just re-assign the registers.  Dest gets Src's regs.
    rl_dest.location = kLocPhysReg;
    rl_dest.reg = rl_src.reg;
    Clobber(rl_src.reg);
  }

  // Dest is now live and dirty (until/if we flush it to home location).
  MarkLive(rl_dest);
  MarkWide(rl_dest.reg);
  MarkDirty(rl_dest);

  ResetDefLocWide(rl_dest);
  if (IsDirty(rl_dest.reg) && (LiveOut(rl_dest.s_reg_low) ||
      LiveOut(GetSRegHi(rl_dest.s_reg_low)))) {
    LIR *def_start = last_lir_insn_;
    DCHECK_EQ((mir_graph_->SRegToVReg(rl_dest.s_reg_low)+1),
              mir_graph_->SRegToVReg(GetSRegHi(rl_dest.s_reg_low)));
    ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
    StoreBaseDisp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg, k64, kNotVolatile);
    MarkClean(rl_dest);
    LIR *def_end = last_lir_insn_;
    MarkDefWide(rl_dest, def_start, def_end);
  }
}

/* Utilities to load the current Method* */
void Mir2Lir::LoadCurrMethodDirect(RegStorage r_tgt) {
  LoadValueDirectFixed(mir_graph_->GetMethodLoc(), r_tgt);
}

RegLocation Mir2Lir::LoadCurrMethod() {
  return LoadValue(mir_graph_->GetMethodLoc(), kRefReg);
}

RegLocation Mir2Lir::ForceTemp(RegLocation loc) {
  DCHECK(!loc.wide);
  DCHECK(loc.location == kLocPhysReg);
  DCHECK(!loc.reg.IsFloat());
  if (IsTemp(loc.reg)) {
    Clobber(loc.reg);
  } else {
    RegStorage temp_low = AllocTemp();
    OpRegCopy(temp_low, loc.reg);
    loc.reg = temp_low;
  }

  // Ensure that this doesn't represent the original SR any more.
  loc.s_reg_low = INVALID_SREG;
  return loc;
}

RegLocation Mir2Lir::ForceTempWide(RegLocation loc) {
  DCHECK(loc.wide);
  DCHECK(loc.location == kLocPhysReg);
  DCHECK(!loc.reg.IsFloat());

  if (!loc.reg.IsPair()) {
    if (IsTemp(loc.reg)) {
      Clobber(loc.reg);
    } else {
      RegStorage temp = AllocTempWide();
      OpRegCopy(temp, loc.reg);
      loc.reg = temp;
    }
  } else {
    if (IsTemp(loc.reg.GetLow())) {
      Clobber(loc.reg.GetLow());
    } else {
      RegStorage temp_low = AllocTemp();
      OpRegCopy(temp_low, loc.reg.GetLow());
      loc.reg.SetLowReg(temp_low.GetReg());
    }
    if (IsTemp(loc.reg.GetHigh())) {
      Clobber(loc.reg.GetHigh());
    } else {
      RegStorage temp_high = AllocTemp();
      OpRegCopy(temp_high, loc.reg.GetHigh());
      loc.reg.SetHighReg(temp_high.GetReg());
    }
  }

  // Ensure that this doesn't represent the original SR any more.
  loc.s_reg_low = INVALID_SREG;
  return loc;
}

}  // namespace art
