/*
 * 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);
}

/*
 * 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);
}

RegStorage Mir2Lir::LoadCurrMethodWithHint(RegStorage r_hint) {
  // If the method is promoted to a register, return that register, otherwise load it to r_hint.
  // (Replacement for LoadCurrMethod() usually used when LockCallTemps() is in effect.)
  DCHECK(r_hint.Valid());
  RegLocation rl_method = mir_graph_->GetMethodLoc();
  if (rl_method.location == kLocPhysReg) {
    DCHECK(!IsTemp(rl_method.reg));
    return rl_method.reg;
  } else {
    LoadCurrMethodDirect(r_hint);
    return r_hint;
  }
}

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
